Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,137 @@
# 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/.
from marionette_driver import expected, By, Wait
from marionette_driver.marionette import Actions
from gaiatest.apps.base import Base
class System(Base):
# status bar
_status_bar_locator = (By.ID, 'statusbar')
_gripper_locator = (By.ID, 'tray-invisible-gripper')
_utility_tray_locator = (By.ID, 'utility-tray')
_system_banner_locator = (By.CSS_SELECTOR, '#screen > gaia-toast.banner')
_notification_toaster_locator = (By.ID, 'notification-toaster')
_update_manager_toaster_locator = (By.ID, 'update-manager-toaster')
_software_home_button_locator = (By.ID, 'software-home-button')
_software_buttons_locator = (By.ID, 'software-buttons')
_screen_locator = (By.ID, 'screen')
_search_bar_locator = (By.CSS_SELECTOR, '[data-l10n-id="search-or-enter-address"]')
@property
def status_bar(self):
self.marionette.switch_to_frame()
from gaiatest.apps.system.regions.status_bar import StatusBar
element = self.marionette.find_element(*self._status_bar_locator)
return StatusBar(self.marionette, element)
def wait_for_status_bar_displayed(self):
Wait(self.marionette).until(expected.element_displayed(*self._status_bar_locator))
# A lot of tests, like mail or call received, need a longer timeout here
def wait_for_notification_toaster_displayed(self, timeout=30, message=None, for_app=None):
self.marionette.switch_to_frame()
el = self.marionette.find_element(*self._notification_toaster_locator)
Wait(self.marionette, timeout).until(expected.element_displayed(el), message=message)
if for_app is not None:
Wait(self.marionette, timeout).until(lambda m:
for_app in el.get_attribute('data-notification-id'), message=message)
def wait_for_notification_toaster_not_displayed(self, timeout=10):
self.marionette.switch_to_frame()
Wait(self.marionette, timeout).until(
expected.element_not_displayed(*self._notification_toaster_locator))
def wait_for_system_banner_displayed(self):
self.marionette.switch_to_frame()
Wait(self.marionette).until(expected.element_displayed(*self._system_banner_locator))
def wait_for_system_banner_not_displayed(self):
self.marionette.switch_to_frame()
Wait(self.marionette).until(
expected.element_not_displayed(*self._system_banner_locator))
def wait_for_software_home_button_displayed(self, timeout=10, message=None):
self.marionette.switch_to_frame()
Wait(self.marionette, timeout=timeout).until(
expected.element_displayed(*self._software_home_button_locator), message)
def wait_for_software_home_button_not_displayed(self, timeout=10):
self.marionette.switch_to_frame()
Wait(self.marionette, timeout=timeout).until(
expected.element_not_displayed(*self._software_home_button_locator))
def open_utility_tray(self):
self.marionette.switch_to_frame()
body = self.marionette.find_element(By.TAG_NAME, 'body')
gripper = self.marionette.find_element(*self._gripper_locator)
gripper_x = int(gripper.rect['width']/2)
gripper_y = int(gripper.rect['y'])
gripper_y_end = int(body.rect['height'])
Actions(self.marionette).flick(gripper, gripper_x, gripper_y, gripper_x, gripper_y_end).perform()
from gaiatest.apps.system.regions.utility_tray import UtilityTray
utility_tray = UtilityTray(self.marionette)
utility_tray.wait_for_dropped_down()
return utility_tray
def tap(self, x=None, y=None):
self.marionette.switch_to_frame()
self.marionette.find_element(*self._screen_locator).tap(x, y)
# As we have trouble disabling the app update toaster these methods
# may be used to wait for it when we know it may interfere
@property
def is_app_update_notification_displayed(self):
self.marionette.switch_to_frame()
update_manager_toaster = self.marionette.find_element(*self._update_manager_toaster_locator)
return update_manager_toaster.location['y'] > (0 - update_manager_toaster.size['height'])
def wait_for_app_update_to_clear(self):
self.marionette.switch_to_frame()
element = self.marionette.find_element(*self._update_manager_toaster_locator)
Wait(self.marionette).until(lambda m: element.location['y'] == (0 - element.size['height']))
@property
def screen_width(self):
self.marionette.switch_to_frame()
return self.marionette.find_element(*self._screen_locator).rect['width']
@property
def screen_height_without_software_home_button(self):
self.marionette.switch_to_frame()
return self.marionette.find_element(*self._screen_locator).rect['height'] - self.software_buttons_height
@property
def software_buttons_height(self):
"""
Gets the height of the software buttons container on the screen.
Always returns 0 if software buttons are not displayed.
"""
self.marionette.switch_to_frame()
if 'software-button-enabled' in self.marionette.find_element(*self._screen_locator).get_attribute('class'):
return self.marionette.find_element(*self._software_buttons_locator).size['height']
else:
return 0
@property
def wallpaper_properties(self):
# The wallpaper returns a blob url and a gradient
self.marionette.switch_to_frame()
screen = self.marionette.find_element(*self._screen_locator)
return screen.value_of_css_property('background-image')
def tap_search_bar(self):
self.marionette.switch_to_frame()
self.marionette.find_element(*self._search_bar_locator).tap()
from gaiatest.apps.system.regions.search_panel import SearchPanel
return SearchPanel(self.marionette)

View file

@ -0,0 +1,116 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
class Activities(Base):
_actions_menu_locator = (By.CSS_SELECTOR, 'form[data-type="action"]')
_action_option_locator = (By.CSS_SELECTOR, 'form[data-type="action"] button')
_activity_window_locator = (By.CLASS_NAME, 'activityWindow')
_wallpaper_button_locator = (By.XPATH, "//*[text()='Wallpaper']")
_gallery_button_locator = (By.XPATH, '//*[text()="Gallery"]')
_camera_button_locator = (By.XPATH, '//*[text()="Camera"]')
_messages_button_locator = (By.XPATH, '//*[text()="Messages"]')
_ringtones_button_locator = (By.XPATH, '//*[text()="Ringtones"]')
_cancel_button_locator = (By.CSS_SELECTOR, 'form[data-type="action"] button[data-action="cancel"]')
_save_image_locator = (By.CSS_SELECTOR, 'button[data-id="save-image"]')
def __init__(self, marionette):
Base.__init__(self, marionette)
self.marionette.switch_to_frame()
view = self.marionette.find_element(*self._actions_menu_locator)
Wait(self.marionette).until(lambda m: view.location['y'] == 0)
def tap_wallpaper(self):
Wait(self.marionette).until(
expected.element_displayed(*self._actions_menu_locator))
self.marionette.find_element(*self._wallpaper_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(*self._actions_menu_locator))
from gaiatest.apps.wallpaper.app import Wallpaper
wallpaper = Wallpaper(self.marionette)
wallpaper.wait_to_be_displayed()
self.apps.switch_to_displayed_app()
return wallpaper
def tap_gallery(self):
actions_menu = Wait(self.marionette).until(
expected.element_present(*self._actions_menu_locator))
Wait(self.marionette).until(
expected.element_displayed(actions_menu))
self.marionette.find_element(*self._gallery_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(actions_menu))
from gaiatest.apps.gallery.app import Gallery
gallery = Gallery(self.marionette)
gallery.wait_to_be_displayed()
self.apps.switch_to_displayed_app()
return gallery
def tap_camera(self):
actions_menu = Wait(self.marionette).until(
expected.element_present(*self._actions_menu_locator))
Wait(self.marionette).until(
expected.element_displayed(actions_menu))
self.marionette.find_element(*self._camera_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(actions_menu))
from gaiatest.apps.camera.app import Camera
camera = Camera(self.marionette)
camera.wait_to_be_displayed()
self.apps.switch_to_displayed_app()
camera.wait_for_capture_ready()
return camera
def tap_cancel(self):
actions_menu = Wait(self.marionette).until(
expected.element_present(*self._actions_menu_locator))
Wait(self.marionette).until(
expected.element_displayed(actions_menu))
self.marionette.find_element(*self._cancel_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(actions_menu))
self.apps.switch_to_displayed_app()
def tap_save_image(self):
element = Wait(self.marionette).until(
expected.element_present(*self._save_image_locator))
Wait(self.marionette).until(expected.element_displayed(element))
element.tap()
@property
def options_count(self):
return len(self.marionette.find_elements(*self._action_option_locator))
@property
def is_menu_visible(self):
return self.is_element_displayed(*self._actions_menu_locator)
def share_to_messages(self):
actions_menu = Wait(self.marionette).until(
expected.element_present(*self._actions_menu_locator))
Wait(self.marionette).until(
expected.element_displayed(actions_menu))
self.marionette.find_element(*self._messages_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(actions_menu))
from gaiatest.apps.messages.regions.new_message import NewMessage
return NewMessage(self.marionette)
def share_to_ringtones(self):
actions_menu = Wait(self.marionette).until(
expected.element_present(*self._actions_menu_locator))
Wait(self.marionette).until(
expected.element_displayed(actions_menu))
self.marionette.find_element(*self._ringtones_button_locator).tap()
Wait(self.marionette).until(
expected.element_not_displayed(actions_menu))
from gaiatest.apps.ring_tone.app import RingTone
return RingTone(self.marionette)

View file

@ -0,0 +1,141 @@
# 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/.
from marionette_driver import expected, By, Wait
from marionette_driver.marionette import Actions
from gaiatest.apps.base import PageRegion
class CardsView(PageRegion):
_root_locator = (By.ID, 'task-manager')
_card_locator = (By.CSS_SELECTOR, '#cards-view .card')
_cards_no_recent_windows_locator = (By.ID, 'cards-no-recent-windows')
_new_private_sheet_locator = (By.ID, 'task-manager-new-private-sheet-button')
_new_sheet_locator = (By.ID, 'task-manager-new-sheet-button')
# Check that the origin contains the current app name, origin is in the format:
# app://clock.gaiamobile.org
# This locator is used by is_app_a11y_visible
_apps_cards_locator = (By.CSS_SELECTOR, '#cards-view li[data-origin*="%s"]')
def __init__(self, marionette):
marionette.switch_to_frame()
root = marionette.find_element(*self._root_locator)
PageRegion.__init__(self, marionette, root)
def open_new_browser(self):
self.root_element.find_element(*self._new_sheet_locator).tap()
self.wait_for_cards_view_not_displayed()
from gaiatest.apps.search.app import Search
return Search(self.marionette)
def open_new_private_window(self):
self.root_element.find_element(*self._new_private_sheet_locator).tap()
self.wait_for_cards_view_not_displayed()
from gaiatest.apps.search.regions.browser import PrivateWindow
return PrivateWindow(self.marionette)
@property
def cards(self):
return [Card(self.marionette, card)
for card in self.root_element.find_elements(*self._card_locator)]
@property
def is_displayed(self):
return self.is_element_displayed(*self._root_locator)
@property
def is_no_card_displayed(self):
return (self.root_element.is_displayed() and
self.root_element.find_element(*self._cards_no_recent_windows_locator).is_displayed())
def wait_for_no_card_displayed(self):
Wait(self.marionette).until(lambda m: self.is_no_card_displayed)
@property
def is_cards_view_a11y_hidden(self):
return self.accessibility.is_hidden(self.root_element)
def is_app_a11y_visible(self, app):
return self.accessibility.is_visible(self.root_element.find_element(
*self._app_cards_locator(app)))
def is_app_a11y_hidden(self, app):
return self.accessibility.is_hidden(self.root_element.find_element(
*self._app_cards_locator(app)))
def a11y_wheel_cards_view(self, direction):
self.accessibility.wheel(self.root_element, direction)
def wait_for_cards_view(self):
Wait(self.marionette).until(
lambda m: self.root_element.get_attribute('class') == 'active')
def wait_for_cards_view_not_displayed(self):
Wait(self.marionette).until(
expected.element_not_displayed(self.root_element))
def swipe_to_previous_app(self):
current_frame = self.apps.displayed_app.frame
final_x_position = current_frame.rect['width'] // 2
start_y_position = current_frame.rect['height'] // 2
# swipe forward to get previous app card
Actions(self.marionette).flick(
current_frame, 0, start_y_position, final_x_position, start_y_position).perform()
class Card(PageRegion):
_close_button_locator = (By.CLASS_NAME, 'close-button')
_screenshot_view_locator = (By.CLASS_NAME, 'screenshotView')
_app_icon_locator = (By.CLASS_NAME, 'appIcon')
_title_locator = (By.CLASS_NAME, 'title')
_subtitle_locator = (By.CLASS_NAME, 'subtitle')
_close_buttons_locator = (By.CSS_SELECTOR, '.close-button')
@property
def title(self):
return self.root_element.find_element(*self._title_locator).text
@property
def subtitle(self):
return self.root_element.find_element(*self._subtitle_locator).text
@property
def is_displayed(self):
return self.root_element.is_displayed()
@property
def manifest_url(self):
return self.root_element.get_attribute('data-origin')
@property
def is_centered(self):
screen_width = int(self.marionette.execute_script('return window.innerWidth'))
left = self.root_element.rect['x']
width = self.root_element.rect['width']
# center of card should be within 1px of viewport center
return 1 >= abs(screen_width / 2 - (left + width / 2))
def wait_for_centered(self):
Wait(self.marionette).until(lambda m: self.is_centered)
def tap(self):
self.root_element.tap()
def close(self):
self.wait_for_centered()
self.root_element.find_element(*self._close_button_locator).tap()
def a11y_click_close_button(self):
self.accessibility.click(self.root_element.find_element(*self._close_button_locator))
def a11y_click_screenshot_view(self):
self.accessibility.click(self.root_element.find_element(*self._screenshot_view_locator))
def a11y_click_app_icon(self):
self.accessibility.click(self.root_element.find_element(*self._app_icon_locator))

View file

@ -0,0 +1,58 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
from gaiatest.form_controls.binarycontrol import GaiaBinaryControl
from gaiatest.apps.search.regions.browser import Browser
class TrackingDialog(PageRegion):
_tracking_notice_locator = (By.ID, 'tracking-notice')
_tracking_protection_toggle_locator = (By.ID, 'tracking-protection-toggle')
_tracking_notice_learn_more_locator = (By.ID, 'tracking-notice-learn-more')
_tracking_notice_confirm_locator = (By.ID, 'tracking-notice-confirm')
def __init__(self, marionette):
marionette.switch_to_frame()
root = Wait(marionette).until(
expected.element_present(*self._tracking_notice_locator))
Wait(marionette).until(expected.element_displayed(root))
PageRegion.__init__(self, marionette, root)
@property
def is_displayed(self):
return self.root_element.is_displayed()
@property
def is_present(self):
self.marionette.switch_to_frame()
from gaiatest.apps.system.app import System
return System(self.marionette).is_element_present(*self._tracking_notice_locator)
def open_learn_more(self):
self.root_element.find_element(*self._tracking_notice_learn_more_locator).tap()
return Browser(self.marionette)
@property
def _tracking_protection_switch(self):
return GaiaBinaryControl(
self.marionette, self.root_element.find_element(*self._tracking_protection_toggle_locator))
@property
def is_tracking_protection_enabled(self):
self._tracking_protection_switch.is_checked
def enable_tracking_protection(self):
self._tracking_protection_switch.enable()
def disable_tracking_protection(self):
self._tracking_protection_switch.disable()
def close_tracking_protection_dialog(self):
self.root_element.find_element(*self._tracking_notice_confirm_locator).tap()
return Browser(self.marionette)

View file

@ -0,0 +1,102 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
class FirefoxAccount(Base):
_email_field_locator = (By.ID, 'fxa-email-input')
_next_locator = (By.ID, 'fxa-module-next')
_password_locator = (By.ID, 'fxa-pw-input')
_done_locator = (By.ID, 'fxa-module-done')
_fxa_iframe_locator = (By.ID, 'fxa-iframe')
_email_page_locator = (By.ID, 'fxa-email')
_password_page_locator = (By.ID, 'fxa-enter-password')
_success_signin_page_locator = (By.ID, 'fxa-signin-success')
_unverified_login_page_locator = (By.ID, 'fxa-signup-success')
_password_error_locator = (By.ID, 'fxa-error-overlay')
_password_error_close_locator = (By.ID, 'fxa-error-ok')
def __init__(self, marionette):
Base.__init__(self, marionette)
self._switch_to_fxa_iframe()
input_field = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._email_page_locator))
Wait(self.marionette).until(expected.element_displayed(input_field))
Wait(self.marionette).until(lambda m: input_field.rect['x'] == 0)
def _switch_to_fxa_iframe(self):
self.marionette.switch_to_frame()
iframe = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._fxa_iframe_locator))
Wait(self.marionette).until(expected.element_displayed(iframe))
Wait(self.marionette, timeout=60).until(lambda m: iframe.get_attribute('data-url') != 'about:blank')
self.marionette.switch_to_frame(iframe)
def enter_email(self, email=None):
self._switch_to_fxa_iframe()
email_field = self.marionette.find_element(*self._email_field_locator)
email_field.send_keys(email)
# Wait until the keyboard is completely displayed, otherwise tapping
# the next button is unreliable
self.marionette.switch_to_frame()
Wait(self.marionette).until(lambda m: self.keyboard.is_keyboard_displayed)
self._switch_to_fxa_iframe()
self.marionette.find_element(*self._next_locator).tap()
passwd_page = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._password_page_locator))
Wait(self.marionette).until(expected.element_displayed(passwd_page))
Wait(self.marionette).until(lambda m: passwd_page.rect['x'] == 0)
def enter_password(self, password=None):
self._switch_to_fxa_iframe()
passwd_field = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._password_locator))
passwd_field.send_keys(password)
# Wait until the keyboard is completely displayed, otherwise tapping
# the next button is unreliable
self.marionette.switch_to_frame()
Wait(self.marionette).until(lambda m: self.keyboard.is_keyboard_displayed)
self._switch_to_fxa_iframe()
self.marionette.find_element(*self._next_locator).tap()
def wait_for_password_error(self):
self._switch_to_fxa_iframe()
done = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._password_error_locator))
Wait(self.marionette).until(expected.element_displayed(done))
Wait(self.marionette).until(lambda m: done.rect['x'] == 0)
def close_password_error(self):
self._switch_to_fxa_iframe()
self.marionette.find_element(*self._password_error_close_locator).tap()
def wait_for_unverified_login(self):
self._switch_to_fxa_iframe()
signed_in_page = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._unverified_login_page_locator))
Wait(self.marionette).until(expected.element_displayed(signed_in_page))
Wait(self.marionette).until(lambda m: signed_in_page.rect['x'] == 0)
def wait_for_successful_login(self):
self._switch_to_fxa_iframe()
signed_in_page = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._success_signin_page_locator))
Wait(self.marionette).until(expected.element_displayed(signed_in_page))
Wait(self.marionette).until(lambda m: signed_in_page.rect['x'] == 0)
def tap_done(self):
self._switch_to_fxa_iframe()
done = Wait(self.marionette, timeout=60).until(
expected.element_present(*self._done_locator))
Wait(self.marionette).until(expected.element_displayed(done))
done.tap()
#Switch back to the settings app
self.apps.switch_to_displayed_app()

View file

@ -0,0 +1,51 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
class IacPublisher(Base):
name = "Test IAC Publisher"
manifest_url = '{}test-iac-publisher{}/manifest.webapp'.format(Base.DEFAULT_PROTOCOL,Base.DEFAULT_APP_HOSTNAME)
_pub_app_msg_to_send_locator = (By.ID, "msgToSend")
_pub_app_send_button_locator = (By.ID, "sendButton")
_pub_app_num_conns_locator = (By.ID, "numConns")
_pub_app_received_str_msg_locator = (By.ID, "receivedStrMsg")
_pub_app_received_blob_msg_locator = (By.ID, "receivedBlobMsg")
def launch(self):
Base.launch(self, launch_timeout=120000)
Wait(self.marionette).until(
expected.element_displayed(*self._pub_app_msg_to_send_locator))
def type_message(self, value):
message_field = self.marionette.find_element(*self._pub_app_msg_to_send_locator)
message_field.tap()
message_field.clear()
message_field.send_keys(value)
def tap_send_message(self):
self.marionette.find_element(*self._pub_app_send_button_locator).tap()
def wait_for_message_received(self):
Wait(self.marionette).until(
expected.element_present(*self._pub_app_received_str_msg_locator))
Wait(self.marionette).until(
expected.element_present(*self._pub_app_received_blob_msg_locator))
@property
def received_str_message(self):
return self.marionette.find_element(*self._pub_app_received_str_msg_locator).get_attribute('value')
@property
def received_blob_message(self):
return self.marionette.find_element(*self._pub_app_received_blob_msg_locator).get_attribute('value')
@property
def number_of_connections(self):
return self.marionette.find_element(*self._pub_app_num_conns_locator).get_attribute('value')

View file

@ -0,0 +1,110 @@
# 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 urllib
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
# Bug 1216626 - Regions should inherit from PageRegion, not Base
class SearchPanel(Base):
_search_results_app_frame_locator = (By.CSS_SELECTOR, '.searchWindow.active iframe')
_search_results_locator = (By.CSS_SELECTOR, 'gaia-grid .icon')
_search_suggestion_ok_button_locator = (By.ID, 'suggestions-notice-confirm')
_rocketbar_input_locator = (By.ID, 'rocketbar-input')
_search_results_offline_locator = (By.ID, 'offline-message')
_search_results_offline_settings_locator = (By.ID, 'settings-connectivity')
_link_results_locator = (By.CSS_SELECTOR, '#suggestions li')
def _switch_to_search_results_frame(self):
self.marionette.switch_to_frame()
self.marionette.switch_to_frame(self.marionette.find_element(*self._search_results_app_frame_locator))
@property
def offline_search_message(self):
return self.marionette.find_element(*self._search_results_offline_locator).text
@property
def is_offline_message_visible(self):
return self.is_element_displayed(*self._search_results_offline_locator)
def tap_offline_settings_button(self):
self.marionette.find_element(*self._search_results_offline_settings_locator).tap()
from gaiatest.apps.settings.app import Settings
settings = Settings(self.marionette)
settings.switch_to_settings_app()
return settings
def type_into_search_box(self, search_term):
self.keyboard.send(search_term)
# The search results frame is not findable with AppWindowManager
self._switch_to_search_results_frame()
def go_to_url(self, url):
# If a URL exists already, clear the field
self.marionette.find_element(*self._rocketbar_input_locator).clear()
self.keyboard.send(url)
#TODO Remove hack once Bug 1062309 is fixed
self.marionette.switch_to_frame()
Wait(self.marionette).until(lambda m: not self.keyboard.is_keyboard_displayed)
self.marionette.find_element(*self._rocketbar_input_locator).tap()
Wait(self.marionette).until(lambda m: self.keyboard.is_keyboard_displayed)
self.keyboard.tap_enter()
if 'http' in urllib.quote(url, safe=':/?=&~').lower():
Wait(self.marionette).until(lambda m: self.apps.displayed_app.name in urllib.quote(url, safe=':/?=&~'))
from gaiatest.apps.search.regions.browser import Browser
return Browser(self.marionette)
def wait_for_search_results_to_load(self, minimum_expected_results=1):
Wait(self.marionette).until(lambda m: len(m.find_elements(
*self._search_results_locator)) > minimum_expected_results)
def confirm_suggestion_notice(self):
confirm = Wait(self.marionette).until(expected.element_present(
*self._search_suggestion_ok_button_locator))
Wait(self.marionette).until(expected.element_displayed(confirm))
confirm.tap()
Wait(self.marionette).until(expected.element_not_displayed(confirm))
def _is_result_a_webapp(self, result_element):
# An app result is to an installable (via marketplace) webapp
return '.webapp' in result_element.get_attribute('data-identifier')
@property
def app_results(self):
# An app result is to an installable (via marketplace) webapp
return [self.Result(marionette=self.marionette, element=result)
for result in self.marionette.find_elements(*self._search_results_locator)
if self._is_result_a_webapp(result)]
@property
def link_results(self):
return [self.Result(marionette=self.marionette, element=result)
for result in self.marionette.find_elements(*self._link_results_locator)]
class Result(PageRegion):
@property
def name(self):
return self.root_element.text
def tap(self):
app_name = self.name
self.root_element.tap()
# Wait for the displayed app to be that we have tapped
Wait(self.marionette).until(lambda m: self.apps.displayed_app.name == app_name)
self.apps.switch_to_displayed_app()
# Wait for title to load (we cannot be more specific because the aut may change)
Wait(self.marionette).until(lambda m: bool(m.title))

View file

@ -0,0 +1,39 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
class SleepScreen(Base):
_sleep_menu_locator = (By.ID, "sleep-menu")
_menu_items_locator = (By.CSS_SELECTOR, "#sleep-menu-container > section > ul > li")
_cancel_button_locator = (By.CSS_SELECTOR, "#sleep-menu-container > gaia-buttons > button")
@property
def is_menu_visible(self):
return self.is_element_displayed(*self._sleep_menu_locator)
def wait_for_sleep_menu_visible(self):
Wait(self.marionette).until(expected.element_displayed(*self._sleep_menu_locator))
def tap_cancel_button(self):
self.marionette.find_element(*self._cancel_button_locator).tap()
@property
def menu_items(self):
return [self.MenuItem(self.marionette, item)
for item in self.marionette.find_elements(*self._menu_items_locator)]
class MenuItem(PageRegion):
@property
def name(self):
return self.root_element.text
def tap(self):
self.root_element.tap()

View file

@ -0,0 +1,84 @@
# 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/.
from marionette_driver import By, Wait
from marionette_driver.errors import StaleElementException
from gaiatest.apps.base import PageRegion
class StatusBar(PageRegion):
_time_locator = (By.ID, 'statusbar-time')
_battery_locator = (By.ID, 'statusbar-battery')
_mobile_connection_locator = (By.ID, 'statusbar-mobile-connection')
_data_connection = (By.CSS_SELECTOR, '#statusbar-mobile-connection .statusbar-data')
_geolocation_locator = (By.ID, 'statusbar-geolocation')
_airplane_mode_locator = (By.ID, 'statusbar-airplane-mode')
@property
def height(self):
if self.is_displayed:
return self.root_element.rect['height']
else:
return 0
@property
def is_displayed(self):
return self.root_element.is_displayed() and self.root_element.rect['y'] == 0
@property
def is_status_bar_maximized_wrapper_a11y_hidden(self):
return self.accessibility.is_hidden(self.marionette.find_element(
*self._status_bar_maximized_locator))
@property
def is_status_bar_minimized_wrapper_a11y_hidden(self):
return self.accessibility.is_hidden(self.marionette.find_element(
*self._status_bar_minimized_locator))
@property
def time(self):
return self.root_element.find_element(*self._time_locator).text
@property
def is_time_displayed(self):
battery_icon = self.root_element.find_element(*self._time_locator)
return battery_icon.is_displayed()
@property
def is_battery_displayed(self):
battery_icon = self.root_element.find_element(*self._battery_locator)
return battery_icon.is_displayed()
@property
def is_mobile_connection_displayed(self):
element = self.root_element.find_element(*self._mobile_connection_locator)
return element.is_displayed()
def wait_for_data_to_be_connected(self):
Wait(self.marionette).until(lambda m: self.is_data_connected)
@property
def is_data_connected(self):
element = self.root_element.find_element(*self._data_connection)
return element.get_attribute('hidden') != 'true'
@property
def is_geolocation_displayed(self):
element = self.root_element.find_element(*self._geolocation_locator)
return element.is_displayed()
def wait_for_geolocation_icon_displayed(self):
Wait(self.marionette).until(lambda m: self.is_geolocation_displayed)
@property
def is_airplane_mode_displayed(self):
element = self.root_element.find_element(*self._airplane_mode_locator)
return element.is_displayed()
def wait_for_airplane_mode_icon_displayed(self):
Wait(self.marionette).until(lambda m: self.is_airplane_mode_displayed)
def a11y_wheel_status_bar_time(self):
self.accessibility.wheel(self.root_element.find_element(*self._time_locator), 'down')

View file

@ -0,0 +1,57 @@
# 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.marionette import Actions
from gaiatest.apps.base import Base
class TimePicker(Base):
_time_picker_locator = (By.CLASS_NAME, 'value-selector-time-picker')
_done_button_locator = (By.CSS_SELECTOR, '.value-selector-time-picker-buttons > button.value-selector-confirm')
_hour_picker_locator = (By.CLASS_NAME, 'value-picker-hours')
_minutes_picker_locator = (By.CLASS_NAME, 'value-picker-minutes')
_hour24_picker_locator = (By.CLASS_NAME, 'value-picker-hour24-state')
def __init__(self, marionette):
Base.__init__(self, marionette)
self.marionette.switch_to_frame()
Wait(self.marionette).until(expected.element_displayed(*self._hour_picker_locator))
# TODO: wait for the time picker to fade in Bug 1038186
time.sleep(2)
def tap_done(self):
time_picker = self.marionette.find_element(*self._time_picker_locator)
self.marionette.find_element(*self._done_button_locator).tap()
Wait(self.marionette).until(expected.element_not_displayed(time_picker))
# TODO: wait for the time picker to fade out Bug 1038186
time.sleep(2)
self.apps.switch_to_displayed_app()
@property
def hour(self):
return self._current(self._hour_picker_locator).text
@property
def minute(self):
return self._current(self._minutes_picker_locator).text
def add_minute(self):
current = self._current(self._minutes_picker_locator)
minute = self.minute
Actions(self.marionette).press(current).wait(0.2).move_by_offset(0, -3*current.rect['height']).wait(0.4).release().perform()
Wait(self.marionette).until(lambda m: self.minute != minute)
@property
def hour24(self):
return self._current(self._hour24_picker_locator).text
def _current(self, locator):
picker = self.marionette.find_element(*locator)
return picker.find_element(By.CLASS_NAME, 'selected')

View file

@ -0,0 +1,93 @@
# 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/.
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
from gaiatest.apps.settings.app import Settings
from gaiatest.apps.system.app import System
class UtilityTray(Base):
_utility_tray_locator = (By.ID, 'utility-tray')
_desktop_notifications_locator = (By.CSS_SELECTOR, '#desktop-notifications-container .notification')
_notification_clear_locator = (By.ID, 'notification-clear')
_quicksettings_app_locator = (By.ID, 'quick-settings-full-app')
_grippy_locator = (By.ID, 'utility-tray-grippy')
_quick_settings_full_app_locator = (By.ID, 'quick-settings-full-app')
def wait_for_dropped_down(self):
utility_tray = self.marionette.find_element(*self._utility_tray_locator)
grippy = self.marionette.find_element(*self._grippy_locator)
Wait(self.marionette).until(lambda m: (grippy.rect['y'] + grippy.rect['height']) == utility_tray.size['height'])
@property
def notifications(self):
return [Notification(self.marionette, notification)
for notification in self.marionette.find_elements(*self._desktop_notifications_locator)]
def get_notifications(self, for_app=None):
return [Notification(self.marionette, notification)
for notification in self.marionette.find_elements(*self._desktop_notifications_locator)
if for_app is None or for_app in notification.get_attribute('data-manifest-u-r-l')]
def clear_all_notifications(self):
self.marionette.find_element(*self._notification_clear_locator).tap()
Wait(self.marionette).until(lambda m: len(self.notifications) == 0)
def a11y_clear_all_notifications(self):
self.accessibility.click(self.marionette.find_element(*self._notification_clear_locator))
@property
def cost_control_widget(self):
return CostControlWidget(self.marionette)
def tap_settings_button(self):
self.marionette.find_element(*self._quicksettings_app_locator).tap()
def a11y_wheel_utility_tray_grippy(self):
self.accessibility.wheel(self.marionette.find_element(*self._grippy_locator), 'up')
Wait(self.marionette).until(
expected.element_not_displayed(*System(self.marionette)._utility_tray_locator))
def a11y_click_quick_settings_full_app(self):
self.accessibility.click(self.marionette.find_element(
*self._quick_settings_full_app_locator))
return Settings(self.marionette)
class Notification(PageRegion):
_body_locator = (By.CSS_SELECTOR, 'div.detail')
_title_locator = (By.CSS_SELECTOR, 'div.title')
@property
def title(self):
return self.root_element.find_element(*self._title_locator).text
@property
def content(self):
return self.root_element.find_element(*self._body_locator).text
def tap_notification(self):
self.root_element.find_element(*self._title_locator).tap()
from gaiatest.apps.email.regions.read_email import ReadEmail
return ReadEmail(self.marionette)
class CostControlWidget(Base):
_cost_control_widget_locator = (By.CSS_SELECTOR, '#cost-control-widget > iframe')
_data_usage_view_locator = (By.ID, 'datausage-limit-view')
def __init__(self, marionette):
Base.__init__(self, marionette)
usage_iframe = self.marionette.find_element(*self._cost_control_widget_locator)
self.marionette.switch_to_frame(usage_iframe)
def tap(self):
self.marionette.find_element(*self._data_usage_view_locator).tap()
def wait_for_limit_to_be_reached(self):
usage_view = self.marionette.find_element(*self._data_usage_view_locator)
Wait(self.marionette, timeout=40).until(lambda m: 'reached-limit' in usage_view.get_attribute('class'))