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,56 @@
# 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 GoogleLogin(Base):
_iframe_locator = (By.CSS_SELECTOR, "iframe.sup-oauth2-browser[src *= 'google']")
_email_locator = (By.ID, 'Email')
_password_locator = (By.ID, 'Passwd')
_sign_in_locator = (By.ID, 'signIn')
_approve_access_locator = (By.CSS_SELECTOR, '#submit_approve_access.goog-buttonset-action')
_next_locator = (By.ID, 'next')
def __init__(self, marionette):
Base.__init__(self, marionette)
self.switch_to_frame()
# wait for the page to load
email = Wait(self.marionette).until(
expected.element_present(*self._email_locator))
Wait(self.marionette).until(lambda m: email.get_attribute('value') != '')
@property
def email(self):
return self.marionette.find_element(*self._email_locator).get_attribute('value')
def type_password(self, password):
element = Wait(self.marionette).until(expected.element_present(*self._password_locator))
Wait(self.marionette).until(expected.element_displayed(element))
element.send_keys(password)
def tap_sign_in(self):
self.marionette.find_element(*self._sign_in_locator).tap()
def tap_next(self):
self.marionette.find_element(*self._next_locator).tap()
def wait_for_approve_access(self):
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._approve_access_locator))))
def tap_approve_access(self):
approve_access = Wait(self.marionette).until(
expected.element_present(*self._approve_access_locator))
Wait(self.marionette).until(expected.element_enabled(approve_access))
approve_access.tap()
def switch_to_frame(self):
# wait for the pop up screen to open
view = Wait(self.marionette).until(
expected.element_present(*self._iframe_locator))
self.marionette.switch_to_frame(view)

View file

@ -0,0 +1,56 @@
# 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 gaiatest.apps.base import Base
class NewEmail(Base):
# Write new email
_view_locator = (By.CSS_SELECTOR, '#cardContainer cards-compose')
_to_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .cmp-to-text.cmp-addr-text')
_cc_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .cmp-cc-text.cmp-addr-text')
_bcc_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .cmp-bcc-text.cmp-addr-text')
_subject_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .cmp-subject-text')
_body_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .cmp-body-text')
_send_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .icon.icon-send')
def __init__(self, marionette):
Base.__init__(self, marionette)
view = self.marionette.find_element(*self._view_locator)
Wait(self.marionette).until(lambda m: view.location['x'] == 0)
def type_to(self, value):
self.marionette.find_element(*self._to_locator).tap()
self.keyboard.send(value)
self.keyboard.dismiss()
def type_cc(self, value):
self.marionette.find_element(*self._cc_locator).tap()
self.keyboard.send(value)
self.keyboard.dismiss()
def type_bcc(self, value):
self.marionette.find_element(*self._bcc_locator).tap()
self.keyboard.send(value)
self.keyboard.dismiss()
def type_subject(self, value):
self.marionette.find_element(*self._subject_locator).tap()
self.keyboard.send(value)
self.keyboard.dismiss()
def type_body(self, value):
self.marionette.find_element(*self._body_locator).tap()
self.keyboard.send(value)
self.keyboard.dismiss()
def tap_send(self):
self.marionette.find_element(*self._send_locator).tap()
from gaiatest.apps.email.app import Email
email = Email(self.marionette)
email.wait_for_message_list()
return email

View file

@ -0,0 +1,69 @@
# 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 gaiatest.apps.base import Base
class ReadEmail(Base):
manifest_url = '{}email{}/manifest.webapp'.format(Base.DEFAULT_PROTOCOL,Base.DEFAULT_APP_HOSTNAME)
_body_locator = (By.CSS_SELECTOR, '.card.center .msg-body-content')
_subject_locator = (By.CSS_SELECTOR, '.card.center .msg-envelope-subject')
_senders_email_locator = (By.CSS_SELECTOR, '.msg-reader-header-label')
_delete_button_locator = (By.CSS_SELECTOR, '.msg-reader-action-toolbar .icon.msg-delete-btn')
_star_button_locator = (By.CSS_SELECTOR, '.msg-reader-action-toolbar .icon.msg-star-btn')
_mark_button_locator = (By.CSS_SELECTOR, '.msg-reader-action-toolbar .icon.msg-mark-read-btn')
_move_button_locator = (By.CSS_SELECTOR, '.msg-reader-action-toolbar .icon.msg-move-btn')
_reply_button_locator = (By.CSS_SELECTOR, '.msg-reader-action-toolbar .icon.msg-reply-btn')
_delete_approve_button_locator = (By.ID, 'msg-delete-ok')
_delete_cancel_button_locator = (By.ID, 'msg-delete-cancel')
_move_cancel_button_locator = (By.CSS_SELECTOR, '.full')
_reply_cancel_button_locator = (By.CSS_SELECTOR, '.msg-reply-menu-cancel')
@property
def body(self):
return self.marionette.find_element(*self._body_locator).text
@property
def subject(self):
return self.marionette.find_element(*self._subject_locator).text
def wait_for_senders_email_displayed(self):
Wait(self.marionette).until(lambda m: m.find_element(*self._senders_email_locator).text != '')
@property
def senders_email(self):
return self.marionette.find_element(*self._senders_email_locator).text
def tap_delete_button(self):
self.marionette.find_element(*self._delete_button_locator).tap()
def tap_star_button(self):
self.marionette.find_element(*self._star_button_locator).tap()
def tap_mark_button(self):
self.marionette.find_element(*self._mark_button_locator).tap()
def tap_move_button(self):
self.marionette.find_element(*self._move_button_locator).tap()
def tap_reply_button(self):
self.marionette.find_element(*self._reply_button_locator).tap()
def approve_delete(self):
self.marionette.find_element(*self._delete_approve_button_locator).tap()
def cancel_delete(self):
self.marionette.find_element(*self._delete_cancel_button_locator).tap()
def cancel_move(self):
self.marionette.find_element(*self._move_cancel_button_locator).tap()
def cancel_reply(self):
self.marionette.find_element(*self._reply_cancel_button_locator).tap()

View file

@ -0,0 +1,73 @@
# 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 Settings(Base):
#general email settings
_email_account_locator = (By.CSS_SELECTOR, '.tng-account-item')
_account_add_locator = (By.CLASS_NAME, 'tng-account-add')
def __init__(self, marionette):
Base.__init__(self, marionette)
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._email_account_locator))))
@property
def email_accounts(self):
return [self.Account(self.marionette, email_account) for email_account in self.marionette.find_elements(*self._email_account_locator)]
class Account(PageRegion):
_name_locator = (By.CSS_SELECTOR, 'a.tng-account-item-label')
def tap(self):
self.root_element.tap()
return EmailAccountSettings(self.marionette)
def a11y_click(self):
self.accessibility.click(self.root_element)
return EmailAccountSettings(self.marionette)
class EmailAccountSettings(Base):
#settings for a specific email account
_delete_account_locator = (By.CSS_SELECTOR, '.tng-account-delete')
def __init__(self, marionette):
Base.__init__(self, marionette)
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._delete_account_locator))))
def tap_delete(self):
self.marionette.find_element(*self._delete_account_locator).tap()
return DeleteConfirmation(self.marionette)
def a11y_click_delete(self):
self.accessibility.click(self.marionette.find_element(*self._delete_account_locator))
return DeleteConfirmation(self.marionette)
class DeleteConfirmation(Base):
_delete_locator = (By.CSS_SELECTOR, '.tng-account-delete-confirm #account-delete-ok')
_cancel_locator = (By.CSS_SELECTOR, '.tng-account-delete-confirm #account-delete-cancel')
_message_locator = (By.CSS_SELECTOR, '.tng-account-delete-confirm > section > p')
def __init__(self, marionette):
Base.__init__(self, marionette)
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._delete_locator))))
def tap_delete(self):
self.marionette.find_element(*self._delete_locator).tap()
def a11y_click_delete(self):
self.accessibility.click(self.marionette.find_element(*self._delete_locator))

View file

@ -0,0 +1,201 @@
# 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 SetupEmail(Base):
_name_locator = (By.CSS_SELECTOR, 'cards-setup-account-info input.sup-info-name')
_email_locator = (By.CSS_SELECTOR, 'cards-setup-account-info input.sup-info-email')
_next_locator = (By.CSS_SELECTOR, '.sup-info-next-btn')
_continue_button_locator = ('class name', 'sup-show-mail-btn sup-form-btn recommend')
_check_for_new_messages_locator = (By.CSS_SELECTOR, '.tng-account-check-interval.mail-select')
_account_prefs_section_locator = (By.CSS_SELECTOR, 'cards-setup-account-prefs section')
_account_prefs_next_locator = (By.CSS_SELECTOR, 'cards-setup-account-prefs .sup-info-next-btn')
_done_section_locator = (By.CSS_SELECTOR, 'cards-setup-done section')
def __init__(self, marionette):
Base.__init__(self, marionette)
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._name_locator))))
def type_name(self, value):
self.marionette.find_element(*self._name_locator).send_keys(value)
def type_email(self, value):
self.marionette.find_element(*self._email_locator).send_keys(value)
def tap_next(self):
self.marionette.find_element(*self._next_locator).tap()
def tap_account_prefs_next(self):
next = Wait(self.marionette, timeout=120).until(
expected.element_present(*self._account_prefs_next_locator))
Wait(self.marionette, timeout=120).until(
expected.element_displayed(next))
next.tap()
def wait_for_setup_complete(self):
element = Wait(self.marionette).until(
expected.element_present(*self._done_section_locator))
Wait(self.marionette).until(lambda m: element.location['x'] == 0)
def tap_continue(self):
self.marionette.find_element(*self._continue_button_locator).tap()
class ManualSetupEmail(Base):
name = 'E-Mail' # hack to be able to use select
_name_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config input.sup-info-name')
_email_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config input.sup-info-email')
_password_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config input.sup-info-password')
_account_type_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-account-type')
_imap_username_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-composite-username')
_imap_password_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-composite-password')
_imap_hostname_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-composite-hostname')
_imap_port_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-composite-port')
_smtp_username_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-smtp-username')
_smtp_password_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-smtp-password')
_smtp_hostname_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-smtp-hostname')
_smtp_port_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-smtp-port')
_activesync_hostname_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-activesync-hostname')
_activesync_username_locator = (By.CSS_SELECTOR, 'cards-setup-manual-config .sup-manual-activesync-username')
_next_locator = (By.CSS_SELECTOR, '.sup-manual-next-btn')
_continue_button_locator = (By.CLASS_NAME, 'sup-show-mail-btn sup-form-btn recommend')
_check_for_new_messages_locator = (By.CSS_SELECTOR, '.tng-account-check-interval.mail-select')
_account_prefs_section_locator = (By.CSS_SELECTOR, 'cards-setup-account-prefs')
_account_prefs_next_locator = (By.CSS_SELECTOR, 'cards-setup-account-prefs .sup-info-next-btn')
_done_section_locator = (By.CSS_SELECTOR, 'cards-setup-done section')
def __init__(self, marionette):
Base.__init__(self, marionette)
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._name_locator))))
def type_name(self, value):
el = self.marionette.find_element(*self._name_locator)
el.clear()
el.send_keys(value)
self.keyboard.dismiss()
def type_email(self, value):
el = self.marionette.find_element(*self._email_locator)
el.clear()
el.send_keys(value)
self.keyboard.dismiss()
def type_password(self, value):
el = self.marionette.find_element(*self._password_locator)
el.clear()
el.send_keys(value)
self.keyboard.dismiss()
def select_account_type(self, value):
account_type = self.marionette.find_element(*self._account_type_locator)
account_type.click()
self.marionette.switch_to_frame()
self.select(value)
def type_imap_name(self, value):
el = self.marionette.find_element(*self._imap_username_locator)
el.clear()
el.send_keys(value)
def type_imap_hostname(self, value):
el = self.marionette.find_element(*self._imap_hostname_locator)
el.clear()
el.send_keys(value)
def type_imap_password(self, value):
el = self.marionette.find_element(*self._imap_password_locator)
el.clear()
el.send_keys(value)
def type_imap_port(self, value):
el = self.marionette.find_element(*self._imap_port_locator)
el.clear()
el.send_keys(value)
def type_smtp_name(self, value):
el = self.marionette.find_element(*self._smtp_username_locator)
el.clear()
el.send_keys(value)
def type_smtp_hostname(self, value):
el = self.marionette.find_element(*self._smtp_hostname_locator)
el.clear()
el.send_keys(value)
def type_smtp_password(self, value):
el = self.marionette.find_element(*self._smtp_password_locator)
el.clear()
el.send_keys(value)
def type_smtp_port(self, value):
el = self.marionette.find_element(*self._smtp_port_locator)
el.clear()
el.send_keys(value)
self.keyboard.dismiss()
def type_activesync_name(self, value):
el = self.marionette.find_element(*self._activesync_username_locator)
el.clear()
el.send_keys(value)
self.keyboard.dismiss()
def type_activesync_hostname(self, value):
el = self.marionette.find_element(*self._activesync_hostname_locator)
el.clear()
el.send_keys(value)
def tap_next(self):
next = Wait(self.marionette).until(expected.element_present(*self._next_locator))
Wait(self.marionette).until(lambda m: next.get_attribute('disabled') != 'true')
next.tap()
account = Wait(self.marionette).until(
expected.element_present(*self._account_prefs_section_locator))
Wait(self.marionette).until(lambda m: account.location['x'] == 0)
Wait(self.marionette, timeout=120).until(expected.element_displayed(
Wait(self.marionette, timeout=120).until(expected.element_present(
*self._account_prefs_next_locator))))
def check_for_emails_interval(self, value):
# The following pref change allows us to check the mail within 1 second or longer,
# rather than the default value of 100 seconds
# The UI data layer of the UI is changed, because the minimum check mail time value is 5 min,
# which is far too long to check for in a test. This allows us to check earlier
with self.marionette.using_context('chrome'):
self.marionette.execute_script(
"Services.prefs.setIntPref('dom.requestSync.minInterval', 1);")
self.marionette.execute_script("""
document.querySelector("[data-l10n-id = settings-check-every-5min]").value = '%s';
""" % value)
self.marionette.find_element(*self._check_for_new_messages_locator).tap()
self.select('Every 5 minutes')
def tap_account_prefs_next(self):
self.marionette.find_element(*self._account_prefs_next_locator).tap()
def wait_for_setup_complete(self):
done = Wait(self.marionette).until(
expected.element_present(*self._done_section_locator))
Wait(self.marionette).until(lambda m: done.location['x'] == 0)
def tap_continue(self):
self.marionette.find_element(*self._continue_button_locator).tap()