def run(self): apps = GaiaApps(self.device.marionette) # open two apps for name in [ 'Contacts', 'Clock', 'Music' ]: app = apps.launch(name) assert app.frame_id is not None # switch back to main frame self.device.marionette.switch_to_frame() # open cards view self.device.marionette.execute_script("window.dispatchEvent(new Event('holdhome'));") # launching apps can reset orientation to the wrong value, since some # apps only support portrait mode. reset it here. self.device.resetOrientation() self.start_capture() self.test_started() for i in range(3): for command in [ 'swipe_left', 'swipe_left', 'swipe_right', 'swipe_right' ]: self.device.executeCommand(command, []) time.sleep(0.5) self.test_finished() self.end_capture()
def run(self): apps = GaiaApps(self.device.marionette) # open two apps for name in ['Contacts', 'Clock', 'Music']: app = apps.launch(name) assert app.frame_id is not None # switch back to main frame self.device.marionette.switch_to_frame() # open cards view self.device.marionette.execute_script( "window.dispatchEvent(new Event('holdhome'));") # launching apps can reset orientation to the wrong value, since some # apps only support portrait mode. reset it here. self.device.resetOrientation() self.start_capture() self.test_started() for i in range(3): for command in ['swipe_left', 'swipe_left', 'swipe_right', 'swipe_right']: self.device.executeCommand(command, []) time.sleep(0.5) self.test_finished() self.end_capture()
def launch_app(self): # launch app and wait for it to "settle" so that it's ready for use # (this is a naive implementation that just assumes that we're done # "loading" after 5 seconds -- feel free to override this method in # your test) apps = GaiaApps(self.device.marionette) app = apps.launch(self.appname) assert app.frame_id is not None time.sleep(5)
def __init__(self, app_name, app_id, device=False): self.device = device if self.device: call(['adb', 'forward', 'tcp:2828', 'tcp:2828']) self._app_name = app_name self._app_id = app_id self._marionette = Marionette() self._marionette.start_session() self._gaia_apps = GaiaApps(self._marionette) self._gaia_data = GaiaData(self._marionette) self._gaia_device = GaiaDevice(self._marionette) ''' Deprecated
def wait_for_content_ready(self): apps = GaiaApps(self.device.marionette) contacts = Contacts(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == 'contacts') apps.switch_to_displayed_app() Wait(self.device.marionette, 120, ignored_exceptions=( NoSuchElementException, ElementNotVisibleException)).until( lambda m: m.find_element( *contacts._contact_locator).is_displayed())
def run(self): apps = GaiaApps(self.device.marionette) self.start_capture() self.test_started() app = apps.launch(self.appname) assert app.frame_id is not None time.sleep(5) self.test_finished() self.end_capture() # cleanup: switch back to main frame self.device.marionette.switch_to_frame()
def wait_for_content_ready(self): apps = GaiaApps(self.device.marionette) contacts = Contacts(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == 'contacts') apps.switch_to_displayed_app() Wait(self.device.marionette, 120, ignored_exceptions=( NoSuchElementException, ElementNotVisibleException)).until(lambda m: m.find_element( *contacts._contact_locator).is_displayed())
def wait_for_content_ready(self): apps = GaiaApps(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == 'marketplace') apps.switch_to_displayed_app() if 'index.html' in self.device.marionette.get_url(): # only switch to iframe if Marketplace is not packaged iframe = Wait(self.device.marionette).until( expected.element_present( By.CSS_SELECTOR, 'iframe[src*="marketplace"]')) self.device.marionette.switch_to_frame(iframe) Wait(self.device.marionette, timeout=30).until( lambda m: 'loaded' in m.find_element( By.TAG_NAME, 'body').get_attribute('class').split())
def wait_for_content_ready(self): apps = GaiaApps(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == 'marketplace') apps.switch_to_displayed_app() iframe = Wait(self.device.marionette).until( expected.element_present(By.CSS_SELECTOR, 'iframe[src*="marketplace"]')) self.device.marionette.switch_to_frame(iframe) # FIXME: The below *should* work, but doesn't... just doing an # arbitrary #Wait(self.device.marionette).until( # lambda m: 'loaded' in m.find_element( # By.TAG_NAME, 'body').get_attribute('class').split() time.sleep(30)
def run(self): apps = GaiaApps(self.device.marionette) app = apps.launch(self.appname) assert app.frame_id is not None time.sleep(5) self.start_capture() self.test_started() self.log("Running commands") self.device.executeCommands(self.cmds) self.log("Executed commands, finishing test") self.test_finished() self.end_capture() # cleanup: switch back to main frame self.device.marionette.switch_to_frame()
def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self._logger.info("Marionette ready, starting session") self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError( "bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette)
def run(self): apps = GaiaApps(self.device.marionette) # theoretically it would be cleaner to set this specifically for the # camera test, but that seemed additional complication for no real # gain apps.set_permission('Camera', 'geolocation', 'deny') self.start_capture() self.test_started() app = apps.launch(self.appname) assert app.frame_id is not None self.log("Waiting %s seconds for app to finish starting" % self.capture_timeout) time.sleep(self.capture_timeout) self.test_finished() self.end_capture() # cleanup: switch back to main frame self.device.marionette.switch_to_frame()
def run(self): self.device.gaiaApps.switch_to_displayed_app() # switch to homescreen appicon = None # HACK: Bug 1026527 - perform a no-op swipe before running test to # workaround flame not processing input events properly self.device.executeCommands([['swipe_right']]) icons = self.device.marionette.find_elements( By.CSS_SELECTOR, 'gaia-grid .icon:not(.placeholder)') for icon in icons: if icon.text == self.appname: self.device.marionette.execute_script( 'arguments[0].scrollIntoView(false);', [icon]) appicon = icon if appicon is None: raise TestException("Cannot find icon for app with name " "'%s'" % self.appname) tap_x = appicon.location['x'] + (appicon.size['width'] / 2) tap_y = appicon.location['y'] + (appicon.size['height'] / 2) self.start_capture() self.execute_actions([['tap', tap_x, tap_y]], test_finished_after_actions=False) # wait for the app to be displayed apps = GaiaApps(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == self.appname.lower()) apps.switch_to_displayed_app() self.wait_for_content_ready() self.logger.info("Content ready. Waiting an additional second to make " "sure it has settled") time.sleep(1) self.test_finished() self.end_capture()
def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError("bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette)
def touch_home_button(self): # ref: https://github.com/mozilla-b2g/gaia/blob/master/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L751 apps = GaiaApps(self._marionette) if apps.displayed_app.name.lower() != 'homescreen': # touching home button will return to homescreen self._dispatch_home_button_event() Wait(self._marionette).until( lambda m: apps.displayed_app.name.lower() == 'homescreen') apps.switch_to_displayed_app() else: apps.switch_to_displayed_app() mode = self._marionette.find_element(By.TAG_NAME, 'body').get_attribute('class') self._dispatch_home_button_event() apps.switch_to_displayed_app() if 'edit-mode' in mode: # touching home button will exit edit mode Wait(self._marionette).until(lambda m: m.find_element( By.TAG_NAME, 'body').get_attribute('class') != mode) else: # touching home button inside homescreen will scroll it to the top Wait(self._marionette).until(lambda m: m.execute_script( "return window.wrappedJSObject.scrollY") == 0)
class B2gExecutor(Executor): def __init__(self, app_name, app_id, device=False): self.device = device if self.device: call(['adb', 'forward', 'tcp:2828', 'tcp:2828']) self._app_name = app_name self._app_id = app_id self._marionette = Marionette() self._marionette.start_session() self._gaia_apps = GaiaApps(self._marionette) self._gaia_data = GaiaData(self._marionette) self._gaia_device = GaiaDevice(self._marionette) ''' Deprecated # https://github.com/mozilla-b2g/gaia/blob/b568b7ae8adb6ee3651bd75acbaaedff86a08912/tests/python/gaia-ui-tests/gaiatest/gaia_test.py js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) self._marionette.import_script(js) js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_data_layer.js")) self._marionette.set_context(self._marionette.CONTEXT_CHROME) self._marionette.import_script(js) self._marionette.set_context(self._marionette.CONTEXT_CONTENT) # C:\Users\Jun-Wei\Desktop\b2g\battery\manifest.webapp #app = GaiaApps(self._marionette).launch(self._app_name) #app = GaiaApps(self._marionette).launch('Battery', manifest_url='C:/Users/Jun-Wei/Desktop/b2g/battery/manifest.webapp', entry_point='/index.html') app = GaiaApps(self._marionette).launch('Battery') print app.frame print app.src print app.origin print app.name #print g_app.manifest_url #self._app_frame = g_app.frame self._app_frame_id = app.frame self._app_src = app.src self._app_origin = app.origin #self.app_manifest_url = g_app.manifest_url #self.gaia_apps = GaiaApps(self.__marionette) #print self.gaia_apps.displayed_app.name #print self.gaia_apps.installed_apps #print self.gaia_apps.running_apps() #js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) #self.__marionette.import_script(js) ''' def fire_event(self, clickable): logger.info('fire_event: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) try: # id staring with DomAnalyzer.serial_prefix is given by our monkey and should be ignored when locating if clickable.get_id() and not clickable.get_id().startswith(DomAnalyzer.serial_prefix): self._marionette.find_element('id', clickable.get_id()).tap() elif clickable.get_xpath(): self._marionette.find_element('xpath', clickable.get_xpath()).tap() else: logger.error('No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info('Element is not interactable in fire_event(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) except Exception as e: logger.error('Unknown Exception: %s in fire_event(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath()) sys.exit() def fill_form(self, clickable): for f in clickable.get_forms(): for input_field in f.get_inputs(): try: if input_field.get_id() and not input_field.get_id().startswith(DomAnalyzer.serial_prefix): self._marionette.find_element('id', input_field.get_id()).send_keys(input_field.get_value()) elif input_field.get_xpath(): self._marionette.find_element('xpath', input_field.get_xpath()).send_keys(input_field.get_value()) else: logger.error('No id nor xpath for an input field in the form id: %s (xpath: %s)', f.get_id(), f.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info('Element is not interactable in fill_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath()) except Exception as e: logger.error('Unknown Exception: %s in fill_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath()) sys.exit() def empty_form(self, clickable): for f in clickable.get_forms(): for input_field in f.get_inputs(): try: if input_field.get_id() and not input_field.get_id().startswith(DomAnalyzer.serial_prefix): self._marionette.find_element('id', input_field.get_id()).clear() elif input_field.get_xpath(): self._marionette.find_element('xpath', input_field.get_xpath()).clear() else: logger.error('No id nor xpath for an input field in the form %s (%s)', f.get_id(), f.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info('Element is not interactable in empty_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath()) except Exception as e: logger.error('Unknown Exception: %s in empty_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath()) sys.exit() def get_source(self): return self._marionette.page_source.encode(sys.stdout.encoding, 'ignore') def get_screenshot(self, clickable=None): element = None if clickable: try: if clickable.get_id() and not clickable.get_id().startswith(DomAnalyzer.serial_prefix): element = self._marionette.find_element('id', clickable.get_id()) elif clickable.get_xpath(): element = self._marionette.find_element('xpath', clickable.get_xpath()) else: logger.error('No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info('Element is not interactable in get_screenshot(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) except Exception as e: logger.error('Unknown Exception: %s in get_screenshot(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath()) sys.exit() if not element: # set context to CHROME to capture whole screen # system frame e.g. FileNotFound cannot be captured without CONTEXT_CHROME (Don't know why) self._marionette.set_context(self._marionette.CONTEXT_CHROME) screenshot = self._marionette.screenshot(element) self._marionette.set_context(self._marionette.CONTEXT_CONTENT) return screenshot def switch_to_frame(self, by, frame_str): """ :param by: options: "id", "xpath", "link text", "partial link text", "name", "tag name", "class name", "css selector", "anon attribute" """ # self.switch_to_top_frame() frame = self._marionette.find_element(by, frame_str) self._marionette.switch_to_frame(frame) def switch_to_top_frame(self): self._marionette.switch_to_frame() # switch to the top-level frame def restart_app(self): # remember to disable screen timeout and screen lock before testing # todo: open b2g simulator, install app, # unlock_screen # self._marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();') self.kill_all_apps() # kill_all_apps() will also kill the 'homescreen app' on real device # so trigger a home event to restore homescreen if self.device: self._dispatch_home_button_event() self.clear_data() self.touch_home_button() # launch the app self._gaia_apps.launch(self._app_name) ''' Deprecated if self.device: icon = self._marionette.find_element('xpath', "//li[contains(@aria-label, '" + self._app_name + "')]") else: icon = self._marionette.find_element('xpath', "//div[contains(@class, 'icon')]//span[contains(text(),'" + self._app_name + "')]") icon.tap() ''' time.sleep(5) # wait for app screen self._marionette.switch_to_frame() # this wait seems not working, need to find another useful one Wait(self._marionette).until(lambda m: m.find_element('css selector', "iframe[data-url*='" + self._app_id + "']").is_displayed()) app_frame = self._marionette.find_element('css selector', "iframe[data-url*='" + self._app_id + "']") self._marionette.switch_to_frame(app_frame) def touch_home_button(self): # ref: https://github.com/mozilla-b2g/gaia/blob/master/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L751 apps = self._gaia_apps if apps.displayed_app.name.lower() != 'homescreen': # touching home button will return to homescreen self._dispatch_home_button_event() Wait(self._marionette).until( lambda m: apps.displayed_app.name.lower() == 'homescreen') apps.switch_to_displayed_app() else: apps.switch_to_displayed_app() mode = self._marionette.find_element(By.TAG_NAME, 'body').get_attribute('class') self._dispatch_home_button_event() apps.switch_to_displayed_app() if 'edit-mode' in mode: # touching home button will exit edit mode Wait(self._marionette).until(lambda m: m.find_element( By.TAG_NAME, 'body').get_attribute('class') != mode) else: # touching home button inside homescreen will scroll it to the top Wait(self._marionette).until(lambda m: m.execute_script( "return window.wrappedJSObject.scrollY") == 0) def _dispatch_home_button_event(self): self._gaia_device._dispatch_home_button_event() ''' Deprecated self._marionette.switch_to_frame() self._marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('home'));") ''' time.sleep(0.5) def clear_data(self): # for now, clear contact data # https://github.com/mozilla-b2g/gaia/blob/v2.2/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L208 self._marionette.set_context(self._marionette.CONTEXT_CHROME) result = self._marionette.execute_async_script('return GaiaDataLayer.removeAllContacts();') assert result, 'Unable to remove all contacts' self._marionette.set_context(self._marionette.CONTEXT_CONTENT) time.sleep(0.5) def kill_all_apps(self): self._marionette.switch_to_frame() self._marionette.execute_async_script(""" // Kills all running apps, except the homescreen. function killAll() { let manager = window.wrappedJSObject.appWindowManager; let apps = manager.getApps(); for (let id in apps) { let origin = apps[id].origin; if (origin.indexOf('verticalhome') == -1) { manager.kill(origin); } } }; killAll(); // return true so execute_async_script knows the script is complete marionetteScriptFinished(true); """) time.sleep(0.5)
class EidetickerB2GMixin(EidetickerMixin): """B2G-specific extensions to the eideticker mixin""" marionette = None def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self._logger.info("Marionette ready, starting session") self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError( "bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaData = GaiaData(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette) def connectWIFI(self, wifiSettings): """ Tries to connect to the wifi network """ self._logger.info("Setting up wifi...") self.gaiaData.connect_to_wifi(wifiSettings) self._logger.info("WIFI ready!") def cleanup(self): self.removeDir('/data/local/storage/persistent') self.removeDir('/data/b2g/mozilla') for item in self.listFiles('/sdcard/'): self.removeDir('/'.join(['/sdcard', item])) def stopB2G(self): self._logger.info("Stopping B2G") if self.marionette and self.marionette.session: self.marionette.delete_session() self.marionette = None self.shellCheckOutput(['stop', 'b2g']) # Wait for a bit to make sure B2G has completely shut down. tries = 100 while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0: tries -= 1 time.sleep(0.1) if tries == 0: raise mozdevice.DMError("Could not kill b2g process") def startB2G(self): self._logger.info("Starting B2G") self.shellCheckOutput(['start', 'b2g']) self.setupMarionette() self.marionette.execute_async_script(""" window.addEventListener('mozbrowserloadend', function loaded(aEvent) { if (aEvent.target.src.indexOf('ftu') != -1 || aEvent.target.src.indexOf('homescreen') != -1) { window.removeEventListener('mozbrowserloadend', loaded); marionetteScriptFinished(); } });""", script_timeout=60000) # TODO: Remove this sleep when Bug 924912 is addressed time.sleep(5) # run the fake update checker FakeUpdateChecker(self.marionette).check_updates() # unlock device, so it doesn't go to sleep self._logger.info("Unlocking screen...") self.gaiaDevice.unlock() # turn off automatic brightness adjustments and set to 100% self.gaiaData.set_setting('screen.automatic-brightness', '') self.gaiaData.set_setting('screen.brightness', 1) # kill running apps so they don't interfere with the test self._logger.info("Killing all running apps...") self.gaiaApps.kill_all() # set correct orientation self._logger.info("Setting orientation") self.marionette.execute_script( "screen.mozLockOrientation('%s');" % self.deviceProperties['defaultOrientation']) def restartB2G(self): """ Restarts the b2g process on the device. """ self.stopB2G() self.startB2G()
def launch_app(self): apps = GaiaApps(self.device.marionette) apps.launch('Marketplace') self.wait_for_content_ready()
class EidetickerB2GMixin(EidetickerMixin): """B2G-specific extensions to the eideticker mixin""" marionette = None def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self._logger.info("Marionette ready, starting session") self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError( "bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette) def connectWIFI(self, wifiSettings): """ Tries to connect to the wifi network """ self._logger.info("Setting up wifi...") data = GaiaData(self.marionette) data.connect_to_wifi(wifiSettings) self._logger.info("WIFI ready!") def cleanup(self): self.removeDir('/data/local/storage/persistent') self.removeDir('/data/b2g/mozilla') for item in self.listFiles('/sdcard/'): self.removeDir('/'.join(['/sdcard', item])) def stopB2G(self): self._logger.info("Stopping B2G") if self.marionette and self.marionette.session: self.marionette.delete_session() self.marionette = None self.shellCheckOutput(['stop', 'b2g']) # Wait for a bit to make sure B2G has completely shut down. tries = 100 while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0: tries -= 1 time.sleep(0.1) if tries == 0: raise mozdevice.DMError("Could not kill b2g process") def startB2G(self): self.shellCheckOutput(['start', 'b2g']) self.setupMarionette() self.marionette.execute_async_script(""" window.addEventListener('mozbrowserloadend', function loaded(aEvent) { if (aEvent.target.src.indexOf('ftu') != -1 || aEvent.target.src.indexOf('homescreen') != -1) { window.removeEventListener('mozbrowserloadend', loaded); marionetteScriptFinished(); } });""", script_timeout=60000) # TODO: Remove this sleep when Bug 924912 is addressed time.sleep(5) def restartB2G(self): """ Restarts the b2g process on the device. """ self.stopB2G() self.startB2G() def resetOrientation(self): self.setOrientation(self.deviceProperties['defaultOrientation']) def setOrientation(self, orientation): # set landscape or portrait mode self._logger.info("Setting orientation: %s" % orientation) self.marionette.execute_script("screen.mozLockOrientation('%s');" % orientation) def unlock(self): # unlock device, so it doesn't go to sleep self._logger.info("Unlocking screen...") self.gaiaDevice.unlock() def killApps(self): self._logger.info("Killing all running apps...") self.gaiaApps.kill_all()
class EidetickerB2GMixin(EidetickerMixin): """B2G-specific extensions to the eideticker mixin""" marionette = None _devicePixelRatio = None def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self._logger.info("Marionette ready, starting session") self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError( "bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaData = GaiaData(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette) self.gaiaCompat = GaiaCompat() def connectWIFI(self, wifiSettings): """ Tries to connect to the wifi network """ self._logger.info("Setting up wifi...") self.gaiaData.connect_to_wifi(wifiSettings) self._logger.info("WIFI ready!") def cleanup(self): self.removeDir('/data/local/storage/persistent') self.removeDir('/data/b2g/mozilla') for item in self.listFiles('/sdcard/'): self.removeDir('/'.join(['/sdcard', item])) def stopB2G(self): self._logger.info("Stopping B2G") if self.marionette and self.marionette.session: self.marionette.delete_session() self.marionette = None self.shellCheckOutput(['stop', 'b2g']) # Wait for a bit to make sure B2G has completely shut down. tries = 100 while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0: tries -= 1 time.sleep(0.1) if tries == 0: raise mozdevice.DMError("Could not kill b2g process") def startB2G(self): self._logger.info("Starting B2G") self.shellCheckOutput(['start', 'b2g']) self.setupMarionette() self.gaiaCompat.wait_for_b2g(self.marionette) # run the fake update checker self.gaiaCompat.supress_update_check(self.marionette) # unlock device, so it doesn't go to sleep self._logger.info("Unlocking screen...") self.gaiaDevice.unlock() # turn off automatic brightness adjustments and set to 100% self.gaiaData.set_setting('screen.automatic-brightness', '') self.gaiaData.set_setting('screen.brightness', 1) # kill running apps so they don't interfere with the test self._logger.info("Killing all running apps...") self.gaiaApps.kill_all() # set correct orientation self._logger.info("Setting orientation") self.marionette.execute_script("screen.mozLockOrientation('%s');" % self.deviceProperties['defaultOrientation']) def restartB2G(self): """ Restarts the b2g process on the device. """ self.stopB2G() self.startB2G() @property def devicePixelRatio(self): if not self._devicePixelRatio: if self.marionette and self.marionette.session: self._devicePixelRatio = self.marionette.execute_script( 'return window.wrappedJSObject.devicePixelRatio;') return self._devicePixelRatio or 1
class B2gExecutor(Executor): def __init__(self, app_name, app_id, device=False): self.device = device if self.device: call(['adb', 'forward', 'tcp:2828', 'tcp:2828']) self._app_name = app_name self._app_id = app_id self._marionette = Marionette() self._marionette.start_session() self._gaia_apps = GaiaApps(self._marionette) self._gaia_data = GaiaData(self._marionette) self._gaia_device = GaiaDevice(self._marionette) ''' Deprecated # https://github.com/mozilla-b2g/gaia/blob/b568b7ae8adb6ee3651bd75acbaaedff86a08912/tests/python/gaia-ui-tests/gaiatest/gaia_test.py js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) self._marionette.import_script(js) js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_data_layer.js")) self._marionette.set_context(self._marionette.CONTEXT_CHROME) self._marionette.import_script(js) self._marionette.set_context(self._marionette.CONTEXT_CONTENT) # C:\Users\Jun-Wei\Desktop\b2g\battery\manifest.webapp #app = GaiaApps(self._marionette).launch(self._app_name) #app = GaiaApps(self._marionette).launch('Battery', manifest_url='C:/Users/Jun-Wei/Desktop/b2g/battery/manifest.webapp', entry_point='/index.html') app = GaiaApps(self._marionette).launch('Battery') print app.frame print app.src print app.origin print app.name #print g_app.manifest_url #self._app_frame = g_app.frame self._app_frame_id = app.frame self._app_src = app.src self._app_origin = app.origin #self.app_manifest_url = g_app.manifest_url #self.gaia_apps = GaiaApps(self.__marionette) #print self.gaia_apps.displayed_app.name #print self.gaia_apps.installed_apps #print self.gaia_apps.running_apps() #js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) #self.__marionette.import_script(js) ''' def fire_event(self, clickable): logger.info('fire_event: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) try: # id staring with DomAnalyzer.serial_prefix is given by our monkey and should be ignored when locating if clickable.get_id() and not clickable.get_id().startswith( DomAnalyzer.serial_prefix): self._marionette.find_element('id', clickable.get_id()).tap() elif clickable.get_xpath(): self._marionette.find_element('xpath', clickable.get_xpath()).tap() else: logger.error( 'No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info( 'Element is not interactable in fire_event(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) except Exception as e: logger.error( 'Unknown Exception: %s in fire_event(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath()) sys.exit() def fill_form(self, clickable): for f in clickable.get_forms(): for input_field in f.get_inputs(): try: if input_field.get_id() and not input_field.get_id( ).startswith(DomAnalyzer.serial_prefix): self._marionette.find_element( 'id', input_field.get_id()).send_keys( input_field.get_value()) elif input_field.get_xpath(): self._marionette.find_element( 'xpath', input_field.get_xpath()).send_keys( input_field.get_value()) else: logger.error( 'No id nor xpath for an input field in the form id: %s (xpath: %s)', f.get_id(), f.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info( 'Element is not interactable in fill_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath()) except Exception as e: logger.error( 'Unknown Exception: %s in fill_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath()) sys.exit() def empty_form(self, clickable): for f in clickable.get_forms(): for input_field in f.get_inputs(): try: if input_field.get_id() and not input_field.get_id( ).startswith(DomAnalyzer.serial_prefix): self._marionette.find_element( 'id', input_field.get_id()).clear() elif input_field.get_xpath(): self._marionette.find_element( 'xpath', input_field.get_xpath()).clear() else: logger.error( 'No id nor xpath for an input field in the form %s (%s)', f.get_id(), f.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info( 'Element is not interactable in empty_form(): id: %s (xpath: %s)', f.get_id(), f.get_xpath()) except Exception as e: logger.error( 'Unknown Exception: %s in empty_form(): id: %s (xpath: %s)', str(e), f.get_id(), f.get_xpath()) sys.exit() def get_source(self): return self._marionette.page_source.encode(sys.stdout.encoding, 'ignore') def get_screenshot(self, clickable=None): element = None if clickable: try: if clickable.get_id() and not clickable.get_id().startswith( DomAnalyzer.serial_prefix): element = self._marionette.find_element( 'id', clickable.get_id()) elif clickable.get_xpath(): element = self._marionette.find_element( 'xpath', clickable.get_xpath()) else: logger.error( 'No id nor xpath for the clickable: id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) sys.exit() except (ElementNotVisibleException, InvalidElementStateException, NoSuchElementException): logger.info( 'Element is not interactable in get_screenshot(): id: %s (xpath: %s)', clickable.get_id(), clickable.get_xpath()) except Exception as e: logger.error( 'Unknown Exception: %s in get_screenshot(): id: %s (xpath: %s)', str(e), clickable.get_id(), clickable.get_xpath()) sys.exit() if not element: # set context to CHROME to capture whole screen # system frame e.g. FileNotFound cannot be captured without CONTEXT_CHROME (Don't know why) self._marionette.set_context(self._marionette.CONTEXT_CHROME) screenshot = self._marionette.screenshot(element) self._marionette.set_context(self._marionette.CONTEXT_CONTENT) return screenshot def switch_to_frame(self, by, frame_str): """ :param by: options: "id", "xpath", "link text", "partial link text", "name", "tag name", "class name", "css selector", "anon attribute" """ # self.switch_to_top_frame() frame = self._marionette.find_element(by, frame_str) self._marionette.switch_to_frame(frame) def switch_to_top_frame(self): self._marionette.switch_to_frame() # switch to the top-level frame def restart_app(self): # remember to disable screen timeout and screen lock before testing # todo: open b2g simulator, install app, # unlock_screen # self._marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();') self.kill_all_apps() # kill_all_apps() will also kill the 'homescreen app' on real device # so trigger a home event to restore homescreen if self.device: self._dispatch_home_button_event() self.clear_data() self.touch_home_button() # launch the app self._gaia_apps.launch(self._app_name) ''' Deprecated if self.device: icon = self._marionette.find_element('xpath', "//li[contains(@aria-label, '" + self._app_name + "')]") else: icon = self._marionette.find_element('xpath', "//div[contains(@class, 'icon')]//span[contains(text(),'" + self._app_name + "')]") icon.tap() ''' time.sleep(5) # wait for app screen self._marionette.switch_to_frame() # this wait seems not working, need to find another useful one Wait(self._marionette).until(lambda m: m.find_element( 'css selector', "iframe[data-url*='" + self._app_id + "']"). is_displayed()) app_frame = self._marionette.find_element( 'css selector', "iframe[data-url*='" + self._app_id + "']") self._marionette.switch_to_frame(app_frame) def touch_home_button(self): # ref: https://github.com/mozilla-b2g/gaia/blob/master/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L751 apps = self._gaia_apps if apps.displayed_app.name.lower() != 'homescreen': # touching home button will return to homescreen self._dispatch_home_button_event() Wait(self._marionette).until( lambda m: apps.displayed_app.name.lower() == 'homescreen') apps.switch_to_displayed_app() else: apps.switch_to_displayed_app() mode = self._marionette.find_element(By.TAG_NAME, 'body').get_attribute('class') self._dispatch_home_button_event() apps.switch_to_displayed_app() if 'edit-mode' in mode: # touching home button will exit edit mode Wait(self._marionette).until(lambda m: m.find_element( By.TAG_NAME, 'body').get_attribute('class') != mode) else: # touching home button inside homescreen will scroll it to the top Wait(self._marionette).until(lambda m: m.execute_script( "return window.wrappedJSObject.scrollY") == 0) def _dispatch_home_button_event(self): self._gaia_device._dispatch_home_button_event() ''' Deprecated self._marionette.switch_to_frame() self._marionette.execute_script("window.wrappedJSObject.dispatchEvent(new Event('home'));") ''' time.sleep(0.5) def clear_data(self): # for now, clear contact data # https://github.com/mozilla-b2g/gaia/blob/v2.2/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L208 self._marionette.set_context(self._marionette.CONTEXT_CHROME) result = self._marionette.execute_async_script( 'return GaiaDataLayer.removeAllContacts();') assert result, 'Unable to remove all contacts' self._marionette.set_context(self._marionette.CONTEXT_CONTENT) time.sleep(0.5) def kill_all_apps(self): self._marionette.switch_to_frame() self._marionette.execute_async_script(""" // Kills all running apps, except the homescreen. function killAll() { let manager = window.wrappedJSObject.appWindowManager; let apps = manager.getApps(); for (let id in apps) { let origin = apps[id].origin; if (origin.indexOf('verticalhome') == -1) { manager.kill(origin); } } }; killAll(); // return true so execute_async_script knows the script is complete marionetteScriptFinished(true); """) time.sleep(0.5)
def prepare_app(self): apps = GaiaApps(self.device.marionette) apps.set_permission('Camera', 'geolocation', 'deny')
class EidetickerB2GMixin(EidetickerMixin): """B2G-specific extensions to the eideticker mixin""" marionette = None _devicePixelRatio = None def setupMarionette(self): self.marionette = marionette.Marionette() self._logger.info("Waiting for Marionette...") self.marionette.wait_for_port() self._logger.info("Marionette ready, starting session") self.marionette.start_session() if 'b2g' not in self.marionette.session: raise mozdevice.DMError( "bad session value %s returned by start_session" % self.marionette.session) self.marionette.set_script_timeout(60000) self.marionette.timeouts(self.marionette.TIMEOUT_SEARCH, 10000) self._logger.info("Marionette ready!") self.b2gpopulate = B2GPopulate(self.marionette) self.gaiaApps = GaiaApps(self.marionette) self.gaiaData = GaiaData(self.marionette) self.gaiaDevice = GaiaDevice(self.marionette) self.gaiaCompat = GaiaCompat() def connectWIFI(self, wifiSettings): """ Tries to connect to the wifi network """ self._logger.info("Setting up wifi...") self.gaiaData.connect_to_wifi(wifiSettings) self._logger.info("WIFI ready!") def cleanup(self): self.removeDir('/data/local/storage/persistent') self.removeDir('/data/b2g/mozilla') for item in self.listFiles('/sdcard/'): self.removeDir('/'.join(['/sdcard', item])) def stopB2G(self): self._logger.info("Stopping B2G") if self.marionette and self.marionette.session: self.marionette.delete_session() self.marionette = None self.shellCheckOutput(['stop', 'b2g']) # Wait for a bit to make sure B2G has completely shut down. tries = 100 while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0: tries -= 1 time.sleep(0.1) if tries == 0: raise mozdevice.DMError("Could not kill b2g process") def startB2G(self): self._logger.info("Starting B2G") self.shellCheckOutput(['start', 'b2g']) self.setupMarionette() self.gaiaCompat.wait_for_b2g(self.marionette) # run the fake update checker self.gaiaCompat.supress_update_check(self.marionette) # unlock device, so it doesn't go to sleep self._logger.info("Unlocking screen...") self.gaiaDevice.unlock() # turn off automatic brightness adjustments and set to 100% self.gaiaData.set_setting('screen.automatic-brightness', '') self.gaiaData.set_setting('screen.brightness', 1) # kill running apps so they don't interfere with the test self._logger.info("Killing all running apps...") self.gaiaApps.kill_all() # set correct orientation self._logger.info("Setting orientation") self.marionette.execute_script( "screen.mozLockOrientation('%s');" % self.deviceProperties['defaultOrientation']) def restartB2G(self): """ Restarts the b2g process on the device. """ self.stopB2G() self.startB2G() @property def devicePixelRatio(self): if not self._devicePixelRatio: if self.marionette and self.marionette.session: self._devicePixelRatio = self.marionette.execute_script( 'return window.wrappedJSObject.devicePixelRatio;') return self._devicePixelRatio or 1
def run(self): self.device.gaiaApps.switch_to_displayed_app() # switch to homescreen appicon = None # HACK: Bug 1026527 - perform a no-op swipe before running test to # workaround flame not processing input events properly self.device.executeCommands([['swipe_right']]) try: # look for the application icon in the dock first self.logger.info('Looking for app icon in dock') appicon = self.device.marionette.find_element( By.CSS_SELECTOR, '#footer .icon[aria-label="%s"]' % self.appname) except NoSuchElementException: # skip the everything.me page self.device.marionette.execute_async_script( 'return window.wrappedJSObject.GridManager.goToPage(1, marionetteScriptFinished);') page_count = self.device.marionette.execute_script( 'return window.wrappedJSObject.GridManager.pageHelper.getTotalPagesNumber();') for i in range(1, page_count): current_page = self.device.marionette.find_element( By.CSS_SELECTOR, '#icongrid .page:not([aria-hidden=true])') try: self.logger.info('Looking for app icon on page %s' % (i + 1)) appicon = current_page.find_element( By.CSS_SELECTOR, '.icon[aria-label="%s"]' % self.appname) break except NoSuchElementException: current_page_index = self.device.marionette.execute_script( 'return window.wrappedJSObject.GridManager.pageHelper.getCurrentPageNumber();') if current_page_index < (page_count - 1): self.device.marionette.execute_script( 'window.wrappedJSObject.GridManager.goToNextPage();') Wait(self.device.marionette).until( lambda m: m.find_element(By.TAG_NAME, 'body').get_attribute( 'data-transitioning') != 'true') else: raise TestException("Cannot find icon for app with name " "'%s'" % self.appname) tap_x = appicon.location['x'] + (appicon.size['width'] / 2) tap_y = appicon.location['y'] + (appicon.size['height'] / 2) self.start_capture() self.execute_actions([['tap', tap_x, tap_y]], test_finished_after_actions=False) # wait for the app to be displayed apps = GaiaApps(self.device.marionette) Wait(self.device.marionette).until( lambda m: apps.displayed_app.name.lower() == self.appname.lower()) apps.switch_to_displayed_app() self.wait_for_content_ready() self.logger.info("Content ready. Waiting an additional second to make " "sure it has settled") time.sleep(1) self.test_finished() self.end_capture()