# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import time
from marionette_driver import expected, By, Wait
from marionette_driver.errors import NoSuchElementException
from gaiatest import GaiaApps
from gaiatest import Accessibility
[docs]class Base(object):
DEFAULT_APP_HOSTNAME = '.gaiamobile.org'
DEFAULT_PROTOCOL = 'app://'
def __init__(self, marionette):
self.marionette = marionette
self.apps = GaiaApps(self.marionette)
self.accessibility = Accessibility(self.marionette)
self.frame = None
self.entry_point = hasattr(self, 'entry_point') and self.entry_point or None
[docs] def launch(self, launch_timeout=None):
self.app = self.apps.launch(self.name, self.manifest_url, self.entry_point, launch_timeout=launch_timeout)
[docs] def is_element_present(self, by, locator):
self.marionette.set_search_timeout(0)
try:
self.marionette.find_element(by, locator)
return True
except NoSuchElementException:
return False
finally:
self.marionette.set_search_timeout(self.marionette.timeout or 10000)
[docs] def is_element_displayed(self, by, locator):
self.marionette.set_search_timeout(0)
try:
return self.marionette.find_element(by, locator).is_displayed()
except NoSuchElementException:
return False
finally:
self.marionette.set_search_timeout(self.marionette.timeout or 10000)
[docs] def find_select_item(self, match_string):
_list_item_locator = (By.CSS_SELECTOR, 'section.value-selector-container li label')
# have to go back to top level to get the B2G select box wrapper
self.marionette.switch_to_frame()
# TODO we should find something suitable to wait for, but this goes too
# fast against desktop builds causing intermittent failures
time.sleep(0.2)
Wait(self.marionette).until(expected.element_present(*_list_item_locator))
for item in self.marionette.find_elements(*_list_item_locator):
if match_string == item.text.encode('ascii','ignore').strip():
# We need to keep this because the Ok button may hang over the element and stop
# Marionette from scrolling the element entirely into view
self.marionette.execute_script('arguments[0].scrollIntoView(false);', [item])
return item
[docs] def wait_for_select_closed(self, by, locator):
Wait(self.marionette).until(expected.element_not_displayed(by, locator))
# now back to app
self.apps.switch_to_displayed_app()
# TODO we should find something suitable to wait for, but this goes too
# fast against desktop builds causing intermittent failures
# This sleep is necessary to make sure the select is completely faded out,
# see bug 1148154
time.sleep(1)
[docs] def select(self, match_string, tap_close=True):
# cheeky Select wrapper until Marionette has its own
# due to the way B2G wraps the app's select box we match on text
_close_button_locator = (By.CSS_SELECTOR, 'button.value-option-confirm')
li = self.find_select_item(match_string)
li.tap()
# Tap close and wait for it to hide
if tap_close:
self.marionette.find_element(*_close_button_locator).tap()
self.wait_for_select_closed(*_close_button_locator)
[docs] def a11y_select(self, match_string):
# Accessibility specific select method
_close_button_locator = (By.CSS_SELECTOR, 'button.value-option-confirm')
li = self.find_select_item(match_string)
self.accessibility.click(li)
# A11y click close and wait for it to hide
self.accessibility.click(self.marionette.find_element(*_close_button_locator))
self.wait_for_select_closed(*_close_button_locator)
[docs] def tap_element_from_system_app(self, element=None, add_statusbar_height=False, x=None, y=None):
# Workaround for bug 1109213, where tapping on the button inside the app itself
# makes Marionette spew out NoSuchWindowException errors, see bug 1164078
cx = element.rect['x']
cy = element.rect['y']
cx += element.rect['width']//2 if x is None else x
cy += element.rect['height']//2 if y is None else y
from gaiatest.apps.system.app import System
system = System(self.marionette)
if add_statusbar_height:
cy = cy + system.status_bar.height
system.tap(cx, cy)
@property
def keyboard(self):
from gaiatest.apps.keyboard.app import Keyboard
return Keyboard(self.marionette)
@property
def manifest_url(self):
return '{}{}{}/manifest.webapp'.format(self.DEFAULT_PROTOCOL, self.__class__.__name__.lower(), self.DEFAULT_APP_HOSTNAME)
@property
def is_displayed(self):
return (self.apps.displayed_app.manifest_url == self.manifest_url and
self.apps.displayed_app.entry_point == self.entry_point)
[docs] def wait_to_be_displayed(self):
Wait(self.marionette).until(lambda m: self.is_displayed == True)
[docs] def wait_to_not_be_displayed(self):
Wait(self.marionette).until(lambda m: self.is_displayed == False)