def _resolve_main(self): # only applies when user is specifying a directory. # need to poll through the test directory allowed_mains = ( os.path.expanduser( os.path.join(self._test_file, "steps", "main.yml")), os.path.expanduser( os.path.join(self._test_file, "steps", "main.yaml")), os.path.expanduser( os.path.join(self._test_file, "steps", "main.json")), ) number_of_mains = 0 for allowed_main in allowed_mains: if os.path.exists(allowed_main) and os.path.isfile(allowed_main): main_file = allowed_main number_of_mains += 1 if number_of_mains > 1: raise DysonError( "There are more than one main files in %s. Only one is allowed" ) elif number_of_mains == 0: raise DysonError( "There are no steps to run in directory %s. A main file must exist" % self._test_file) else: return main_file
def run(self, webdriver, params): if isinstance(params, dict): if params['url']: return webdriver.get(params['url']) else: raise DysonError("You need to specify a valid URL to go to") else: raise DysonError("Key \"url\" is required")
def run(self): super(TestCLI, self).run() for test in self.args: if not os.path.exists(test): raise DysonError("Test file %s does not exist" % test) dataloader = DataLoader({"basedir": self.options.base_dir}) # initialize constants using base_dir from dyson import constants constants.init({"basedir": self.options.base_dir}) variablemanager = VariableManager() variablemanager.extra_vars = load_extra_vars(loader=dataloader, options=self.options) variablemanager.aut_vars = load_aut_vars( loader=dataloader, options=self.options, variable_manager=variablemanager) variablemanager.vars = load_vars(loader=dataloader, options=self.options, variable_manager=variablemanager) for test in self.args: self.report.add_test( Test(test, data_loader=dataloader, variable_manager=variablemanager).run()) self.report.render()
def run(self): super(TestCLI, self).run() for test in self.args: if not os.path.exists(test): raise DysonError("Test file %s does not exist" % test) dataloader = DataLoader() variablemanager = VariableManager() variablemanager.extra_vars = load_extra_vars(loader=dataloader, options=self.options) variablemanager.aut_vars = load_aut_vars( loader=dataloader, options=self.options, variable_manager=variablemanager) variablemanager.vars = load_vars(loader=dataloader, options=self.options, variable_manager=variablemanager) for test in self.args: self.report.add_test( Test(test, data_loader=dataloader, variable_manager=variablemanager).run()) self.report.render()
def run(self, webdriver, params): """ Sleep for a time :param webdriver: :param params: :return: """ if isinstance(params, string_types): # they specified - sleep: 5 # assume seconds time.sleep(params) elif isinstance(params, dict): if 'seconds' in params: time.sleep(params['seconds']) elif 's' in params: time.sleep(params['s']) elif 'ms' in params: ms = int(params['ms']) time.sleep(ms / 1000) elif 'milliseconds' in params: ms = int(params['milliseconds']) time.sleep(ms / 1000) else: raise DysonError( "Invalid option \"%s\" for sleep. Valid options are %s" % (params, ','.join(self.VALID_OPTIONS)))
def run(self): super(SuiteCLI, self).run() for suite in self.args: if not os.path.exists(suite): raise DysonError("Suite file %s does not exist" % suite) dataloader = DataLoader({"basedir": self.options.base_dir}) # initialize constants using base_dir from dyson import constants constants.init({"basedir": self.options.base_dir}) variablemanager = VariableManager() variablemanager.extra_vars = load_extra_vars(loader=dataloader, options=self.options) variablemanager.aut_vars = load_aut_vars( loader=dataloader, options=self.options, variable_manager=variablemanager) variablemanager.vars = load_vars(loader=dataloader, options=self.options, variable_manager=variablemanager) for suite in self.args: Suite(suite, data_loader=dataloader, variable_manager=variablemanager, report=self.report).run()
def translate_selector_to_by(selector): """ The By class has different ways of selecting things. This method translates: "css" to By.CSS_SELECTOR "name" to By.NAME "xpath" to By.XPATH "link" to By.LINK_TEXT "partiallink" to By.PARTIAL_LINK_TEXT "tag" to By.TAG_NAME "class" to By.CLASS_NAME :param selector: the strategy to check :return: the By.* class from Selenium """ valid_selectors = { 'CSS': 'CSS_SELECTOR', 'NAME': 'NAME', 'XPATH': 'XPATH', 'LINK': 'LINK_TEXT', 'PARTIALLINK': 'PARTIAL_LINK_TEXT', 'TAG': 'TAG_NAME', 'CLASS': 'CLASS_NAME' } if isinstance(selector, dict): the_strategy = next(iter(selector)).upper() if the_strategy in valid_selectors: return getattr(By, valid_selectors[the_strategy]), next( iter(selector.values())) else: raise DysonError( "%s is not a valid selector. Valid selectors are %s", ','.join(valid_selectors.keys())) elif isinstance(selector, string_types): the_strategy, the_selector = selector.split("=", maxsplit=1) if the_strategy.upper() in valid_selectors: return getattr(By, valid_selectors[the_strategy.upper()]), the_selector else: raise DysonError( "%s is not a valid selector. Valid selectors are %s", the_strategy, ','.join([key for key, _ in valid_selectors.items()]))
def run(self, webdriver, params): """ Click an element on the page :param webdriver: :param params: :return: """ if len(params.keys()) > 0: selector, strategy = translate_selector(params, webdriver) if selector and strategy: return selector(strategy).click() else: raise DysonError( "You need to specify a valid selector to click") else: raise DysonError("You need to specify an argument to \"click\"")
def run(self, webdriver, params): """ Get an attribute of an element :param webdriver: :param params: :return: """ if 'of' in params: if 'attribute' in params: element = params['of'] attribute = params['attribute'] strategy, selector = translate_selector(element, webdriver) return strategy(selector).get_attribute(attribute) else: raise DysonError("Key \"attribute\" required") else: raise DysonError("Key \"of\" required")
def run(self, webdriver, params): """ Get the text of a specific element (return innerText) :param webdriver: :param params: :return: """ if 'of' in params: strategy, selector = translate_selector(params['of'], webdriver) return strategy(selector).text else: raise DysonError("Key \"of\" is required")
def run(self, webdriver, params): """ Add cookie(s) to the session :param webdriver: :param params: :return: """ if isinstance(params, list): for cookie in params: webdriver.add_cookie(cookie) else: raise DysonError("Type needs to be array.")
def run(self, webdriver, params): """ Unchecks an element on the page. ONLY applies to checkbox's :param webdriver: :param params: :return: """ if len(params.keys()) > 0: selector, strategy = translate_selector(params, webdriver) if selector and strategy: element = selector(strategy) if element.is_selected(): return selector(strategy).click() else: raise DysonError( "You need to specify a valid selector to uncheck") else: raise DysonError("You need to specify an argument to \"uncheck\"")
def run(self, webdriver, params): """ Set the text of an input :param webdriver: :param params: :return: """ if 'of' in params and 'to' in params: strategy, selector = translate_selector(params['of'], webdriver=webdriver) return strategy(selector).send_keys(params['to']) else: raise DysonError("Keys \"of\" and \"to\" are required")
def run(self): if 'name' in self._step.keys(): print(self._step['name']) del self._step['name'] step_module = next(iter(self._step)) if step_module in self._keywords: """ We check keywords first. if they have a keyword that overrides a module, so be it. """ # for the keyword, get the steps within, and execute it. self._variable_manager.add_var( self._step) # add ephemeral variables individual_steps = self._data_loader.load_file( self._keywords[step_module]) if isinstance(individual_steps, list): for individual_step in individual_steps: individual_step = iterate_dict( individual_step, variable_manager=self._variable_manager) Step(individual_step, data_loader=self._data_loader, variable_manager=self._variable_manager, keywords=self._keywords, modules=self._modules, webdriver=self._webdriver).run() else: raise DysonError("Keywords must be a list") self._variable_manager.clear_additional_vars() elif step_module in self._modules: """ Run the specified Module """ return step_module, self._step[step_module], \ self._modules[step_module]().run(webdriver=self._webdriver, params=self._step[step_module]) else: raise DysonError("No such module or keyword \"%s\" exists" % step_module)
def run(self, webdriver, params): """ Get specific cookies, or all cookies. :param webdriver: :param params: :return: """ if isinstance(params, dict): if 'name' in params: return webdriver.get_cookie(params['name']) elif isinstance(params, list): cookies = list() for cookie in params: cookies.append(webdriver.get_cookie(cookie)) return cookies elif isinstance(params, string_types): if params is 'all': return webdriver.get_cookies() else: raise DysonError("Don't know how to fetch \"%s\". To get all cookies, specify \"all\"") else: raise DysonError("Invalid type")
def _validate_mutable_mappings(first_hash, second_hash): if not (isinstance(first_hash, MutableMapping) and isinstance(second_hash, MutableMapping)): myvars = [] for x in [first_hash, second_hash]: try: myvars.append(dumps(x)) except: pass raise DysonError( "Failed to combine dictionaries, expected dicts but got a '{0}' and '{1}': \n{2}\n{3}" .format(first_hash.__class__.__name__, second_hash.__class__.__name__, myvars[0], myvars[1]))
def run(self, webdriver, params): """ Navigate between pages. :param webdriver: :param params: :return: """ if isinstance(params, string_types): if 'forward' is params: webdriver.forward() elif 'back' is params: webdriver.back() elif isinstance(params, dict): if 'to' in params: GotoModule().run(webdriver, {'url': params['to']}) else: raise DysonError("Invalid type")
def run(self): super(SuiteCLI, self).run() for suite in self.args: if not os.path.exists(suite): raise DysonError("Suite file %s does not exist" % suite) dataloader = DataLoader() variablemanager = VariableManager() variablemanager.extra_vars = load_extra_vars(loader=dataloader, options=self.options) variablemanager.aut_vars = load_aut_vars(loader=dataloader, options=self.options, variable_manager=variablemanager) variablemanager.vars = load_vars(loader=dataloader, options=self.options, variable_manager=variablemanager) for suite in self.args: Suite(suite, data_loader=dataloader, variable_manager=variablemanager, report=self.report).run()
def _start_selenium(self): from dyson import constants browser = constants.DEFAULT_SELENIUM_BROWSER.capitalize() if hasattr(self._webdriver, browser) and hasattr( DesiredCapabilities, browser.upper()): command_executor = constants.DEFAULT_SELENIUM_HUB if command_executor: self._webdriver = self._webdriver.Remote( command_executor=command_executor, desired_capabilities=getattr(DesiredCapabilities, browser.upper())) self._webdriver.implicitly_wait( constants.DEFAULT_SELENIUM_IMPLICIT_WAIT) else: self._webdriver = getattr(self._webdriver, browser)() else: raise DysonError("Invalid browser " % constants.DEFAULT_SELENIUM_BROWSER)
def _load_modules_from(module_path): all_modules_from_path = dict() if os.path.exists(module_path) and os.path.isdir(module_path): for filename in glob.iglob("%s/**" % module_path, recursive=True): # FIXME (maybe?) for now, we only support python modules if os.path.isfile(filename) and os.path.basename(filename).endswith(".py") \ and not os.path.basename(filename).startswith("__"): module = None # module = importlib.import_module(os.path.basename(filename)) dirs = os.path.abspath(os.path.dirname(filename)).split(os.path.sep) dirs = list(filter(None, dirs)) for i in range(len(dirs)): i = 0 module_path = '.'.join(dirs) try: module = importlib.import_module(module_path) break except ImportError: del dirs[i] if module and module_path: try: module_to_load = os.path.basename(os.path.splitext(filename)[0]) if module_to_load.find("_") != -1: # using a _ in the module name. split = module_to_load.split("_") module_nicename = "" for s in split: module_nicename += s.capitalize() else: module_nicename = module_to_load.replace("_", "").capitalize() theclass = "%sModule" % module_nicename mod = getattr(__import__("%s.%s" % (module_path, module_to_load), fromlist=[theclass]), theclass) if issubclass(mod, DysonModule): all_modules_from_path[module_to_load] = mod except ImportError: raise DysonError("Couldn't find class %s" % theclass) return all_modules_from_path
def load_config_file(): """ Load Config File order (first found is used). environment variable, working dir, HOME """ p = configparser.ConfigParser() path0 = os.getenv("DYSON_CONFIG", None) if path0 is not None: path0 = os.path.expanduser(path0) if os.path.isdir(path0): path0 += "/dyson.cfg" try: path1 = os.getcwd() + "/dyson.cfg" except OSError: path1 = None path2 = os.path.expanduser("~/.dyson.cfg") for path in [path0, path1, path2]: if path is not None and os.path.exists(path): try: p.read(path) except configparser.Error as e: raise DysonError("Error reading config file: \n{0}".format(e)) return p, path return None, ''
def run(self, webdriver, params): """ Wait for things :param webdriver: :param params: :return: """ if isinstance(params, dict): if 'visibility_of' in params: """ Wait for the visibility of an element """ if 'element' in params['visibility_of']: element = params['visibility_of']['element'] else: raise DysonError("Key \"element\" is required") timeout = int(constants.DEFAULT_TIMEOUT) # seconds if 'timeout' in params['visibility_of']: timeout = int(params['visibility_of']['timeout']) return self._wait_for( element, expected_conditions.visibility_of_element_located, timeout, webdriver) if 'invisibility_of' in params: """ Wait for the invisibility of an element """ if 'element' in params['invisibility_of']: element = params['invisibility_of']['element'] else: raise DysonError("Key \"element\" is required") timeout = int(constants.DEFAULT_TIMEOUT) # seconds if 'timeout' in params['invisibility_of']: timeout = int(params['invisibility_of']['timeout']) return self._wait_for( element, expected_conditions.invisibility_of_element_located, timeout, webdriver) if 'presence_of' in params: """ Wait for the presence of an element """ if 'element' in params['presence_of']: element = params['presence_of']['element'] else: raise DysonError("Key \"element\" is required") timeout = int(constants.DEFAULT_TIMEOUT) # seconds if 'timeout' in params['presence_of']: timeout = int(params['presence_of']['timeout']) return self._wait_for( element, expected_conditions.presence_of_element_located, timeout, webdriver) if 'title_to_be' in params: """ Wait for the title to be something """ title = params['title_to_be'] timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['title_to_be']: timeout = int(params['title_to_be']['timeout']) return WebDriverWait(webdriver, timeout).until( expected_conditions.title_is(title)) if 'title_to_contain' in params: """ Wait for the title to contain """ title = params['title_to_contain'] timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['title_to_contain']: timeout = int(params['title_to_contain']['timeout']) return WebDriverWait(webdriver, timeout).until( expected_conditions.title_contains(title)) if 'alert' in params: """ Wait for an alert to be present """ timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['alert']: timeout = int(params['alert']['timeout']) return WebDriverWait(webdriver, timeout).until( expected_conditions.alert_is_present()) if 'text_to_be_present' in params: """ Wait for text to be present in an element """ timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['text_to_be_present']: timeout = int(params['text_to_be_present']['timeout']) if 'in_element' in params['text_to_be_present']: in_element = params['text_to_be_present']['in_element'] if 'text' in params['text_to_be_present']: text = in_element['text'] strategy, selector = translate_selector_to_by( in_element) return WebDriverWait(webdriver, timeout).until( expected_conditions.text_to_be_present_in_element( (strategy, selector), text)) else: raise DysonError("Key \"text\" is required") else: raise DysonError("Key \"in_element\" is required") if 'clickable' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['clickable']: timeout = int(params['clickable']['timeout']) return self._wait_for( params['clickable']['element'], expected_conditions.element_to_be_clickable, timeout, webdriver) if 'value_to_be' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['value_to_be']: timeout = int(params['value_to_be']['timeout']) if 'in_element' in params['value_to_be']: in_element = params['value_to_be']['in_element'] if 'value' in params['value_to_be']: value = in_element['value'] strategy, selector = translate_selector_to_by( in_element) return WebDriverWait(webdriver, timeout).until( expected_conditions. text_to_be_present_in_element_value( (strategy, selector), value)) else: raise DysonError("Key \"text\" is required") else: raise DysonError("Key \"in_element\" is required") if 'staleness_of' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['staleness_of']: timeout = int(params['staleness_of']['timeout']) if 'element' in params['staleness_of']: element = params['staleness_of']['element'] return self._wait_for(element, expected_conditions.staleness_of, timeout, webdriver) else: raise DysonError("Key \"element\" is required") if 'presence_of_all' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['presence_of_all']: timeout = int(params['presence_of_all']['timeout']) if 'elements' in params['presence_of_all']: elements = params['presence_of_all'] return self._wait_for( elements, expected_conditions.presence_of_all_elements_located, timeout, webdriver) else: raise DysonError("Key \"elements\" is required") if 'element_to_be_selected' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['element_to_be_selected']: timeout = int(params['element_to_be_selected']['timeout']) if 'element' in params['element_to_be_selected']: element = params['element_to_be_selected']['element'] return self._wait_for( element, expected_conditions.element_located_to_be_selected, timeout, webdriver) else: raise DysonError("Key \"element\" is required") if 'selection_state_to_be' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['selection_state_to_be']: timeout = int(params['selection_state_to_be']['timeout']) if 'in_element' in params['selection_state_to_be']: in_element = params['selection_state_to_be']['in_element'] if 'state' in params['selection_state_to_be']: state = to_boolean( params['selection_state_to_be']['state']) strategy, selector = translate_selector_to_by( in_element) return WebDriverWait(webdriver, timeout).until( expected_conditions. element_located_selection_state_to_be( (strategy, selector), state)) else: raise DysonError("Key \"state\" is required") else: raise DysonError("Key \"in_element\" is required") if 'frame_and_switch' in params: timeout = int(constants.DEFAULT_TIMEOUT) if 'timeout' in params['frame_and_switch']: timeout = int(params['frame_and_switch']['timeout']) if 'frame' in params['frame_and_switch']: frame = params['frame_and_switch']['frame'] return self._wait_for( frame, expected_conditions. frame_to_be_available_and_switch_to_it, timeout, webdriver) else: raise DysonError("Key \"frame\" is required") else: self.fail("Invalid type. You must specify a valid action")
def run(self, webdriver, params): """ Collection of switch_to actions with selenium. Available actions: - switch_to - frame <selector> - alert - action - dismiss - accept - send_keys - authenticate :param webdriver: :param params: :return: """ if isinstance(params, dict): if 'frame' in params: """ Switch to a frame / iframe """ selector, strategy = translate_selector(params['frame'], webdriver) return webdriver.switch_to.frame(selector(strategy)) elif 'alert' in params: """ Switch to an alert window """ if 'action' in params['alert']: alert_action = params['alert']['action'] valid_actions = frozenset(['accept', 'dismiss', 'authenticate', 'send_keys']) if alert_action in valid_actions: if 'accept' is alert_action: return webdriver.switch_to.alert.accept() elif 'dismiss' is alert_action: return webdriver.switch_to.alert.dismiss() elif 'get_text' is alert_action: return webdriver.switch_to.alert.text else: raise DysonError("Invalid action \"%s\". Valid actions are %s" % (alert_action, ','.join(valid_actions))) elif 'username' in params['alert']: username = params['alert']['username'] password = "" if params['alert']['password']: password = params['alert']['password'] return webdriver.switch_to.alert.authenticate(username, password) else: return webdriver.switch_to.alert() elif 'window' in params: return webdriver.switch_to.window(params['window']) else: raise DysonError("Unsure how to switch to \"%s\". Valid options are %s" % (params, ','.join(self.ACTIONS))) elif isinstance(params, string_types): if "default_content" == params: return webdriver.switch_to.default_content() else: raise DysonError("Unsure how to switch to \"%s\". Valid options are %s" % (params, ','.join(self.ACTIONS)))
def run(self, webdriver, params): """ Validate things :param webdriver: :param params: allowed validations: - title - is - is_not - present - not_present - text_of - is - is_not - value_of - is - is_not - is_checked - is_unchecked :return: """ if params and isinstance(params, dict): if 'title' in params: """ Validate the title_shouldbe of the page """ actual_title = webdriver.title title_shouldbe = params['title'] if 'is' in title_shouldbe: if actual_title != title_shouldbe: self.fail("Title is not \"%s\". Actual: \"%s\"" % (title_shouldbe, actual_title)) elif 'is_not' in title_shouldbe: if actual_title == title_shouldbe: self.fail("Title is \"%s\" when it shouldn't be" % title_shouldbe) if 'present' in params: """ Validate the presence of an element """ strategy, selector = translate_selector( params['present'], webdriver) return strategy(selector) if 'not_present' in params: """ Validate the absence of an element """ element = None strategy, selector = translate_selector( params['not_present'], webdriver) return strategy(selector) if 'text_of' in params: """ Validate text (or innerText) of an element """ text_of = params['text_of'] if 'element' not in text_of: raise DysonError("Key \"element\" is required") if 'is' in text_of: strategy, selector = translate_selector( text_of['element'], webdriver) actual_text = strategy(selector).text if actual_text != text_of['is']: self.fail( "Text of %s is not \"%s\". Actual: \"%s\"" % (text_of['element'], text_of['is'], actual_text)) else: return actual_text elif 'is_not' in text_of: strategy, selector = translate_selector( text_of['element'], webdriver) actual_text = strategy(selector).text if actual_text == text_of['is_not']: self.fail("Text of %s is \"%s\" when it shouldn't be" % (text_of['element'], text_of['is_not'])) else: return actual_text if 'value_of' in params: """ Validate value attribute of an element """ value_of = params['value_of'] if 'element' not in value_of: raise DysonError("Key \"element\" is required") if 'is' in value_of: strategy, selector = translate_selector( value_of['element'], webdriver) actual_value = strategy(selector).get_attribute('value') if actual_value != value_of['is']: self.fail("Value of %s is not \"%s\". Actual: \"%s\"" % (value_of['element'], value_of['is'], actual_value)) else: return actual_value elif 'is_not' in value_of: strategy, selector = translate_selector( value_of['element'], webdriver) actual_value = strategy(selector).get_attribute('value') if actual_value == value_of['is']: self.fail( "Value of %s is \"%s\" when it shouldn't be" % (value_of['element'], value_of['is'])) else: return actual_value if 'is_checked' in params: """ Validate that a checkbox / radio button is checked """ element = params['is_checked'] strategy, selector = translate_selector(element, webdriver) status = strategy(selector).is_selected() if not status: self.fail("Element %s is not checked" % element) else: return status if 'is_not_checked' in params: """ Validate that a checkbox / radio button is unchecked """ element = params['is_not_checked'] strategy, selector = translate_selector(element, webdriver) status = strategy(selector).is_selected() if status: self.fail("Element %s is checked" % element) else: return status elif isinstance(params, string_types): result = eval(params) if not to_boolean(result): self.fail("\"%s\" has a result of False" % params) return result