Source code for pytest_splunk_addon_ui_smartx.components.controls.single_select

#
# Copyright 2023 Splunk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import time
from time import sleep

from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

from ..base_component import Selector
from .base_control import BaseControl


[docs]class SingleSelect(BaseControl): """ Entity-Component: SingleSelect A dropdown which can select only one value """ def __init__(self, browser, container, searchable=True, allow_new_values=False): """ :param browser: The selenium webdriver :param container: The locator of the container where the control is located in. :param searchable: Boolean indicating if the dropdown provides filter or not. :param allow_new_values: Boolean indicating if the dropdown allows for user entered custom values excluding predefined list. """ super().__init__(browser, container) self.searchable = searchable # Component is ComboBox in case of True self.allow_new_values = allow_new_values self.container = container self.elements.update( { "internal_container": Selector( select=container.select + " .dropdownBox" ), "dropdown": Selector(select=container.select + " .dropdownBox"), "combobox": Selector( select=container.select + ' [data-test="combo-box"]' ), "selected": Selector( select=container.select + ' [data-test="textbox"]' ), "cancel_selected": Selector( select=container.select + ' [data-test="clear"]' ), } ) if not self.searchable and self.allow_new_values: raise ValueError( "Invalid combination of values for searchable and allow_new_values flags" )
[docs] def select(self, value, open_dropdown=True): """ Selects the value within the select dropdown :param value: the value to select :param open_dropdown: Whether or not the dropdown should be opened :return: Bool if successful in selection, else raises an error """ if open_dropdown: self.wait_to_be_clickable("dropdown") self.dropdown.click() if self.allow_new_values: if self.get_value(): self.cancel_selected.click() popoverid = "#" + self.combobox.get_attribute("data-test-popover-id") else: popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"values": Selector(select=popoverid + ' [data-test="option"]')} ) for each in self.get_elements("values"): if each.text.strip().lower() == value.lower(): each.click() self.wait_for("internal_container") sleep(0.25) return True else: raise ValueError("{} not found in select list".format(value))
[docs] def search(self, value, open_dropdown=True): """ search with the singleselect input :param value: string value to search :assert: Asserts whether or not the single select is seachable """ assert self.searchable, "Can not search, as the Singleselect is not searchable" if open_dropdown: self.wait_to_be_clickable("dropdown") self.dropdown.click() if self.searchable: if self.allow_new_values: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) else: popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) # DEBUG: maybe we have to click the select button self.input.send_keys(value)
[docs] def search_get_list(self, value): """ search with the singleselect input and return the list :param value: string value to search :returns: list of values """ if self.searchable: if self.allow_new_values: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) else: self.dropdown.click() popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) # as the dropdown is already open we dont try to open it self.search(value, open_dropdown=False) if self.allow_new_values: searched_values = list(self._list_visible_values()) else: self.wait_for_search_list() searched_values = list(self._list_visible_values(open_dropdown=False)) self.input.send_keys(Keys.ESCAPE) self.wait_for("container") return searched_values
def _list_visible_values(self, open_dropdown=True): """ Gets list of values which are visible. Used while filtering :param open_dropdown: Whether or not the dropdown should be opened :returns: List of the values that are visible """ if open_dropdown: self.dropdown.click() if self.allow_new_values: popoverid = "#" + self.combobox.get_attribute("data-test-popover-id") self.elements.update( {"values": Selector(select=popoverid + ' [data-test="option"]')} ) else: popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( { "values": Selector( select=popoverid + ' [data-test="option"]:not([data-test-selected="true"]) [data-test="label"]' ) } ) for each in self.get_elements("values"): yield each.get_attribute("textContent")
[docs] def get_value(self): """ Gets the selected value :return: The selected value's text, or returns false if unsuccessful """ if self.allow_new_values: # ComboBox do not support label return self.selected.get_attribute("value") else: if self.dropdown.get_attribute( "data-test-loading" ) == "false" and self.dropdown.get_attribute("data-test-value"): return self.dropdown.get_attribute("label") else: return False
[docs] def get_placeholder_value(self): """ get placeholder value from the single select """ if self.searchable: if self.allow_new_values: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) else: self.dropdown.click() popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) return self.input.get_attribute("placeholder").strip()
[docs] def cancel_selected_value(self): """ Cancels the currently selected value in the SingleSelect :return: Bool whether or not canceling the selected item was successful, else raises a error """ sleep(1) self.dropdown.click() self.wait_to_be_clickable("cancel_selected") self.cancel_selected.click() return True
[docs] def list_of_values(self): """ Gets the list of value from the Single Select :returns: list of options avaialble within the single select """ selected_val = self.get_value() sleep(1) self.dropdown.click() first_element = None list_of_values = [] if self.allow_new_values: if self.searchable: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) popoverid = "#" + self.combobox.get_attribute("data-test-popover-id") else: popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") if self.searchable: self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) self.elements.update( {"values": Selector(select=popoverid + ' [data-test="option"]')} ) for each in self.get_elements("values"): if not first_element: first_element = each list_of_values.append(each.text.strip()) if selected_val and not self.allow_new_values: # as the dropdown is already open we dont try to open it self.select(selected_val, open_dropdown=False) elif self.searchable: self.input.send_keys(Keys.ESCAPE) elif first_element: self.select(first_element.text.strip(), open_dropdown=False) self.wait_for("internal_container") return list_of_values
[docs] def get_single_value(self): """ Return one value from Single Select """ selected_val = self.get_value() first_element = None self.wait_to_be_clickable("dropdown") self.dropdown.click() if self.allow_new_values: if self.searchable: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) popoverid = "#" + self.combobox.get_attribute("data-test-popover-id") self.elements.update( { "values": Selector( select=popoverid + ' [data-test="option"]:not([data-test-selected="true"]) [data-test="label"]' ) } ) else: if self.searchable: popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"values": Selector(select=popoverid + ' [data-test="option"]')} ) single_element = self.get_element("values") if selected_val and not self.allow_new_values: # as the dropdown is already open we dont try to open it self.select(selected_val, open_dropdown=False) elif self.searchable: self.input.send_keys(Keys.ESCAPE) else: self.select(single_element.text.strip(), open_dropdown=False) self.wait_for("internal_container") return single_element
[docs] def get_list_count(self): """ Gets the total count of the SingleSelect list :return: Int the count of the options within the Single Select """ return len(list(self.list_of_values()))
[docs] def wait_for_values(self): """ Wait for dynamic values to load in SingleSelect """ def _wait_for_values(driver): return self.get_single_value() self.wait_for(_wait_for_values, msg="No values found in SingleSelect")
[docs] def wait_for_search_list(self): """ Wait for SingleSelect search to populate """ def _wait_for_search_list(driver): return len(list(self._list_visible_values(open_dropdown=False))) > 0 self.wait_for( _wait_for_search_list, msg="No values found in SingleSelect search" )
[docs] def is_editable(self): """ Returns True if the Textbox is editable, False otherwise """ if self.searchable: if self.allow_new_values: self.elements.update( { "input": Selector( select=self.container.select + ' [data-test="textbox"]' ) } ) else: self.dropdown.click() popoverid = "#" + self.dropdown.get_attribute("data-test-popover-id") self.elements.update( {"input": Selector(select=popoverid + ' [data-test="textbox"]')} ) return not bool( self.input.get_attribute("readonly") or self.input.get_attribute("readOnly") or self.input.get_attribute("disabled") )