def train(self, request, run_id): training_run = get_object_or_404(TrainingRun, id=run_id) with open(os.path.join(settings.BASE_DIR, 'build', 'train.bundle.js')) as f: train_script = f.read() fd, ruleset_path = mkstemp() with os.fdopen(fd, 'w') as f: f.write(training_run.ruleset.code.encode('utf8')) facts = training_run.ruleset.fact_set.facts.all() client = None try: client = Marionette(bin=settings.FIREFOX_BIN, headless=True) client.start_session() webpages = list( map( lambda webpage: { 'url': webpage.url, 'facts': { fact.fact.key: fact.fact_answer for fact in webpage.webpagefact_set.filter(fact__in =facts) }, }, training_run.training_pages.all(), )) results = client.execute_async_script( train_script, script_args=( ruleset_path, list(map(lambda fact: fact.key, facts)), webpages, json.loads(training_run.initial_coefficients), ), sandbox='system', script_timeout=1000 * 60 * 5, ) training_run.final_coefficients = json.dumps(results[0]) training_run.save() finally: if client: client.cleanup() os.remove(ruleset_path) messages.add_message(request, messages.SUCCESS, 'Training run completed.') return redirect('admin:training_trainingrun_change', run_id)
def main(firefox_bin): if not firefox_bin: raise click.BadParameter( 'No Firefox binary found; configure the path to Firefox with `npm config`.' ) elif not os.path.exists(firefox_bin): raise click.BadParameter('Path to Firefox binary does not exist.') click.echo('== Building test bundle with Webpack') bundle_handle, bundle_path = mkstemp() try: webpack_config_path = os.path.join(ROOT, 'webpack/test.config.js') check_call([ 'webpack', '--bail', '--config', webpack_config_path, '--output', bundle_path, ]) with open(bundle_path) as f: test_code = f.read() finally: os.remove(bundle_path) click.echo('== Running tests') client = None try: client = Marionette(bin=firefox_bin, headless=True) client.start_session() results = client.execute_async_script(test_code) finally: if client: client.cleanup() # Pipe output through formatter to make it readable. reporter_env = os.environ.copy() reporter_env.setdefault('TAP_COLORS', '1') # Support color outpput reporter = Popen( ['tap-mocha-reporter', 'spec'], stdout=PIPE, stderr=STDOUT, stdin=PIPE, env=reporter_env, ) formatted_output, stderr = reporter.communicate(results['output']) click.echo(formatted_output) # Exit with an error code if there were any failures if results['failures'] > 0: sys.exit(1)
def freeze(self, request, queryset): with open(os.path.join(settings.BASE_DIR, 'build', 'freeze.bundle.js')) as f: freeze_script = f.read() client = None try: client = Marionette(bin=settings.FIREFOX_BIN, headless=True) client.start_session() for webpage in queryset: print('Freezing {}...'.format(webpage.url)) client.navigate(webpage.url) results = client.execute_async_script( freeze_script, script_timeout=1000 * 60 * 5, ) webpage.frozen_html.save(webpage.url, ContentFile(results['html'])) webpage.save() finally: if client: client.cleanup()
class CommonTestCase(unittest.TestCase): __metaclass__ = MetaParameterized match_re = None failureException = AssertionError pydebugger = None def __init__(self, methodName, **kwargs): unittest.TestCase.__init__(self, methodName) self.loglines = [] self.duration = 0 self.expected = kwargs.pop("expected", "pass") self.logger = get_default_logger() self.profile = FirefoxProfile() self.binary = kwargs.pop("binary", None) def _enter_pm(self): if self.pydebugger: self.pydebugger.post_mortem(sys.exc_info()[2]) def _addSkip(self, result, reason): addSkip = getattr(result, "addSkip", None) if addSkip is not None: addSkip(self, reason) else: warnings.warn("TestResult has no addSkip method, skips not reported", RuntimeWarning, 2) result.addSuccess(self) def run(self, result=None): # Bug 967566 suggests refactoring run, which would hopefully # mean getting rid of this inner function, which only sits # here to reduce code duplication: def expected_failure(result, exc_info): addExpectedFailure = getattr(result, "addExpectedFailure", None) if addExpectedFailure is not None: addExpectedFailure(self, exc_info) else: warnings.warn("TestResult has no addExpectedFailure method, " "reporting as passes", RuntimeWarning) result.addSuccess(self) self.start_time = time.time() orig_result = result if result is None: result = self.defaultTestResult() startTestRun = getattr(result, "startTestRun", None) if startTestRun is not None: startTestRun() result.startTest(self) testMethod = getattr(self, self._testMethodName) if getattr(self.__class__, "__unittest_skip__", False) or getattr(testMethod, "__unittest_skip__", False): # If the class or method was skipped. try: skip_why = getattr(self.__class__, "__unittest_skip_why__", "") or getattr( testMethod, "__unittest_skip_why__", "" ) self._addSkip(result, skip_why) finally: result.stopTest(self) self.stop_time = time.time() return try: success = False try: if self.expected == "fail": try: self.setUp() except Exception: raise _ExpectedFailure(sys.exc_info()) else: self.setUp() except SkipTest as e: self._addSkip(result, str(e)) except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except: self._enter_pm() result.addError(self, sys.exc_info()) else: try: if self.expected == "fail": try: testMethod() except: raise _ExpectedFailure(sys.exc_info()) raise _UnexpectedSuccess else: testMethod() except self.failureException: self._enter_pm() result.addFailure(self, sys.exc_info()) except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except _UnexpectedSuccess: addUnexpectedSuccess = getattr(result, "addUnexpectedSuccess", None) if addUnexpectedSuccess is not None: addUnexpectedSuccess(self) else: warnings.warn( "TestResult has no addUnexpectedSuccess method, reporting as failures", RuntimeWarning ) result.addFailure(self, sys.exc_info()) except SkipTest as e: self._addSkip(result, str(e)) except: self._enter_pm() result.addError(self, sys.exc_info()) else: success = True try: if self.expected == "fail": try: self.tearDown() except: raise _ExpectedFailure(sys.exc_info()) else: self.tearDown() except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except: self._enter_pm() result.addError(self, sys.exc_info()) success = False # Here we could handle doCleanups() instead of calling cleanTest directly self.cleanTest() if success: result.addSuccess(self) finally: result.stopTest(self) if orig_result is None: stopTestRun = getattr(result, "stopTestRun", None) if stopTestRun is not None: stopTestRun() @classmethod def match(cls, filename): """ Determines if the specified filename should be handled by this test class; this is done by looking for a match for the filename using cls.match_re. """ if not cls.match_re: return False m = cls.match_re.match(filename) return m is not None @classmethod def add_tests_to_suite(cls, mod_name, filepath, suite, testloader, testvars): """ Adds all the tests in the specified file to the specified suite. """ raise NotImplementedError @property def test_name(self): if hasattr(self, "jsFile"): return os.path.basename(self.jsFile) else: return "%s.py %s.%s" % (self.__class__.__module__, self.__class__.__name__, self._testMethodName) def id(self): # TBPL starring requires that the "test name" field of a failure message # not differ over time. The test name to be used is passed to # mozlog via the test id, so this is overriden to maintain # consistency. return self.test_name def setUp(self): # Convert the marionette weakref to an object, just for the # duration of the test; this is deleted in tearDown() to prevent # a persistent circular reference which in turn would prevent # proper garbage collection. self.start_time = time.time() self.pingServer = PingServer() self.pingServer.start() self.marionette = Marionette(bin=self.binary, profile=self.profile) if self.marionette.session is None: self.marionette.start_session() if self.marionette.timeout is not None: self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, self.marionette.timeout) self.marionette.timeouts(self.marionette.TIMEOUT_SCRIPT, self.marionette.timeout) self.marionette.timeouts(self.marionette.TIMEOUT_PAGE, self.marionette.timeout) else: self.marionette.timeouts(self.marionette.TIMEOUT_PAGE, 30000) def tearDown(self): self.marionette.cleanup() self.pingServer.stop() def cleanTest(self): self._deleteSession() def _deleteSession(self): if hasattr(self, "start_time"): self.duration = time.time() - self.start_time if hasattr(self.marionette, "session"): if self.marionette.session is not None: try: self.loglines.extend(self.marionette.get_logs()) except Exception, inst: self.loglines = [["Error getting log: %s" % inst]] try: self.marionette.delete_session() except (socket.error, MarionetteException, IOError): # Gecko has crashed? self.marionette.session = None try: self.marionette.client.close() except socket.error: pass self.marionette = None
def run_tests(firefox_path=None): basedir = os.path.dirname(__file__) if sys.platform == 'darwin' and os.path.isdir(firefox_path): firefox_path = os.path.join(firefox_path, 'Contents', 'MacOS', 'firefox') driver = Marionette(app='fxdesktop', bin=firefox_path, gecko_log='-', prefs={'xpinstall.signatures.required': False}) driver.start_session() try: build1 = tempfile.NamedTemporaryFile(mode='wb', suffix='.xpi', delete=False) build2 = tempfile.NamedTemporaryFile(mode='wb', suffix='.xpi', delete=False) try: jpm_build(basedir, build1.name) jpm_build(os.path.join(basedir, 'testhelper'), build2.name) addons = Addons(driver) addons.install(build1.name, temp=True) addons.install(build2.name, temp=True) finally: os.unlink(build1.name) os.unlink(build2.name) driver.expected = expected driver.keys = Keys class restore_url: def __enter__(self): self.url = driver.get_url() def __exit__(self, type, value, traceback): driver.navigate('about:blank') driver.navigate(self.url) driver.restore_url = restore_url def wait_until(method): Wait(driver, default_timeout).until(lambda d: method()) driver.wait_until = wait_until def accept_alert(): driver.switch_to_alert().accept() driver.accept_alert = accept_alert max_timestamp = {'value': 0} def get_urls(): result = [] prefix = '[testhelper] Loading: ' new_timestamp = max_timestamp['value'] with driver.using_context(driver.CONTEXT_CHROME): messages = driver.execute_script( 'return ' + 'Cc["@mozilla.org/consoleservice;1"]' + '.getService(Ci.nsIConsoleService).getMessageArray()' + '.map(m => m instanceof Ci.nsIScriptError ? ' + '[m.timeStamp, m.errorMessage] : [null, null])' ) for timestamp, message in messages: if timestamp <= max_timestamp['value']: continue if not message.startswith(prefix): continue if timestamp > new_timestamp: new_timestamp = timestamp result.append(message[len(prefix):]) max_timestamp['value'] = new_timestamp return result driver.get_urls = get_urls def close_windows(keep): for h in [h for h in driver.chrome_window_handles if h != keep]: driver.switch_to_window(h) driver.close_chrome_window() driver.switch_to_window(keep) driver.close_windows = close_windows def close_background_tabs(): current_tab = driver.current_window_handle for h in [h for h in driver.window_handles if h != current_tab]: driver.switch_to_window(h) driver.close() driver.switch_to_window(current_tab) driver.close_background_tabs = close_background_tabs def wait_for_load(): code = 'return document.readyState == "complete";' driver.wait_until(lambda: driver.execute_script(code)) driver.wait_for_load = wait_for_load def click(self): action = Actions(driver) action.click(self) action.perform() HTMLElement.click = click def middle_click(self): action = Actions(driver) action.middle_click(self) action.perform() HTMLElement.middle_click = middle_click def context_click(self): action = Actions(driver) action.context_click(self) action.perform() HTMLElement.context_click = context_click testdir = os.path.join(basedir, 'tests') for filename in os.listdir(testdir): if filename.startswith('.') or not filename.endswith('.py'): continue filepath = os.path.join(testdir, filename) globals = {} execfile(filepath, globals) globals['run'](driver) finally: driver.cleanup()
class CommonTestCase(unittest.TestCase): __metaclass__ = MetaParameterized match_re = None failureException = AssertionError pydebugger = None def __init__(self, methodName, **kwargs): unittest.TestCase.__init__(self, methodName) self.loglines = [] self.duration = 0 self.expected = kwargs.pop('expected', 'pass') self.logger = get_default_logger() self.profile = FirefoxProfile() self.binary = kwargs.pop('binary', None) def _enter_pm(self): if self.pydebugger: self.pydebugger.post_mortem(sys.exc_info()[2]) def _addSkip(self, result, reason): addSkip = getattr(result, 'addSkip', None) if addSkip is not None: addSkip(self, reason) else: warnings.warn( "TestResult has no addSkip method, skips not reported", RuntimeWarning, 2) result.addSuccess(self) def run(self, result=None): # Bug 967566 suggests refactoring run, which would hopefully # mean getting rid of this inner function, which only sits # here to reduce code duplication: def expected_failure(result, exc_info): addExpectedFailure = getattr(result, "addExpectedFailure", None) if addExpectedFailure is not None: addExpectedFailure(self, exc_info) else: warnings.warn( "TestResult has no addExpectedFailure method, " "reporting as passes", RuntimeWarning) result.addSuccess(self) self.start_time = time.time() orig_result = result if result is None: result = self.defaultTestResult() startTestRun = getattr(result, 'startTestRun', None) if startTestRun is not None: startTestRun() result.startTest(self) testMethod = getattr(self, self._testMethodName) if (getattr(self.__class__, "__unittest_skip__", False) or getattr(testMethod, "__unittest_skip__", False)): # If the class or method was skipped. try: skip_why = ( getattr(self.__class__, '__unittest_skip_why__', '') or getattr(testMethod, '__unittest_skip_why__', '')) self._addSkip(result, skip_why) finally: result.stopTest(self) self.stop_time = time.time() return try: success = False try: if self.expected == "fail": try: self.setUp() except Exception: raise _ExpectedFailure(sys.exc_info()) else: self.setUp() except SkipTest as e: self._addSkip(result, str(e)) except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except: self._enter_pm() result.addError(self, sys.exc_info()) else: try: if self.expected == 'fail': try: testMethod() except: raise _ExpectedFailure(sys.exc_info()) raise _UnexpectedSuccess else: testMethod() except self.failureException: self._enter_pm() result.addFailure(self, sys.exc_info()) except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except _UnexpectedSuccess: addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None) if addUnexpectedSuccess is not None: addUnexpectedSuccess(self) else: warnings.warn( "TestResult has no addUnexpectedSuccess method, reporting as failures", RuntimeWarning) result.addFailure(self, sys.exc_info()) except SkipTest as e: self._addSkip(result, str(e)) except: self._enter_pm() result.addError(self, sys.exc_info()) else: success = True try: if self.expected == "fail": try: self.tearDown() except: raise _ExpectedFailure(sys.exc_info()) else: self.tearDown() except KeyboardInterrupt: raise except _ExpectedFailure as e: expected_failure(result, e.exc_info) except: self._enter_pm() result.addError(self, sys.exc_info()) success = False # Here we could handle doCleanups() instead of calling cleanTest directly self.cleanTest() if success: result.addSuccess(self) finally: result.stopTest(self) if orig_result is None: stopTestRun = getattr(result, 'stopTestRun', None) if stopTestRun is not None: stopTestRun() @classmethod def match(cls, filename): """ Determines if the specified filename should be handled by this test class; this is done by looking for a match for the filename using cls.match_re. """ if not cls.match_re: return False m = cls.match_re.match(filename) return m is not None @classmethod def add_tests_to_suite(cls, mod_name, filepath, suite, testloader, testvars): """ Adds all the tests in the specified file to the specified suite. """ raise NotImplementedError @property def test_name(self): if hasattr(self, 'jsFile'): return os.path.basename(self.jsFile) else: return '{0}.py {1}.{2}'.format(self.__class__.__module__, self.__class__.__name__, self._testMethodName) def id(self): # TBPL starring requires that the "test name" field of a failure message # not differ over time. The test name to be used is passed to # mozlog via the test id, so this is overriden to maintain # consistency. return self.test_name def setUp(self): # Convert the marionette weakref to an object, just for the # duration of the test; this is deleted in tearDown() to prevent # a persistent circular reference which in turn would prevent # proper garbage collection. self.start_time = time.time() self.pingServer = PingServer() self.pingServer.start() self.marionette = Marionette(bin=self.binary, profile=self.profile) if self.marionette.session is None: self.marionette.start_session() self.marionette.reset_timeouts() def tearDown(self): self.marionette.cleanup() self.pingServer.stop() def cleanTest(self): self._deleteSession() def _deleteSession(self): if hasattr(self, 'start_time'): self.duration = time.time() - self.start_time if hasattr(self.marionette, 'session'): if self.marionette.session is not None: try: self.loglines.extend(self.marionette.get_logs()) except Exception, inst: self.loglines = [['Error getting log: {}'.format(inst)]] try: self.marionette.delete_session() except (socket.error, MarionetteException, IOError): # Gecko has crashed? self.marionette.session = None try: self.marionette.client.close() except socket.error: pass self.marionette = None
class MarionetteHelper: """ Helper for starting firefox and for remote browsing """ def __init__(self, firefox_path, logger=None): self.logger = logger # type: logging.Logger self.client = None # type: Marionette self.ffpopen = None # type: subprocess.Popen self.ffpath = firefox_path # type: str if logger is None: self.logger = logging.getLogger("MarionetteHelper") self.logger.debug("Marionette helper init done") def _open_session(self, host='localhost', port=2828): """ Opens the session for marionette""" caps = {u'acceptInsecureCerts': True, } self.client = Marionette(host, port=port) self.client.start_session(capabilities=caps) def run_firefox(self): """ Start the firefox process""" self.logger.debug("Starting firefox process") self.ffpopen = subprocess.Popen([self.ffpath, "-marionette"]) self.logger.debug("Opening marionette session") self._open_session() def quit_firefox(self): """ Close the firefox process and close marionette session""" #self.logger.debug("Closing firefox") #self.client._send_message("Marionette:Quit") self.client._request_in_app_shutdown("eForceQuit") self.client.delete_session(False) self.client.cleanup() self.client = None # reset client state #try: # self.client.close() # try to close the window anyway #except InvalidSessionIdException: # pass #except socket.error: # pass #finally: # try: # self.logger.debug("Closing marionette session") # self.client.delete_session(False) # close client session # except InvalidSessionIdException: # pass # except socket.error: # pass # self.client = None # reset client state #self.logger.debug("Waiting for firefox to close") #for _ in range(3): # give the process 3 seconds to terminate # time.sleep(1) # self.ffpopen.poll() # if self.ffpopen.returncode is not None: # break #self.ffpopen.poll() #if self.ffpopen.returncode is None: # self.logger.warning("Firefox not closed in time, killing it!") # self.ffpopen.kill() # process was not quit in time, kill it #self.ffpopen = None # reset popen state #self.logger.debug("Firefox is closed") def ___get_client(self): """ Returns the internal marionette client object""" return self.client def navigate_to_url(self, url): """ Open an url in format of http[s]://example.com""" try: if "http" not in url: url = "http://" + url self.client.navigate(url) except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def back(self): """ Go a page backward""" try: self.client.go_back() except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def forward(self): """ Go a page forward""" try: self.client.go_forward() except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def follow_link(self, index=0): """ Click on a link""" try: links = self.client.find_elements(By.TAG_NAME, "a") links[index].click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except IndexError: self.logger.warning("Error: Out of bound") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_class_name(self, html_class_name): """ Click on first element via class name""" try: e = self.client.find_element(By.CLASS_NAME, html_class_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_css_selector(self, css_selector): """ Click on first element via css selector""" try: e = self.client.find_element(By.CSS_SELECTOR, css_selector) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_id(self, html_id): """ Click on first element via element id""" try: e = self.client.find_element(By.ID, html_id) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_name(self, html_name): """ Click on first element via element name""" try: e = self.client.find_element(By.NAME, html_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_tag_name(self, html_tag_name): """ Click on first element via tag name""" try: e = self.client.find_element(By.TAG_NAME, html_tag_name) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_xpath(self, xpath): """ Click on first element via xpath""" try: e = self.client.find_element(By.XPATH, xpath) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def click_element_by_link_text(self, html_link_text): """ Click on first element via link text""" try: e = self.client.find_element(By.LINK_TEXT, html_link_text) e.click() except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False except InsecureCertificateException: self.logger.warning("Warning: Insecure Certificate") return True except UnknownException as e: if "Reached error page" in str(e): self.logger.warning("Reached error page, ignoring...") else: # reraise, something very unexpected happened here t, v, tb = sys.exc_info() raise t, v, tb return False return True def send_keys_to_element_by_name(self, name, text): """ Sends text to an element via name""" try: e = self.client.find_element(By.NAME, name) e.send_keys(text) except ElementNotVisibleException: self.logger.warning("Error: Element not visible") return False except ElementNotSelectableException: self.logger.warning("Error: Element not selectable") return False except ElementNotAccessibleException: self.logger.warning("Error: Element not accessible") return False except ElementNotInteractableException: self.logger.warning("Error: Element not interactable") return False except NoSuchElementException: self.logger.warning("Error: Element does not exist") return False except TimeoutException: self.logger.warning("Error: Timeout") return False return True def select_window(self, index): """ Switch window via index""" try: self.client.switch_to_window(self.client.window_handles[index]) except NoSuchWindowException: self.logger.warning("Error: Window does not exist") return False return True def close_window(self): """ Close the current window""" self.client.close() # this won't close the last window, call quit_firefox instead def get_current_window_index(self): """ Get current windows index""" return self.client.window_handles.index(self.client.current_window_handle) def new_tab(self): """ Open a new empty tab""" with self.client.using_context("chrome"): self.client.find_element(By.ID, "menu_newNavigatorTab").click() def new_window(self): """ Open a new empty window""" with self.client.using_context("chrome"): self.client.execute_script("window.open();") def close_tab(self): """ Close the current tab""" self.close_window() # basically the same as close windows
'}') # The location of the Firefox binary, will depend on system. # Be careful to use the actual binary and not a wrapper script. binary = '/usr/lib/firefox/firefox' # Loop through the four different configurations. for mode in ['headless', 'graphical']: # Set up the client with the appropriate settings. if mode == 'headless': os.environ['MOZ_HEADLESS'] = '1' else: os.environ.pop('MOZ_HEADLESS', None) client = Marionette('localhost', bin=binary, port=2828) client.start_session() # Navigate to the test page and inject the JavaScript. client.navigate( 'https://intoli.com/blog/javascript-injection/test-page.html') client.execute_async_script(injected_javascript) # Save the results as an image. filename = os.path.join( 'img', 'marionette-execute-async-scripy-firefox-%s-results.png' % mode) with open(filename, 'wb') as f: f.write(client.screenshot(format='binary')) print 'Saved "%s".' % filename # Cleanup the client before the next test. client.cleanup()
def marionette(request): marionette = Marionette(bin=request.config.getoption('firefox_path')) marionette.start_session() request.node._marionette = marionette yield marionette marionette.cleanup()
def run_tests(firefox_path=None): basedir = os.path.dirname(__file__) if sys.platform == 'darwin' and os.path.isdir(firefox_path): firefox_path = os.path.join(firefox_path, 'Contents', 'MacOS', 'firefox') driver = Marionette(app='fxdesktop', bin=firefox_path, gecko_log='-', prefs={'xpinstall.signatures.required': False}) driver.start_session() try: build1 = tempfile.NamedTemporaryFile(mode='wb', suffix='.xpi', delete=False) build2 = tempfile.NamedTemporaryFile(mode='wb', suffix='.xpi', delete=False) try: gulp_build(basedir, build1.name) jpm_build(basedir, os.path.join(basedir, 'testhelper'), build2.name) addons = Addons(driver) addons.install(build1.name, temp=True) addons.install(build2.name, temp=True) finally: os.unlink(build1.name) os.unlink(build2.name) driver.expected = expected driver.keys = Keys class restore_url: def __enter__(self): self.url = driver.get_url() def __exit__(self, type, value, traceback): driver.navigate('about:blank') driver.navigate(self.url) driver.restore_url = restore_url def wait_until(method): Wait(driver, default_timeout).until(lambda d: method()) driver.wait_until = wait_until def accept_alert(): driver.switch_to_alert().accept() driver.accept_alert = accept_alert max_timestamp = {'value': 0} def get_urls(): result = [] prefix = '[testhelper] Loading: ' new_timestamp = max_timestamp['value'] with driver.using_context(driver.CONTEXT_CHROME): messages = driver.execute_script( 'return ' + 'Cc["@mozilla.org/consoleservice;1"]' + '.getService(Ci.nsIConsoleService).getMessageArray()' + '.map(m => m instanceof Ci.nsIScriptError ? ' + '[m.timeStamp, m.errorMessage] : [null, null])') for timestamp, message in messages: if timestamp <= max_timestamp['value']: continue if not message.startswith(prefix): continue if timestamp > new_timestamp: new_timestamp = timestamp result.append(message[len(prefix):]) max_timestamp['value'] = new_timestamp return result driver.get_urls = get_urls def close_windows(keep): for h in [h for h in driver.chrome_window_handles if h != keep]: driver.switch_to_window(h) driver.close_chrome_window() driver.switch_to_window(keep) driver.close_windows = close_windows def close_background_tabs(): current_tab = driver.current_window_handle for h in [h for h in driver.window_handles if h != current_tab]: driver.switch_to_window(h) driver.close() driver.switch_to_window(current_tab) driver.close_background_tabs = close_background_tabs def wait_for_load(): code = 'return document.readyState == "complete";' driver.wait_until(lambda: driver.execute_script(code)) driver.wait_for_load = wait_for_load def click(self): action = Actions(driver) action.click(self) action.perform() HTMLElement.click = click def middle_click(self): action = Actions(driver) action.middle_click(self) action.perform() HTMLElement.middle_click = middle_click def context_click(self): action = Actions(driver) action.context_click(self) action.perform() HTMLElement.context_click = context_click testdir = os.path.join(basedir, 'tests') for filename in os.listdir(testdir): if filename.startswith('.') or not filename.endswith('.py'): continue filepath = os.path.join(testdir, filename) globals = {} execfile(filepath, globals) globals['run'](driver) finally: driver.cleanup()