def launch(self, _job, task): """Launch the browser""" self.connected = False self.extension = MessageServer() self.extension.start() from marionette_driver.marionette import Marionette from marionette_driver.addons import Addons args = [ '-profile', '"{0}"'.format(task['profile']), '-no-remote', '-marionette', 'about:blank' ] if self.path.find(' ') > -1: command_line = '"{0}"'.format(self.path) else: command_line = self.path command_line += ' ' + ' '.join(args) DesktopBrowser.launch_browser(self, command_line) self.marionette = Marionette('localhost', port=2828) self.marionette.start_session(timeout=self.task['time_limit']) logging.debug('Installing extension') self.addons = Addons(self.marionette) extension_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'support', 'Firefox', 'extension') self.extension_id = self.addons.install(extension_path, temp=True) logging.debug('Resizing browser to %dx%d', task['width'], task['height']) self.marionette.set_window_position(x=0, y=0) self.marionette.set_window_size(height=task['height'], width=task['width']) self.marionette.navigate(START_PAGE) time.sleep(0.5) self.wait_for_extension() if self.connected: DesktopBrowser.wait_for_idle(self)
class AnnounceMessenger: # Create our marionette instance. def __init__(self): self.client = Marionette('localhost', port=2828) self.client.start_session() random.seed() def send_message(self, to_user, message, wait_load=0.5): # Make firefox go to the users page. self.client.navigate("https://www.messenger.com/t/{}".format(to_user)) # Give a little bit of time to load. time.sleep(wait_load) for letter in message: # Make the typing look realistic. keep_down = random.uniform(0.005, 0.010) wait_time = keep_down + random.uniform(0.02, 0.05) # Send off the action action = Actions(self.client) if letter != '\n': action.key_down(letter).wait(keep_down).key_up(letter) else: # Handle multi line messages. action.key_down(Keys.SHIFT).key_down(Keys.ENTER)\ .wait(keep_down).key_up(Keys.SHIFT).key_up(Keys.ENTER) action.perform() # wait for it to complete. time.sleep(wait_time) # Send message. action.key_down('\n').wait(keep_down).key_up('\n') action.perform()
def start_client(self): logger.info( '{}: connecting to Marionette and beginning session'.format( self.name)) client = Marionette('localhost', port=2828) client.start_session() return client
def test_disable_enable_new_connections(self): # Do not re-create socket if it already exists self.marionette._send_message("Marionette:AcceptConnections", {"value": True}) try: # Disabling new connections does not affect existing ones... self.marionette._send_message( "Marionette:AcceptConnections", {"value": False} ) self.assertEqual(1, self.marionette.execute_script("return 1")) # but only new connection attempts marionette = Marionette( host=self.marionette.host, port=self.marionette.port ) self.assertRaises(socket.timeout, marionette.raise_for_port, timeout=1.0) self.marionette._send_message( "Marionette:AcceptConnections", {"value": True} ) marionette.raise_for_port(timeout=10.0) finally: self.marionette._send_message( "Marionette:AcceptConnections", {"value": True} )
def launch(self, job, task): """Launch the browser""" if self.job['message_server'] is not None: self.job['message_server'].flush_messages() self.connected = False from marionette_driver.marionette import Marionette from marionette_driver.addons import Addons args = [ '-profile', '"{0}"'.format(task['profile']), '-no-remote', '-marionette', 'about:blank' ] if self.path.find(' ') > -1: command_line = '"{0}"'.format(self.path) else: command_line = self.path command_line += ' ' + ' '.join(args) DesktopBrowser.launch_browser(self, command_line) try: self.marionette = Marionette('localhost', port=2828) self.marionette.start_session(timeout=self.task['time_limit']) self.configure_prefs() logging.debug('Installing extension') self.addons = Addons(self.marionette) extension_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'support', 'Firefox', 'extension') self.extension_id = self.addons.install(extension_path, temp=True) logging.debug('Resizing browser to %dx%d', task['width'], task['height']) self.marionette.set_window_position(x=0, y=0) self.marionette.set_window_size(height=task['height'], width=task['width']) if 'browserVersion' in self.marionette.session_capabilities: self.browser_version = self.marionette.session_capabilities[ 'browserVersion'] self.marionette.navigate(self.start_page) time.sleep(0.5) self.wait_for_extension() if self.connected: # Override the UA String if necessary ua_string = self.execute_js('navigator.userAgent;') modified = False if 'uastring' in self.job: ua_string = self.job['uastring'] modified = True if ua_string is not None and 'AppendUA' in task: ua_string += ' ' + task['AppendUA'] modified = True if modified: logging.debug(ua_string) self.marionette.set_pref('general.useragent.override', ua_string) # Wait for the browser startup to finish DesktopBrowser.wait_for_idle(self) except Exception as err: task['error'] = 'Error starting Firefox: {0}'.format(err.__str__())
def start_client(self): logger.info( '{}: connecting to Marionette and beginning session'.format( self.name)) client = Marionette('localhost', port=2828, bin=self.get_ff_default_path(), prefs={"browser.tabs.remote.autostart": True}, gecko_log='-') client.start_session() return client
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 setup(self): I18nSetup.locale_path = os.path.join(site.getsitepackages()[0], 'OWDTestToolkit/locale') if not I18nSetup.configured: marionette = Marionette() marionette.start_session() # Configure the translation to be used based on the previously retrieved language. Should # the translation is not found, the fallback will prevent a failure lang = marionette.execute_script("""return window.navigator.language;""") translation = gettext.translation('default', I18nSetup.locale_path, languages=[lang], fallback=True) I18nSetup._ = translation.ugettext I18nSetup.configured = True return I18nSetup._
def init_ff(self): """ Initialises the connection to Firefox and starts a session. @return: - """ if not check_socket(MARIONETTE_HOST, MARIONETTE_PORT): self.logger.error( u" > [ERROR] Please check if you started Firefox with the '-marionette' " "option or set 'marionette.enabled' to 'true' in 'about:config'. {}" .format(self.failure_symbol)) sys.exit(1) self.client = Marionette(host=MARIONETTE_HOST, port=MARIONETTE_PORT) self.client.start_session()
def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert (self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script)
def get_new_emulator(self): self.extra_emulator_index += 1 if len(self.marionette.extra_emulators) == self.extra_emulator_index: qemu = Marionette(emulator=self.marionette.emulator.arch, emulatorBinary=self.marionette.emulator.binary, homedir=self.marionette.homedir, baseurl=self.marionette.baseurl, noWindow=self.marionette.noWindow, gecko_path=self.marionette.gecko_path) qemu.start_session() self.marionette.extra_emulators.append(qemu) else: qemu = self.marionette.extra_emulators[self.extra_emulator_index] return qemu
def get_new_emulator(self): self.extra_emulator_index += 1 if len(self.marionette.extra_emulators) == self.extra_emulator_index: qemu = Marionette(emulator=self.marionette.emulator.arch, emulatorBinary=self.marionette.emulator.binary, homedir=self.marionette.homedir, baseurl=self.marionette.baseurl, noWindow=self.marionette.noWindow, gecko_path=self.marionette.gecko_path) qemu.start_session() self.marionette.extra_emulators.append(qemu) else: qemu = self.marionette.extra_emulators[self.extra_emulator_index] return qemu
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.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 marionette(request, timeout): """Return a marionette instance""" m = Marionette(bin=request.config.option.bin) m.start_session() m.set_prefs({'signon.rememberSignons': False}) request.addfinalizer(m.delete_session) m.set_search_timeout(timeout) return m
def fixture_marionette(binary, ping_server, marionette_port): """Start a marionette session with specific browser prefs""" server_url = "{url}pings".format(url=ping_server.get_url("/")) prefs = { # Fake the geoip lookup to always return Germany to: # * avoid net access in tests # * stabilize browser.search.region to avoid an extra subsession (bug 1545207) "browser.search.geoip.url": 'data:application/json,{"country_code": "DE"}', # Disable smart sizing because it changes prefs at startup. (bug 1547750) "browser.cache.disk.smart_size.enabled": False, "toolkit.telemetry.server": server_url, "toolkit.telemetry.initDelay": 1, "toolkit.telemetry.minSubsessionLength": 0, "datareporting.healthreport.uploadEnabled": True, "datareporting.policy.dataSubmissionEnabled": True, "datareporting.policy.dataSubmissionPolicyBypassNotification": True, "toolkit.telemetry.log.level": "Trace", "toolkit.telemetry.log.dump": True, "toolkit.telemetry.send.overrideOfficialCheck": True, "toolkit.telemetry.testing.disableFuzzingDelay": True, } yield Marionette(host="localhost", port=marionette_port, bin=binary, prefs=prefs)
def mock_marionette(request): """ Mock marionette instance """ marionette = MagicMock(spec=Marionette()) if "has_crashed" in request.funcargnames: marionette.check_for_crash.return_value = request.getfuncargvalue( "has_crashed") return marionette
def run(self, args=sys.argv[1:]): args = self.parser.parse_args() host, port = args.address.split(':') self.marionette = Marionette(host=host, port=int(port)) self.marionette.start_session() self.apps = gaiatest.GaiaApps(self.marionette) self.data_layer = gaiatest.GaiaData(self.marionette) self.device = gaiatest.GaiaDevice(self.marionette) ret = args.func(args) if ret is None: ret = 0 self.marionette.delete_session() sys.exit(ret)
def launch(self, _job, task): """Launch the browser""" from marionette_driver.marionette import Marionette args = [ '-profile', '"{0}"'.format(task['profile']), '-no-remote', '-width', str(task['width']), '-height', str(task['height']), '-marionette', 'about:blank' ] if self.path.find(' ') > -1: command_line = '"{0}"'.format(self.path) else: command_line = self.path command_line += ' ' + ' '.join(args) DesktopBrowser.launch_browser(self, command_line) self.marionette = Marionette('localhost', port=2828) self.marionette.start_session(timeout=60) self.marionette.navigate(START_PAGE)
def test_disable_enable_new_connections(self): # Do not re-create socket if it already exists self.marionette._send_message("acceptConnections", {"value": True}) try: # Disabling new connections does not affect existing ones... self.marionette._send_message("acceptConnections", {"value": False}) self.assertEqual(1, self.marionette.execute_script("return 1")) # but only new connection attempts marionette = Marionette(host=self.marionette.host, port=self.marionette.port) self.assertRaises(socket.timeout, marionette.raise_for_port, timeout=1.0) self.marionette._send_message("acceptConnections", {"value": True}) marionette.raise_for_port(timeout=10.0) finally: self.marionette._send_message("acceptConnections", {"value": True})
def marionette(request, timeout): """Return a marionette instance""" m = Marionette(bin=request.config.option.bin) m.start_session() m.set_prefs({'signon.rememberSignons': False}) request.addfinalizer(m.delete_session) m.set_search_timeout(timeout) return m
def test_single_active_session(self): self.assertEqual(1, self.marionette.execute_script("return 1")) # Use a new Marionette instance for the connection attempt, while there is # still an active session present. marionette = Marionette(host=self.marionette.host, port=self.marionette.port) self.assertRaises(socket.timeout, marionette.raise_for_port, timeout=1.0)
def __init__(self, binary: str, profile: str): self.__has_marionette = False self.__auto_download = False self.__download_dir = "" if not Path(binary).is_file(): return if not Path(profile).is_dir(): return # geckodriver の log ファイル出力を抑止する NO_LOG = "-" self.marionette = Marionette(bin=binary, gecko_log=NO_LOG, profile=profile) # start_session しないと quit もできない self.marionette.start_session() self.__has_marionette = True
def test_load_vapid_page(): client = Marionette("localhost", port=2828) client.start_session() url = "https://jrconlin.github.io/Webpush_QA/" expected_url = "https://jrconlin.github.io/Webpush_QA/success.html" client.navigate(url) sleep(5) assert expected_url in client.get_url()
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 single_setup(socks_port, run_cmd_over_tor): global tb_dir, tb_launcher, userjs_dir client = None tb_proc = None set_port(socks_port) # launch tor browser tb_launcher_fullpath = os.path.join(tb_dir, tb_launcher) userjs_fulldir = os.path.join(tb_dir, userjs_dir) if not os.path.isfile(tb_launcher_fullpath): exit( 'Tor browser launcher not found: %s, change variables tb_dir and tb_launcher and try again.' % tb_launcher_fullpath) if (not os.path.isdir(tb_dir)) or (not os.path.isdir(userjs_fulldir)): exit( 'Tor browser profile directory not found: %s, change variables tb_dir and userjs_dir and try again.' % tb_dir) # launch with marionette support and custom starup url # (when using your own tor instance the default startpage reports a problem) tb_proc = subprocess.Popen([ tb_launcher_fullpath, '--class', 'Tor Browser', '-profile', userjs_fulldir, '-marionette', '-url', 'about:blank', '-foreground' ]) # wait until browser has started listening on marionette port sleep(2) # connect to marionette client = Marionette('localhost', port=2828, socket_timeout=360) client.start_session() log.debug("tor browser started.") log.debug('default pageload timeout: %s' % str(client.timeout.page_load)) # in ms. default 60s. client.set_page_load_timeout(360000) client.timeout.page_load = 360 log.debug('set timeout to: %s' % str(client.timeout.page_load)) log.debug("marionette created.") return client, tb_proc
def boot_firefox(self, headless=True): # Indicate whether to run in headless mode self.enable_headless(headless) # Optionally shut down Marionette/Firefox after performing work # This will just be called if Python exits normally atexit.register(self.shutdown) # Check whether Firefox is already running logger.info( "Check for running instance of Marionette/Firefox at {}:{}".format(self.firefox_host, self.firefox_port) ) if check_socket(self.firefox_host, self.firefox_port): logger.info("Will reuse running Marionette/Firefox") self.firefox_bin = None self.firefox_already_started = True else: logger.info("Will launch new Marionette/Firefox instance") # Connect to / start Marionette Gecko engine self.marionette = Marionette( host=self.firefox_host, port=self.firefox_port, bin=self.firefox_bin, socket_timeout=self.socket_timeout, startup_timeout=self.startup_timeout, headless=self.firefox_run_headless, verbose=self.firefox_verbosity, ) self.marionette.DEFAULT_SHUTDOWN_TIMEOUT = self.shutdown_timeout # Start a session with Marionette Gecko engine self.marionette.start_session() # Configure Marionette self.configure_marionette()
def navigate(url): client = Marionette(host='localhost', port=2828) client.start_session() client.navigate(url) start_page = InformationPage(client) exhibitor_widget = start_page.get_exhibitor_widget() exhibitors = exhibitor_widget.get_exhibitors() return exhibitors
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 get_base_url(): if os.environ.get('BROWSER') != 'firefox': return PB_EXT_BG_URL_BASE from marionette_driver.marionette import Marionette marionette_client = Marionette('localhost', port=MARIONETTE_PORT) marionette_client.start_session() uuid_pref = marionette_client.get_pref('extensions.webextensions.uuids') uuid = json.loads(uuid_pref).values().pop() marionette_client.delete_session() return 'moz-extension://' + uuid + '/'
def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert(self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script)
def __init__(self, binary: str, profile: str): self.__has_session = False self.__auto_download = False self.__download_dir = "" if not Path(binary).is_file(): print(f"Binary {binary} Not Found") return if not Path(profile).is_dir(): print(f"Profile {profile} Not Found") return # geckodriver の log ファイル出力を抑止する self.marionette = Marionette( bin=binary, gecko_log=self.NO_LOG, profile=profile) # start_session 前にファイルを消しておかないと # 後で自動ダウンロードできない self.__delete_download_profile() # start_session しないと quit もできない self.marionette.start_session() self.__has_session = True
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 navigate(url): client = Marionette(host='localhost', port=2828) client.start_session() client.navigate(url) start_page = InformationPage(client) exhibitor_page = start_page.navigate_to_page("Exhibitors") exhibitor_widget = exhibitor_page.get_exhibitor_widget() exhibitors = exhibitor_widget.get_exhibitors() for exhibitor in exhibitors: print exhibitor
def test_load_vapid_page(): client = Marionette('localhost', port=2828) client.start_session() url = 'https://jrconlin.github.io/Webpush_QA/' client.navigate(url) sleep(5) # Loop through each expected test element and make sure we have our unicode check mark field_ids = ['pre', 'reg', 'sub', 'gen', 'vap', 'enc', 'snd', 'rcv', 'dec'] command = "return window.getComputedStyle(document.querySelector('li#{0}.done.undone'),':before').getPropertyValue('content')" for field_id in field_ids: resp = client.execute_script(command.format(field_id)) assert resp == u'"\u2611"'
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()
init += 1 return gp_success(init) else: return True parser = argparse.ArgumentParser(description='Bulk Reject translations on GlotPress with Firefox') parser.add_argument('--search', dest='search', help='The term with problems', required=True, type=str) parser.add_argument('--remove', dest='remove', help='The wrong translation to remove', required=True, type=str) parser.add_argument('--replace', dest='replace', help='The new translation to submit', required=False, type=str) parser.add_argument('--lang', dest='lang', help='The locale, eg: it', default="it") args = parser.parse_args() # Load configuration config = ConfigParser.RawConfigParser() config.readfp(open('config.ini')) print "Connection in progress to Firefox" client = Marionette(host='127.0.0.1', port=28288) client.start_session() print "Connection to Firefox Done" # Detect if already logged try: client.find_element(By.CSS_SELECTOR, 'body.logged-in') client.navigate("https://translate.wordpress.org/wp-login.php?action=logout&redirect_to=https%3A%2F%2Ftranslate.wordpress.org%2F&_wpnonce=583839252e") except: pass # Login client.navigate("https://login.wordpress.org/?redirect_to=https%3A%2F%2Ftranslate.wordpress.org%2F") try: #Log In Form usernameLogin = client.find_element(By.ID, 'user_login') usernameLogin.click() usernameLogin.send_keys(config.get('Login', 'user'))
#!/usr/bin/python2.7 # # Script to work around Marionette bug 879816 (cannot click the modal 'ok' button # following clicking something else). # from marionette_driver.marionette import Marionette marionette = Marionette(host='localhost', port=2828) marionette.start_session() marionette.switch_to_frame() marionette.execute_script("document.getElementById('modal-dialog-prompt-ok').click();")
def client(): # On MacOS: /Applications/Firefox.app/Contents/MacOS/firefox -marionette client = Marionette(host='localhost', port=2828) client.start_session() return client
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 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: 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()
#!/usr/bin/env python # -*- coding: utf-8 -*- from marionette_driver.marionette import Marionette import pdb client = Marionette("localhost", port=2828) client.start_session() client.navigate("http://www.tianyancha.com/company/75507246") element = client.find_element("class name", 'company_info') print element.text
class B2GDesktopReftest(RefTest): build_type = "desktop" marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert(self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status def create_profile(self, options, manifests, profile_to_clone=None): profile = RefTest.createReftestProfile(self, options, manifests, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False if not self.build_type == "mulet": # FIXME: With Mulet we can't set this values since Gaia won't launch prefs["b2g.system_startup_url"] = \ "app://test-container.gaiamobile.org/index.html" prefs["b2g.system_manifest_url"] = \ "app://test-container.gaiamobile.org/manifest.webapp" # Make sure we disable system updates prefs["app.update.enabled"] = False prefs["app.update.url"] = "" prefs["app.update.url.override"] = "" # Disable webapp updates prefs["webapps.update.enabled"] = False # Disable tiles also prefs["browser.newtabpage.directory.source"] = "" prefs["browser.newtabpage.directory.ping"] = "" prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False # Set a future policy version to avoid the telemetry prompt. prefs["toolkit.telemetry.prompted"] = 999 prefs["toolkit.telemetry.notifiedOptOut"] = 999 # Disable periodic updates of service workers prefs["dom.serviceWorkers.periodic-updates.enabled"] = False # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) if self.build_type == "mulet": args += ['-chrome', 'chrome://b2g/content/shell.html'] return cmd, args def _on_output(self, line): sys.stdout.write("%s\n" % line) sys.stdout.flush() # TODO use structured logging if "TEST-START" in line and "|" in line: self.last_test = line.split("|")[1].strip() def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" log.testFail(msg % (self.last_test, self.timeout)) # kill process to get a stack self.runner.stop(sig=signal.SIGABRT)
def marionette(request): m = Marionette(bin=request.config.option.bin) m.start_session() m.set_prefs({'signon.rememberSignons': False}) request.addfinalizer(m.delete_session) return m
class GCli(object): def __init__(self): self.commands = { 'connectwifi': { 'function': self.connect_to_wifi, 'args': [ {'name': 'ssid', 'help': 'SSID of the network to connect to'}, {'name': '--security', 'choices': ['WPA-PSK', 'WEP'], 'help': 'Security model of the network'}, {'name': '--password', 'help': 'Password to access the network'}], 'help': 'Connect to a WiFi network'}, 'disablewifi': { 'function': self.disable_wifi, 'help': 'Disable WiFi'}, 'enablewifi': { 'function': self.enable_wifi, 'help': 'Enable WiFi'}, 'forgetallwifi': { 'function': self.forget_all_wifi_networks, 'help': 'Forget all WiFi networks'}, 'getknownwifi': { 'function': self.known_wifi_networks, 'help': 'Show known WiFi networks'}, 'getsetting': { 'function': self.get_setting, 'args': [{ 'name': 'name', 'help': 'Name of the setting to retrieve'}], 'help': 'Show the current value of a setting'}, 'holdhome': { 'function': self.hold_home, 'help': 'Simulate holding the home button'}, 'holdsleep': { 'function': self.hold_sleep, 'help': 'Simulate holding the sleep button'}, 'home': { 'function': self.home, 'help': 'Simulate pressing the home button'}, 'killapps': { 'function': self.kill_all_apps, 'help': 'Kill all running apps'}, 'launchapp': { 'function': self.launch_app, 'args': [ {'name': 'name', 'nargs': argparse.REMAINDER, 'help': 'Name of app to launch'}], 'help': 'Launch an application'}, 'listallapps': { 'function': self.list_all_apps, 'help': 'List all apps'}, 'listrunningapps': { 'function': self.list_running_apps, 'help': 'List the running apps'}, 'lock': { 'function': self.lock, 'help': 'Lock screen'}, 'screenshot': { 'function': self.screenshot, 'help': 'Take a screenshot'}, 'sendsms': { 'function': self.send_sms, 'args': [ {'name': 'number', 'help': 'Phone number of recipient'}, {'name': 'message', 'help': 'Message content'}], 'help': 'Send an SMS'}, 'setsetting': { 'function': self.set_setting, 'args': [ {'name': 'name', 'help': 'Name of setting to change'}, {'name': 'value', 'help': 'New value for setting'}], 'help': 'Change the value of a setting'}, 'sleep': { 'function': self.sleep, 'help': 'Enter sleep mode'}, 'unlock': { 'function': self.unlock, 'help': 'Unlock screen'}, 'volume': { 'function': self.volume, 'args': [ {'name': 'direction', 'choices': ['down', 'up'], 'help': 'Direction to change the volume'}], 'help': 'Change the volume'}, 'wake': { 'function': self.wake, 'help': 'Wake from sleep mode'}} self.parser = argparse.ArgumentParser() self.add_options(self.parser) self.add_commands(self.parser) def run(self, args=sys.argv[1:]): args = self.parser.parse_args() host, port = args.address.split(':') self.marionette = Marionette(host=host, port=int(port)) self.marionette.start_session() self.apps = gaiatest.GaiaApps(self.marionette) self.data_layer = gaiatest.GaiaData(self.marionette) self.device = gaiatest.GaiaDevice(self.marionette) ret = args.func(args) if ret is None: ret = 0 self.marionette.delete_session() sys.exit(ret) def add_options(self, parser): parser.add_argument( '--address', default='localhost:2828', help='Address (host:port) of running Gecko instance to connect to ' '(default: %(default)s)') def add_commands(self, parser): subparsers = parser.add_subparsers( title='Commands', metavar='<command>') for (name, props) in sorted(self.commands.iteritems()): subparser = subparsers.add_parser(name, help=props['help']) if props.get('args'): for arg in props['args']: kwargs = {k: v for k, v in arg.items() if k is not 'name'} subparser.add_argument(arg['name'], **kwargs) subparser.set_defaults(func=props['function']) def connect_to_wifi(self, args): network = { 'ssid': args.ssid, 'keyManagement': args.security or 'NONE'} if args.security == 'WEP': network['wep'] = args.password elif args.security == 'WPA-PSK': network['psk'] = args.password self.data_layer.connect_to_wifi(network) def disable_wifi(self, args): self.data_layer.disable_wifi() def enable_wifi(self, args): self.data_layer.enable_wifi() def forget_all_wifi_networks(self, args): self.data_layer.forget_all_networks() def get_setting(self, args): print '%s: %s' % ( args.name, self.data_layer.get_setting(args.name)) def home(self, args): self.device.touch_home_button() def hold_home(self, args): self.device.hold_home_button() def hold_sleep(self, args): self.marionette.execute_script( "window.wrappedJSObject.dispatchEvent(new Event('holdsleep'));") def kill_all_apps(self, args): self.apps.kill_all() def known_wifi_networks(self, args): networks = [n for n in self.data_layer.known_networks if 'ssid' in n] if len(networks) > 0: for i, network in enumerate(networks): print '%s: %s' % (i + 1, network['ssid']) else: print 'No known networks.' def launch_app(self, args): for name in args.name: self.apps.launch(name) def list_all_apps(self, args): for i, app in enumerate(sorted(self.apps.installed_apps, key=lambda a: a.name.lower())): print '%d: %s' % (i + 1, app.name) def list_running_apps(self, args): for i, app in enumerate(sorted(self.apps.running_apps, key=lambda a: a.name.lower())): print '%d: %s' % (i + 1, app.name) def lock(self, args): self.device.lock() def screenshot(self, args): self.marionette.execute_script( "window.wrappedJSObject.dispatchEvent(new Event('volumedown+sleep'));") def send_sms(self, args): self.data_layer.send_sms(args.number, args.message) def set_setting(self, args): self.data_layer.set_setting(args.name, args.value) def sleep(self, args): self.marionette.execute_script( "window.wrappedJSObject.dispatchEvent(new Event('sleep'));") def unlock(self, args): self.device.unlock() def volume(self, args): self.marionette.execute_script( "window.wrappedJSObject.dispatchEvent(new Event('volume%s'));" % args.direction) def wake(self, args): self.marionette.execute_script( "window.wrappedJSObject.dispatchEvent(new Event('wake'));")
class MuletReftest(RefTest): build_type = "mulet" marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert(self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) self._populate_logger(options) outputHandler = OutputHandler(self.log, options.utilityPath, symbolsPath=options.symbolsPath) kp_kwargs = { 'processOutputLine': [outputHandler], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 self.log.info("%s | Running tests: start." % os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) self.log.info("%s | Application pid: %d" % ( os.path.basename(__file__), self.runner.process_handler.pid)) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: self.log.testFail("%s | application terminated with exit code %s" % ( self.last_test, status)) elif status < 0: self.log.info("%s | application killed with signal %s" % ( self.last_test, -status)) self.log.info("%s | Running tests: end." % os.path.basename(__file__)) return status def create_profile(self, options, manifests, profile_to_clone=None): profile = RefTest.createReftestProfile(self, options, manifests, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False if not self.build_type == "mulet": # FIXME: With Mulet we can't set this values since Gaia won't launch prefs["b2g.system_startup_url"] = \ "app://test-container.gaiamobile.org/index.html" prefs["b2g.system_manifest_url"] = \ "app://test-container.gaiamobile.org/manifest.webapp" # Make sure we disable system updates prefs["app.update.enabled"] = False prefs["app.update.url"] = "" # Disable webapp updates prefs["webapps.update.enabled"] = False # Disable tiles also prefs["browser.newtabpage.directory.source"] = "" prefs["browser.newtabpage.directory.ping"] = "" prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) if self.build_type == "mulet": args += ['-chrome', 'chrome://b2g/content/shell.html'] return cmd, args def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" self.log.testFail(msg % (self.last_test, self.timeout)) self.log.error("Force-terminating active process(es)."); # kill process to get a stack self.runner.stop(sig=signal.SIGABRT) def _unlockScreen(self): self.marionette.set_context(self.marionette.CONTEXT_CONTENT) self.marionette.import_script(os.path.abspath( os.path.join(__file__, os.path.pardir, "gaia_lock_screen.js"))) self.marionette.switch_to_frame() self.marionette.execute_async_script('GaiaLockScreen.unlock()') def _wait_for_homescreen(self, timeout): self.log.info("Waiting for home screen to load") Wait(self.marionette, timeout).until(expected.element_present( By.CSS_SELECTOR, '#homescreen[loading-state=false]'))