def driver_name_filter(self, driver_name=None): """Filter names of driver to search selected on config list Keyword Arguments: driver_name {str} -- driver_name_format is {driver_name}{arch}{os} (default: {None}) Raises: CoreException -- driver_name param is None CoreException -- driver_name not in Returns: str -- name of driver (example: chromedriver_32.exe) """ driver_name_format = '{}{}{}' if driver_name is None: raise CoreException(message='driver_name received it\'s None') driver_name_format = driver_name_format.format(driver_name, '{}', '{}') if self.IS_WIN: driver_name_format = driver_name_format.format('{}', '.exe') else: driver_name_format = driver_name_format.format('{}', '') if self.IS_64BITS: driver_name_format = driver_name_format.format('driver_64') else: driver_name_format = driver_name_format.format('driver_32') for name in self.bot_config.config['drivers_names']: if name.endswith(driver_name_format): return driver_name_format raise CoreException( message='Driver name not found {}'.format(driver_name_format))
def find_elements(self, selector, locator=By.CSS_SELECTOR): """Just divided execution ways for search web elements throught selenium Arguments: selector {str} -- string selector used to locate one or more elements Keyword Arguments: locator {By} -- locator strategy used to find WebElement selector (default: {By.CSS_SELECTOR}) Raises: CoreException -- If locator is None CoreException -- Element selector+locator strategy raises selenium NoSuchElementException Returns: list(WebElement) -- selenium representation for a list of web elements """ method = self.method_name() msg = "Locator not selected at find_element, selector={}".format( selector) if locator is None: raise CoreException(msg, info_bot={"method": method}) try: elements = self.driver.find_elements(locator, selector) if len(elements) == 0: raise CoreException("0 elements found", info_bot={"method": method}) return elements except NoSuchElementException as err: info_bot = {"err": err, "method": method} raise CoreException(info_bot=info_bot)
def driver_name_filter(self, driver_name=None): """Filter names of driver to search selected on config list Keyword Arguments: driver_name {str} -- driver_name_format is {driver_name}{arch}{os} (default: {None}) Raises: CoreException -- driver_name param is None CoreException -- driver_name not in Returns: str -- name of driver (example: chromedriver_32.exe) """ driver_name_format = "{}{}{}" if driver_name is None: raise CoreException("driver_name received it\'s None") driver_name_format = driver_name_format.format(driver_name, "{}", "{}") if self.IS_WIN: driver_name_format = driver_name_format.format("{}", ".exe") else: driver_name_format = driver_name_format.format("{}", "") if self.IS_64BITS: driver_name_format = driver_name_format.format("driver_64") else: driver_name_format = driver_name_format.format("driver_32") for name in self.settings.get("drivers_names"): if name.endswith(driver_name_format): return driver_name_format msg = "Driver name not found {}".format(driver_name_format) raise CoreException(msg, log=self.log)
def find_elements(self, selector, locator=By.CSS_SELECTOR): """Just divided execution ways for search web elements throught selenium Arguments: selector {str} -- string selector used to locate one or more elements Keyword Arguments: locator {By} -- locator strategy used to find WebElement selector (default: {By.CSS_SELECTOR}) Raises: CoreException -- If locator is None CoreException -- Element selector+locator strategy raises selenium NoSuchElementException Returns: list(WebElement) -- selenium representation for a list of web elements """ msg = "Locator not selected at find_element, selector={}".format( selector) msg_err = "Error at find_elements: selector={}".format(selector) if locator is None: raise CoreException(message=msg) try: return self.driver.find_elements(locator, selector) except NoSuchElementException as err: raise CoreException(err, message=msg_err)
def add_cookie(self, cookie_dict): """Adds a cookie to your current session. Args: cookie_dict: A dictionary object, with required keys - "name" and "value" optional keys - "path", "domain", "secure", "expiry" Usage: driver.add_cookie({ "name" : "foo", "value" : "bar"}) driver.add_cookie({ 'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True, 'domain': None}) """ method = self.method_name() valid_keys = ["name", "value"] if cookie_dict is None: raise CoreException("Can't add None cookie") for key in valid_keys: if cookie_dict.get(key) is None: msg = "Can't add new cookie without '{}'".format(key) raise CoreException(msg) try: return self.driver.add_cookie(cookie_dict) except WebDriverException as err: bot_info = {"err": err, "method": method} raise CoreException(bot_info=bot_info)
def find_element(self, selector, locator=By.CSS_SELECTOR): """Just divided execution ways for search web element throught selenium Arguments: selector {str} -- string selector used to locate one element or first obtained Keyword Arguments: locator {By} -- locator strategy used to find WebElement selector (default: {By.CSS_SELECTOR}) Raises: CoreException -- If locator is None CoreException -- Element selector+locator strategy raises selenium NoSuchElementException Returns: WebElement -- selenium representation for a web element """ method = self.method_name() msg = "Locator not selected at find_element, selector={}".format( selector) if locator is None: raise CoreException(msg) try: return self.driver.find_element(locator, selector) except NoSuchElementException as err: info_bot = {"err": err, "method": method} raise CoreException(info_bot=info_bot)
def ele_wait_visible(self, element, timeout=0): """Wait for visible condition element, returns self""" if element is None: raise CoreException("Can't wait visible if element is None") driver_wait = WebDriverWait(self.driver, timeout) try: element = driver_wait.until(EC.visibility_of(element)) except Exception: raise CoreException("Fails at wait for visible element") return element
def ele_wait_invisible(self, selector, locator=By.CSS_SELECTOR, timeout=0): """Wait for invisible element (display:none), returns element""" if selector is None: raise CoreException( "Can't wait invisible element if None selector given") locator_tuple = (locator, selector) driver_wait = WebDriverWait(self.driver, timeout) try: element = driver_wait.until( EC.invisibility_of_element_located(locator_tuple)) except Exception: raise CoreException("Fails at wait for invisible element") return element
def mode_local(self, browser_name='chrome'): """Open new brower on local mode Raises: CoreException -- driver_name on config JSON file is not valid value """ driver_name = self.driver_name_filter(driver_name=browser_name) # TODO: Need it ? maybe a test for this ? self.curr_driver_path = os.path.abspath("{}/{}".format( self.settings.get('drivers_path'), driver_name)) sys.path.append(self.curr_driver_path) self.log.debug('Starting browser with mode : LOCAL ...') try: self.curr_driver = { "chrome": self.get_driver_chrome(), "firefox": self.get_driver_firefox(), "iexplorer": self.get_driver_iexplorer(), "edge": self.get_driver_edge(), }[browser_name] except KeyError: msg = ("config file error, SECTION=bot, KEY=browser isn't " "valid value: {}".format(browser_name)) raise CoreException(msg, log=self.log) self.log.info('Started browser with mode : LOCAL OK')
def get_options(self, browser_name='chrome', headless_enabled=False): """Instance Options class from selenium and return it Keyword Arguments: browser_name {str} -- name of a valid browser name for selenium (default: {'chrome'}) headless_enabled {bool} -- allow to configure --headless param (default: {False}) Raises: CoreException -- if name of browser isn't supported Returns: [Options] -- Options inherit class instanced for one browser """ options = None msg_not_conf = ("get_options | : doesn't have configurations" " for browser='{}'".format(browser_name)) try: options = { "chrome": ChromeOptions(), "firefox": FirefoxOptions(), }[browser_name] if headless_enabled: options.add_argument("--headless") except KeyError: if browser_name in self.BROWSERS_WITHOUT_OPTIONS: self.log.debug(msg_not_conf) else: raise CoreException("Bad browser selected", log=self.log) return options
def get_capabilities(self, browser_name='chrome'): """Instance DesiredCapabilities class from selenium and return it Keyword Arguments: browser_name {str} -- name of a valid browser name for selenium (default: {'chrome'}) Raises: CoreException -- if name of browser isn't supported Returns: [DesiredCapabilities] -- DesiredCapabilities inherit class instanced for one browser """ capabilities = None try: capabilities = { "chrome": DesiredCapabilities.CHROME.copy(), "firefox": DesiredCapabilities.FIREFOX.copy(), "iexplorer": DesiredCapabilities.INTERNETEXPLORER.copy(), "edge": DesiredCapabilities.EDGE.copy(), }[browser_name] capabilities['acceptInsecureCerts'] = True except KeyError: msg = 'Bad browser selected at load options' raise CoreException(msg, log=self.log) return capabilities
def find_element_wait(self, selector, locator=By.CSS_SELECTOR, driver_wait=None): """Search element using WebDriverWait class and ElementConditions presence_of_element_located Arguments: selector {str} -- string selector used to locate one element or first obtained Keyword Arguments: locator {By} -- locator strategy used to find WebElement selector (default: {By.CSS_SELECTOR}) driver_wait {WebDriverWait} -- driver that supports ExpectedConditions methods (default: {None}) Raises: CoreException -- if NavBase instanced without driver_wait Returns: WebElement -- element through selenium WebDriverWait class """ if driver_wait is None and self.driver_wait is None: raise CoreException(message='Nav instanced without driver_wait') if driver_wait is None: driver_wait = self.driver_wait return driver_wait.until( EC.presence_of_element_located((locator, selector)))
def __init__(self, bot_config): """Create new Bot browser based on options object what can be (help for each option can be found on settings.json) Arguments: bot_config {BotConfig} -- object containing configuration for new bot instance Raises: CoreException -- Fail at instance LoggerManager class CoreException -- bot_config param is None CoreException -- bot_config.mode is not in [local, remote] """ if bot_config is None: raise CoreException( message=("BotBase configuration can't be none: bad bot_config" " provided")) self.bot_config = bot_config self.logger_manager = bot_config.logger_manager self.log = self.bot_config.log if self.bot_config.config['mode'] == 'local': self.mode_local() elif self.bot_config.config['mode'] == 'remote': self.mode_remote() # else: handled at BotConfig self.curr_driver_wait = WebDriverWait(self.curr_driver, 10) self.navigation = NavBase(self.curr_driver, self.log, driver_wait=self.curr_driver_wait)
def mode_remote(self): """Open new brower on remote mode Raises: CoreException -- browser name is not in valid values list """ browser_name = self.bot_config.config['browser'] url_hub = self.bot_config.config['url_hub'] self.log.debug('Starting browser with mode : REMOTE ...') if browser_name == 'firefox': self.curr_caps = DesiredCapabilities.FIREFOX.copy() elif browser_name == 'chrome': self.curr_caps = DesiredCapabilities.CHROME.copy() elif browser_name == 'iexplorer': self.curr_caps = DesiredCapabilities.INTERNETEXPLORER.copy() elif browser_name == 'phantomjs': self.curr_caps = DesiredCapabilities.PHANTOMJS.copy() elif browser_name == 'edge': self.curr_caps = DesiredCapabilities.EDGE.copy() elif browser_name == 'opera': self.curr_caps = DesiredCapabilities.OPERA.copy() else: raise CoreException(message='Bad browser selected') self.curr_driver = RemoteWebDriver(command_executor=url_hub, desired_capabilities=self.curr_caps) self.log.info('Started browser with mode : REMOTE OK')
def __settings_parse__(self, **kwargs): """Allow to parse settings dict from instance kwargs updating just valid keys with default values if it's required """ self.bot.log.debug(MSG.CB_SETTINGS_LOADING) self._selector = kwargs.get("selector") self._name = kwargs.get("name") self._locator = kwargs.get("locator") self._on_instance_search = kwargs.get("on_instance_search") self._auto_reload = kwargs.get("auto_reload") self._element = kwargs.get("element") # validate params if self._selector is None or self._selector == '': msg = "ctl | Selector it's required to use instance" raise CoreException(msg, info_bot=self._info_bot) if self._name is None: self._name = "UNNAMED" if self._locator is None: self._locator = By.CSS_SELECTOR if self._on_instance_search is None: self._on_instance_search = False if self._auto_reload is None: self._auto_reload = True settings = { "name": self._name, "locator": self._locator, "selector": self._selector, "on_instance_search": self._on_instance_search, "auto_reload": self._auto_reload, } self.bot.log.debug(MSG.CB_SETTINGS_LOADED) return settings
def __init__(self, bot, **kwargs): """Initialize an instance of ControlBase Arguments: bot {BotBase} -- BotBase instance """ if not bot or not isinstance(bot, BotBase): raise CoreException("Bad param 'bot'") # instance minimal data self._bot = bot self._name = None self._locator = None self._selector = None self._element = None self._on_instance_search = None self._auto_reload = None # __search__, step 2 self._text = None self._id = None # Raises self._info_bot = {} self._bot.log.debug( "ctl | Generating instance of type {}...".format( self.__class__.__name__)) self.__load__(**kwargs)
def get_driver_wait(self, driver_wait=None): """Allow to obatin an instance of WebDriverWait""" if driver_wait is None and self.driver_wait is None: raise CoreException("Nav instanced without driver_wait") if driver_wait is None: driver_wait = self.driver_wait return driver_wait
def ele_text(self, element, on_screen=True): """Get element content text. If the isDisplayed() method can sometimes trip over when the element is not really hidden but outside the viewport get_text() returns an empty string for such an element. Keyword Arguments: on_screen {bool} -- allow to obtain text if element it not displayed to this element before read text (default: {True}) Returns: str -- Return element content text (innerText property) """ method = self.method_name() if on_screen: text = str(element.text) else: text = self.ele_attribute(element, 'innerText') self.log.debug("text obtained from innerText") if self.ele_is_displayed(element): msg = ("on_screen param must use when" "element it's not displayed") raise CoreException(msg, info_bot={"method": method}) return text
def get_log(self, log_name='browser', raises=False): """Get selenium log by name, this depends of driver mode and browser what it's using each time Keyword Arguments: log_name {str} -- get log type lanes (default: {'browser'}) Raises: CoreException -- if log_name value not in list of valid values : browser, driver, client, server Returns: list() -- list of messages typed on a log_name """ method = self.method_name() try: return { 'browser': self.driver.get_log, 'driver': self.driver.get_log, 'client': self.driver.get_log, 'server': self.driver.get_log, }[log_name](log_name) except (KeyError, WebDriverException) as err: if isinstance(err, KeyError): raise CoreException("Can't use not valid value to get log", info_bot={ "err": err, "method": method }) self.log.debug(("nav | get_log: Selenium, not all drivers will" " be handled by them with all optionsvalues")) self.log.warning("nav | get_log: log_name={}, err={}".format( log_name, err.msg)) return list()
def _load(self): self.log = Log(log_path=self.settings.get('log_output_file'), log_name=self.settings.get('log_name'), log_level=self.settings.get('log_level')) required_keys = [ 'mode', 'browser', 'options', 'url_hub', 'drivers_path', 'drivers_names', 'log_name', 'log_output_file', 'log_level', ] for setting in self.settings.keys(): if setting not in required_keys: msg = ("Key for config isn't valid for" " key='{}'").format(setting) raise CoreException(msg, log=self.log) # Configure browser settings browser_name = self.settings.get('browser') headless_enabled = self.settings.get('options').get('headless') # Instance selenium settings classes self.curr_caps = self.get_capabilities(browser_name=browser_name) self.curr_options = self.get_options(browser_name=browser_name, headless_enabled=headless_enabled) # Open browser based on mode from settings.json if self.settings.get('mode') == 'local': self.mode_local(browser_name=browser_name) elif self.settings.get('mode') == 'remote': self.mode_remote(browser_name=browser_name) else: msg = "Bad mode selected, mode={}".format( self.settings.get('mode')) raise CoreException(msg, log=self.log) # Instance all needed for BotBase instance self.curr_driver_wait = WebDriverWait(self.curr_driver, 10) self.curr_driver_actions = ActionChains(self.curr_driver) self.curr_driver_touch = TouchActions(self.curr_driver) self.navigation = NavBase(self.curr_driver, self.log, driver_wait=self.curr_driver_wait, driver_actions=self.curr_driver_actions, driver_touch=self.curr_driver_touch)
def __init__(self, name, strict_type, severity): """Class to allows include validation checks when loading elements using qacode library through selenium core Arguments: strict_type {StrictType} -- type of rule severity {StrictSeverity} -- severity of rule (for logging messages) """ if name is None: raise CoreException(message="bad param 'name' can't be None") if isinstance(name, (HtmlTag, HtmlAttr, CssProperty)): self.name = name.value else: self.name = name.lower() if not isinstance(strict_type, StrictType): raise CoreException( message="bad param 'strict_type' isn't instance of StrictType") self.strict_type = strict_type if not isinstance(severity, StrictSeverity): raise CoreException( message="bad param 'severity' isnt instance of StrictSeverity") self.severity = severity if strict_type == StrictType.TAG: if HtmlTag.has_tag(self.name): self.enum_type = HtmlTag(self.name) elif strict_type == StrictType.HTML_ATTR: if HtmlAttr.has_attr(self.name): self.enum_type = HtmlAttr(self.name) elif strict_type == StrictType.CSS_PROP: if CssProperty.has_css_property(self.name): self.enum_type = CssProperty(self.name) elif strict_type == StrictType.JS_EVENT: raise NotImplementedError("Open an issue on github if raise here") elif strict_type == StrictType.BEHAVIOUR: raise NotImplementedError("Open an issue on github if raise here") elif strict_type == StrictType.USABILITY: raise NotImplementedError("Open an issue on github if raise here") elif strict_type == StrictType.SEO: raise NotImplementedError("Open an issue on github if raise here") else: raise CoreException( message="bad param 'strict_type', invalid value")
def find_element_children(self, element, child_selector, locator=By.CSS_SELECTOR): """TODO: doc method""" method = self.method_name() if element is None or not isinstance(element, WebElement): raise CoreException("Cant find children if not element found") try: return element.find_elements(locator, child_selector) except (NoSuchElementException, StaleElementReferenceException) as err: # at Java lang exist 1 expected condition # named : visibilityOfNestedElementsLocatedBy # doc : https://selenium-python.readthedocs.io/waits.html # maybe must exist at python too # then, create and use new method named: find_element_child_wait() # raise NotImplementedError("TODO:open an issue at github please") info_bot = {"err": err, "method": method} raise CoreException(info_bot=info_bot)
def ele_attribute(self, element, attr_name): """Returns tuple with (attr, value) if founds This method will first try to return the value of a property with the given name. If a property with that name doesn't exist, it returns the value of the attribute with the same name. If there's no attribute with that name, None is returned. """ value = element.get_attribute(attr_name) if value is None or value == attr_name: raise CoreException( message="Attr '{}' not found".format(attr_name)) return value
def ele_wait_value(self, selector, value, locator=By.CSS_SELECTOR, timeout=0): """Wait if the given value is present in the specified element""" locator_tuple = (locator, selector) driver_wait = WebDriverWait(self.driver, timeout) try: return driver_wait.until( EC.text_to_be_present_in_element_value(locator_tuple, value)) except Exception: raise CoreException("Fails at wait for element value")
def ele_attribute(self, element, attr_name): """Returns tuple with (attr, value) if founds This method will first try to return the value of a property with the given name. If a property with that name doesn't exist, it returns the value of the attribute with the same name. If there's no attribute with that name, None is returned. """ method = self.method_name() value = str(element.get_attribute(attr_name)) if value is None or value == attr_name: msg = "Attr '{}' not found".format(attr_name) raise CoreException(msg, info_bot={"method": method}) return value
def mode_local(self): """Open new brower on local mode Raises: CoreException -- driver_name on config JSON file is not valid value """ browser_name = self.bot_config.config['browser'] driver_name = self.driver_name_filter(driver_name=browser_name) self.curr_driver_path = os.path.abspath("{}/{}".format( self.bot_config.config['drivers_path'], driver_name)) # add to path before to open sys.path.append(self.curr_driver_path) self.log.debug('Starting browser with mode : LOCAL ...') if browser_name == "chrome": self.curr_caps = DesiredCapabilities.CHROME.copy() self.curr_driver = WebDriver.Chrome( executable_path=self.curr_driver_path, desired_capabilities=self.curr_caps) elif browser_name == "firefox": self.curr_caps = DesiredCapabilities.FIREFOX.copy() self.curr_driver = WebDriver.Firefox( executable_path=self.curr_driver_path, capabilities=self.curr_caps) elif browser_name == "iexplorer": self.curr_caps = DesiredCapabilities.INTERNETEXPLORER.copy() self.curr_driver = WebDriver.Ie( executable_path=self.curr_driver_path, capabilities=self.curr_caps) elif browser_name == "edge": self.curr_caps = DesiredCapabilities.EDGE.copy() self.curr_driver = WebDriver.Edge( executable_path=self.curr_driver_path, capabilities=self.curr_caps) elif browser_name == "phantomjs": self.curr_caps = DesiredCapabilities.PHANTOMJS.copy() self.curr_driver = WebDriver.PhantomJS( executable_path=self.curr_driver_path, desired_capabilities=self.curr_caps) elif browser_name == "opera": self.curr_caps = DesiredCapabilities.OPERA.copy() self.curr_driver = WebDriver.Opera( executable_path=self.curr_driver_path, desired_capabilities=self.curr_caps) else: raise CoreException( message=("config file error, SECTION=bot, KEY=browser isn't " "valid value: {}".format(browser_name)), log=self.log) self.log.info('Started browser with mode : REMOTE OK')
def get_current_url(self): """Return current url from opened bot Raises: CoreException -- if can't obtains url with this selenium driver Returns: str -- string representation of current driver url """ msg = "Failed at obtain selenium driver property 'current_url'" try: return self.driver.current_url except WebDriverException: raise CoreException(msg)
def ele_write(self, element, text=None): """ Over element perform send_keys , if not sended text, then will write empty over element :param element: WebElement :return: None """ if not isinstance(element, WebElement): raise CoreException( "Param 'locator' it's not instance of WebElement class") if text is not None: element.send_keys(text) else: # it's neccessary because some fields shows validation message and # color after try to send empty message element.send_keys()
def ele_write(self, element, text=None): """ Over element perform send_keys , if not sended text, then will write empty over element :param element: WebElement :return: None """ method = self.method_name() if not isinstance(element, WebElement): msg = "Param 'element' it's not WebElement" raise CoreException(msg, info_bot={"method": method}) if text is not None: element.send_keys(text) else: # it's neccessary because some fields shows validation message and # color after try to send empty message element.send_keys()
def __init__(self, log=None, url_api=None, dev_key=None): """Instance testlink api and save as self.conn property Keyword Arguments: logger_manager {Log} -- Class used for logging, raise if None obtained (default: None) url_api {str} -- url to TestlinkAPI (default: None) dev_key {str} -- developerKey for TestlinkAPI (default: None) Raises: CoreException -- If Log it's None """ if log is None: raise CoreException("Testlink log can\'t be None") self.log = log # connect with success params self.conn = self.connect() # verify content exist self.load()