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:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
3
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/__init__.py
Executable file
3
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/__init__.py
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
# 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/.
|
||||
191
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/app.py
Executable file
191
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/app.py
Executable file
|
|
@ -0,0 +1,191 @@
|
|||
# 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.errors import JavascriptException
|
||||
|
||||
from gaiatest.apps.base import Base
|
||||
from gaiatest.apps.base import PageRegion
|
||||
|
||||
|
||||
class Contacts(Base):
|
||||
|
||||
name = "Contacts"
|
||||
entry_point = "contacts"
|
||||
manifest_url = '{}communications{}/manifest.webapp'.format(Base.DEFAULT_PROTOCOL,Base.DEFAULT_APP_HOSTNAME)
|
||||
|
||||
_new_contact_button_locator = (By.ID, 'add-contact-button')
|
||||
_settings_button_locator = (By.ID, 'settings-button')
|
||||
_favorites_list_locator = (By.ID, 'contacts-list-favorites')
|
||||
_select_all_wrapper_locator = (By.ID, 'select-all-wrapper')
|
||||
_select_all_button_locator = (By.CSS_SELECTOR, 'button[data-l10n-id="selectAll"]')
|
||||
_select_action_button_locator = (By.ID, 'select-action')
|
||||
_status_message_locator = (By.ID, 'statusMsg')
|
||||
_confirm_delete_locator = (By.CSS_SELECTOR, 'button.danger[data-l10n-id="delete"]')
|
||||
_no_contacts_message_locator = (By.CSS_SELECTOR, '*[data-l10n-id="no-contacts"]')
|
||||
_group_container_selector = "#groups-container"
|
||||
_contact_locator = (By.CSS_SELECTOR, 'li[data-uuid]:not([data-group="ice"])')
|
||||
_ice_contact = (By.CSS_SELECTOR, 'ol#ice-group')
|
||||
_ice_list_icon_locator = (By.ID, 'contact-list-ice')
|
||||
_select_ice_contact_1_locator = (By.ID, 'select-ice-contact-1')
|
||||
|
||||
def launch(self):
|
||||
Base.launch(self)
|
||||
Wait(self.marionette).until(expected.element_displayed(
|
||||
Wait(self.marionette).until(expected.element_present(
|
||||
*self._settings_button_locator))))
|
||||
|
||||
# Workaround for bug 1201211
|
||||
import time
|
||||
time.sleep(1)
|
||||
|
||||
def switch_to_contacts_frame(self):
|
||||
self.wait_to_be_displayed()
|
||||
self.apps.switch_to_displayed_app()
|
||||
|
||||
@property
|
||||
def contacts(self):
|
||||
return [self.Contact(marionette=self.marionette, element=contact)
|
||||
for contact in self.marionette.find_elements(*self._contact_locator)]
|
||||
|
||||
def wait_for_contacts(self, number_to_wait_for=1):
|
||||
Wait(self.marionette).until(lambda m: len(m.find_elements(
|
||||
*self._contact_locator)) == number_to_wait_for)
|
||||
|
||||
# we need to scroll in order to force the rendering of all the contacts
|
||||
height = self.marionette.execute_script("return document.querySelector('[data-uuid]').clientHeight;")
|
||||
for idx in range(number_to_wait_for):
|
||||
self.marionette.execute_script("document.querySelector('{0}').scrollTop = {1}".
|
||||
format(self._group_container_selector, idx * height))
|
||||
|
||||
def contact(self, name):
|
||||
for contact in self.contacts:
|
||||
if contact.name == name:
|
||||
return contact
|
||||
|
||||
def tap_new_contact(self):
|
||||
self.marionette.find_element(*self._new_contact_button_locator).tap()
|
||||
from gaiatest.apps.contacts.regions.contact_form import NewContact
|
||||
new_contact = NewContact(self.marionette)
|
||||
new_contact.wait_for_new_contact_form_to_load()
|
||||
return new_contact
|
||||
|
||||
def a11y_click_new_contact(self):
|
||||
self.accessibility.click(self.marionette.find_element(*self._new_contact_button_locator))
|
||||
from gaiatest.apps.contacts.regions.contact_form import NewContact
|
||||
new_contact = NewContact(self.marionette)
|
||||
new_contact.wait_for_new_contact_form_to_load()
|
||||
return new_contact
|
||||
|
||||
def tap_settings(self):
|
||||
settings = self.marionette.find_element(*self._settings_button_locator)
|
||||
Wait(self.marionette).until(expected.element_displayed(settings))
|
||||
settings.tap()
|
||||
Wait(self.marionette).until(expected.element_not_displayed(settings))
|
||||
from gaiatest.apps.contacts.regions.settings_form import SettingsForm
|
||||
return SettingsForm(self.marionette)
|
||||
|
||||
def tap_select_all(self):
|
||||
window_height = self.marionette.execute_script('return window.wrappedJSObject.innerHeight')
|
||||
wrapper = self.marionette.find_element(*self._select_all_wrapper_locator)
|
||||
Wait(self.marionette).until(lambda m: int(wrapper.size['height'] + wrapper.location['y']) == window_height)
|
||||
|
||||
self.marionette.find_element(*self._select_all_button_locator).tap()
|
||||
|
||||
def tap_export(self):
|
||||
self._tap_action_button()
|
||||
|
||||
def tap_delete(self):
|
||||
self._tap_action_button()
|
||||
|
||||
def _tap_action_button(self):
|
||||
# The same button is used to do bulk operations (like delete or export). The displayed string changes though.
|
||||
# Hence, let's define more semantically explicit functions.
|
||||
self.marionette.find_element(*self._select_action_button_locator).tap()
|
||||
|
||||
def tap_confirm_delete(self):
|
||||
delete_button = Wait(self.marionette).until(expected.element_present(*self._confirm_delete_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(delete_button))
|
||||
delete_button.tap()
|
||||
|
||||
@property
|
||||
def is_favorites_list_displayed(self):
|
||||
return self.marionette.find_element(*self._favorites_list_locator).is_displayed()
|
||||
|
||||
@property
|
||||
def is_ice_list_icon_displayed(self):
|
||||
return self.marionette.find_element(*self._ice_list_icon_locator).is_displayed()
|
||||
|
||||
def open_ice_contact_list(self):
|
||||
ice_list = Wait(self.marionette).until(expected.element_present(*self._ice_list_icon_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(ice_list))
|
||||
ice_list.tap()
|
||||
return Contacts(self.marionette)
|
||||
|
||||
def wait_for_ice_contact_shown(self):
|
||||
Wait(self.marionette).until(expected.element_displayed(*self._ice_contact))
|
||||
|
||||
@property
|
||||
def status_message(self):
|
||||
status = Wait(self.marionette).until(expected.element_present(
|
||||
*self._status_message_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(status))
|
||||
return status.text
|
||||
|
||||
@property
|
||||
def is_no_contacts_message_displayed(self):
|
||||
return self.marionette.find_element(*self._no_contacts_message_locator).is_displayed()
|
||||
|
||||
class Contact(PageRegion):
|
||||
|
||||
_name_locator = (By.CSS_SELECTOR, 'bdi > strong')
|
||||
_full_name_locator = (By.CSS_SELECTOR, 'p.contact-text bdi')
|
||||
_image_locator = (By.CSS_SELECTOR, 'span[data-type="img"]')
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.root_element.find_element(*self._name_locator).text
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return self.root_element.find_element(*self._full_name_locator).text
|
||||
|
||||
@property
|
||||
def image_data_group(self):
|
||||
return self.root_element.find_element(*self._image_locator).get_attribute('data-group')
|
||||
|
||||
def tap(self, return_class='ContactDetails'):
|
||||
self.marionette.execute_script('arguments[0].scrollIntoView(false);', [self.root_element])
|
||||
if return_class == None:
|
||||
self.tap_element_from_system_app(
|
||||
self.root_element.find_element(*self._name_locator), add_statusbar_height=True)
|
||||
else:
|
||||
self.root_element.find_element(*self._name_locator).tap()
|
||||
|
||||
return self._return_class_from_tap(return_class)
|
||||
|
||||
def a11y_click(self, return_class='ContactDetails'):
|
||||
self.accessibility.click(self.root_element)
|
||||
return self._return_class_from_tap(return_class)
|
||||
|
||||
def _return_class_from_tap(self, return_class='ContactDetails'):
|
||||
if return_class == 'ContactDetails':
|
||||
Wait(self.marionette).until(lambda m: expected.element_not_displayed(self.root_element))
|
||||
from gaiatest.apps.contacts.regions.contact_details import ContactDetails
|
||||
return ContactDetails(self.marionette)
|
||||
elif return_class == 'EditContact':
|
||||
# This may seem superfluous but we can enter EditContact from Contacts, or from ActivityPicker
|
||||
Contacts(self.marionette).wait_to_be_displayed()
|
||||
self.apps.switch_to_displayed_app()
|
||||
from gaiatest.apps.contacts.regions.contact_form import EditContact
|
||||
return EditContact(self.marionette)
|
||||
elif return_class == 'SelectContact':
|
||||
return None
|
||||
elif return_class == 'SetIceContacts':
|
||||
from gaiatest.apps.contacts.regions.set_ice_contacts import SetIceContacts
|
||||
return SetIceContacts(self.marionette)
|
||||
else:
|
||||
# We are using contacts picker in activity - after choosing, fall back to open app
|
||||
Contacts(self.marionette).wait_to_not_be_displayed()
|
||||
self.apps.switch_to_displayed_app()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# 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/.
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
# 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.form_controls.header import GaiaHeader
|
||||
|
||||
|
||||
class ContactDetails(Base):
|
||||
|
||||
_contact_name_title_locator = (By.ID, 'contact-name-title')
|
||||
_contact_image_locator = (By.ID, 'cover-img')
|
||||
_call_phone_number_button_locator = (By.ID, 'call-or-pick-0')
|
||||
_phone_numbers_locator = (By.CSS_SELECTOR, '#contact-detail-inner .icon-call')
|
||||
_send_sms_button_locator = (By.ID, 'send-sms-button-0')
|
||||
_edit_contact_button_locator = (By.ID, 'edit-contact-button')
|
||||
_details_header_locator = (By.ID, 'details-view-header')
|
||||
_add_remove_favorite_button_locator = (By.ID, 'toggle-favorite')
|
||||
_comments_locator = (By.ID, 'note-details-template-0')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
el = self.marionette.find_element(*self._details_header_locator)
|
||||
Wait(self.marionette).until(lambda m: el.location['x'] == 0 and el.is_displayed())
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return self.marionette.find_element(*self._contact_name_title_locator).text
|
||||
|
||||
@property
|
||||
def phone_number(self):
|
||||
return self.marionette.find_element(*self._call_phone_number_button_locator).text
|
||||
|
||||
@property
|
||||
def phone_numbers(self):
|
||||
return [element.text for element in self.marionette.find_elements(*self._phone_numbers_locator)]
|
||||
|
||||
@property
|
||||
def comments(self):
|
||||
return self.marionette.find_element(*self._comments_locator).text
|
||||
|
||||
@property
|
||||
def image_style(self):
|
||||
return self.marionette.find_element(*self._contact_image_locator).get_attribute('style')
|
||||
|
||||
def tap_phone_number(self):
|
||||
call = self.marionette.find_element(*self._call_phone_number_button_locator)
|
||||
Wait(self.marionette).until(expected.element_enabled(call))
|
||||
call.tap()
|
||||
from gaiatest.apps.phone.regions.call_screen import CallScreen
|
||||
return CallScreen(self.marionette)
|
||||
|
||||
def tap_send_sms(self):
|
||||
self.marionette.find_element(*self._send_sms_button_locator).tap()
|
||||
from gaiatest.apps.messages.regions.new_message import NewMessage
|
||||
return NewMessage(self.marionette)
|
||||
|
||||
def tap_edit(self):
|
||||
edit = Wait(self.marionette).until(expected.element_present(
|
||||
*self._edit_contact_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(edit))
|
||||
edit.tap()
|
||||
from gaiatest.apps.contacts.regions.contact_form import EditContact
|
||||
return EditContact(self.marionette)
|
||||
|
||||
def a11y_click_edit(self):
|
||||
edit = Wait(self.marionette).until(expected.element_present(
|
||||
*self._edit_contact_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(edit))
|
||||
self.accessibility.click(edit)
|
||||
from gaiatest.apps.contacts.regions.contact_form import EditContact
|
||||
return EditContact(self.marionette)
|
||||
|
||||
def tap_back(self):
|
||||
GaiaHeader(self.marionette, self._details_header_locator).go_back()
|
||||
|
||||
def tap_add_remove_favorite(self):
|
||||
button = self.marionette.find_element(*self._add_remove_favorite_button_locator)
|
||||
# Capture the current state of the element
|
||||
initial_state = button.get_attribute('data-l10n-id')
|
||||
self.marionette.execute_script("arguments[0].scrollIntoView(false);", [button])
|
||||
button.tap()
|
||||
# Wait for it to have toggled
|
||||
Wait(self.marionette).until(lambda m: button.get_attribute('data-l10n-id') != initial_state)
|
||||
|
||||
@property
|
||||
def add_remove_text(self):
|
||||
return self.marionette.find_element(*self._add_remove_favorite_button_locator).text
|
||||
227
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/contact_form.py
Executable file
227
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/contact_form.py
Executable file
|
|
@ -0,0 +1,227 @@
|
|||
# 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 ContactForm(Base):
|
||||
|
||||
name = 'Contacts'
|
||||
|
||||
_given_name_locator = (By.ID, 'givenName')
|
||||
_family_name_locator = (By.ID, 'familyName')
|
||||
_phone_locator = (By.ID, 'number_0')
|
||||
_email_locator = (By.ID, 'email_0')
|
||||
_street_locator = (By.ID, 'streetAddress_0')
|
||||
_zip_code_locator = (By.ID, 'postalCode_0')
|
||||
_city_locator = (By.ID, 'locality_0')
|
||||
_country_locator = (By.ID, 'countryName_0')
|
||||
_comment_locator = (By.ID, 'note_0')
|
||||
_add_new_email_locator = (By.ID, 'add-new-email')
|
||||
_add_new_address_locator = (By.ID, 'add-new-address')
|
||||
_add_new_note_locator = (By.ID, 'add-new-note')
|
||||
_add_new_phone_locator = (By.ID, 'add-new-phone')
|
||||
|
||||
_thumbnail_photo_locator = (By.ID, 'thumbnail-photo')
|
||||
|
||||
@property
|
||||
def given_name(self):
|
||||
return self.marionette.find_element(*self._given_name_locator).text
|
||||
|
||||
def type_given_name(self, value):
|
||||
element = self.marionette.find_element(*self._given_name_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
@property
|
||||
def family_name(self):
|
||||
return self.marionette.find_element(*self._family_name_locator).text
|
||||
|
||||
def type_family_name(self, value):
|
||||
element = self.marionette.find_element(*self._family_name_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
@property
|
||||
def phone(self):
|
||||
return self.marionette.find_element(*self._phone_locator).text
|
||||
|
||||
def _type_in_field(self, add_locator, field_locator, value):
|
||||
Wait(self.marionette).until(expected.element_present(*add_locator)).tap()
|
||||
element = Wait(self.marionette).until(expected.element_present(*field_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(element))
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
def type_phone(self, value):
|
||||
self._type_in_field(self._add_new_phone_locator, self._phone_locator, value)
|
||||
|
||||
@property
|
||||
def email(self):
|
||||
return self.marionette.find_element(*self._email_locator).text
|
||||
|
||||
def type_email(self, value):
|
||||
self._type_in_field(self._add_new_email_locator, self._email_locator, value)
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.marionette.find_element(*self._street_locator).text
|
||||
|
||||
def type_street(self, value):
|
||||
self._type_in_field(self._add_new_address_locator, self._street_locator, value)
|
||||
|
||||
@property
|
||||
def zip_code(self):
|
||||
return self.marionette.find_element(*self._zip_code_locator).text
|
||||
|
||||
def type_zip_code(self, value):
|
||||
element = self.marionette.find_element(*self._zip_code_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.marionette.find_element(*self._city_locator).text
|
||||
|
||||
def type_city(self, value):
|
||||
element = self.marionette.find_element(*self._city_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.marionette.find_element(*self._country_locator).text
|
||||
|
||||
def type_country(self, value):
|
||||
element = self.marionette.find_element(*self._country_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
|
||||
@property
|
||||
def comment(self):
|
||||
return self.marionette.find_element(*self._comment_locator).text
|
||||
|
||||
def type_comment(self, value):
|
||||
if self.is_element_present(*self._comment_locator):
|
||||
element = self.marionette.find_element(*self._comment_locator)
|
||||
element.clear()
|
||||
element.send_keys(value)
|
||||
else:
|
||||
self._type_in_field(self._add_new_note_locator, self._comment_locator, value)
|
||||
|
||||
|
||||
def tap_comment(self):
|
||||
self.marionette.find_element(*self._comment_locator).tap()
|
||||
|
||||
@property
|
||||
def picture_style(self):
|
||||
return self.marionette.find_element(*self._thumbnail_photo_locator).get_attribute('style')
|
||||
|
||||
def tap_picture(self):
|
||||
self.marionette.find_element(*self._thumbnail_photo_locator).tap()
|
||||
from gaiatest.apps.system.regions.activities import Activities
|
||||
return Activities(self.marionette)
|
||||
|
||||
def wait_for_image_to_load(self):
|
||||
el = self.marionette.find_element(*self._thumbnail_photo_locator)
|
||||
Wait(self.marionette).until(lambda m: 'background-image' in el.get_attribute('style'))
|
||||
|
||||
|
||||
class EditContact(ContactForm):
|
||||
|
||||
_update_locator = (By.ID, 'save-button')
|
||||
_cancel_locator = (By.ID, 'cancel-edit')
|
||||
_delete_locator = (By.ID, 'delete-contact')
|
||||
_delete_form_locator = (By.ID, 'confirmation-message')
|
||||
_cancel_delete_locator = (By.CSS_SELECTOR, 'form#confirmation-message button:not(.danger)')
|
||||
_confirm_delete_locator = (By.CSS_SELECTOR, 'form#confirmation-message button.danger')
|
||||
|
||||
def __init__(self, marionette):
|
||||
ContactForm.__init__(self, marionette)
|
||||
update = Wait(self.marionette).until(expected.element_present(*self._update_locator))
|
||||
Wait(self.marionette).until(lambda m: update.location['y'] == 0 and update.is_displayed())
|
||||
|
||||
def tap_update(self, return_class='ContactDetails'):
|
||||
self.wait_for_update_button_enabled()
|
||||
update = self.marionette.find_element(*self._update_locator)
|
||||
update.tap()
|
||||
if return_class == 'ContactDetails':
|
||||
from gaiatest.apps.contacts.regions.contact_details import ContactDetails
|
||||
return ContactDetails(self.marionette)
|
||||
elif return_class == 'Merge':
|
||||
from gaiatest.apps.contacts.regions.merge import Merge
|
||||
return Merge(self.marionette)
|
||||
else:
|
||||
# else we drop back to the underlying app
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
Contacts(self.marionette).wait_to_not_be_displayed()
|
||||
self.apps.switch_to_displayed_app()
|
||||
|
||||
def tap_cancel(self):
|
||||
self.marionette.find_element(*self._cancel_locator).tap()
|
||||
from gaiatest.apps.contacts.regions.contact_details import ContactDetails
|
||||
return ContactDetails(self.marionette)
|
||||
|
||||
def tap_delete(self):
|
||||
delete_item = self.marionette.find_element(*self._delete_locator)
|
||||
self.marionette.execute_script(
|
||||
'arguments[0].scrollIntoView(true);', [delete_item])
|
||||
delete_item.tap()
|
||||
|
||||
def tap_cancel_delete(self):
|
||||
Wait(self.marionette).until(expected.element_displayed(*self._delete_form_locator))
|
||||
self.marionette.find_element(*self._cancel_delete_locator).tap()
|
||||
|
||||
def tap_confirm_delete(self):
|
||||
Wait(self.marionette).until(expected.element_displayed(*self._delete_form_locator))
|
||||
self.marionette.find_element(*self._confirm_delete_locator).tap()
|
||||
|
||||
def wait_for_update_button_enabled(self):
|
||||
update = self.marionette.find_element(*self._update_locator)
|
||||
Wait(self.marionette).until(expected.element_enabled(update))
|
||||
|
||||
|
||||
class NewContact(ContactForm):
|
||||
|
||||
_src = 'app://communications.gaiamobile.org/contacts/views/form/form.html'
|
||||
_done_button_locator = (By.ID, 'save-button')
|
||||
|
||||
def __init__(self, marionette):
|
||||
ContactForm.__init__(self, marionette)
|
||||
|
||||
def switch_to_new_contact_form(self):
|
||||
# When NewContact form is called as an ActivityWindow
|
||||
Wait(self.marionette).until(lambda m: self.apps.displayed_app.src == self._src)
|
||||
self.apps.switch_to_displayed_app()
|
||||
self.wait_for_new_contact_form_to_load()
|
||||
|
||||
def wait_for_new_contact_form_to_load(self):
|
||||
done = self.marionette.find_element(*self._done_button_locator)
|
||||
Wait(self.marionette).until(lambda m: done.location['y'] == 0)
|
||||
|
||||
def tap_done(self, return_contacts=True):
|
||||
element = self.marionette.find_element(*self._done_button_locator)
|
||||
self.tap_element_from_system_app(element, add_statusbar_height=True)
|
||||
|
||||
return self.wait_for_done(return_contacts)
|
||||
|
||||
def a11y_click_done(self, return_contacts=True):
|
||||
element = self.marionette.find_element(*self._done_button_locator)
|
||||
self.accessibility.click(element)
|
||||
Wait(self.marionette).until(expected.element_not_displayed(element))
|
||||
return self.wait_for_done(return_contacts)
|
||||
|
||||
def wait_for_done(self, return_contacts=True):
|
||||
# NewContact can be opened as an Activity from other apps. In this scenario we don't return Contacts
|
||||
if return_contacts:
|
||||
self.apps.switch_to_displayed_app()
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
return Contacts(self.marionette)
|
||||
else:
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
Contacts(self.marionette).wait_to_not_be_displayed()
|
||||
# Fall back to the underlying app
|
||||
self.apps.switch_to_displayed_app()
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# 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 ContactImportPicker(Base):
|
||||
|
||||
_contact_import_picker_frame_locator = (By.ID, 'iframe_extensions')
|
||||
_import_button_locator = (By.ID, 'import-action')
|
||||
_friends_list_locator = (By.ID, 'friends-list')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
Wait(self.marionette).until(
|
||||
expected.element_displayed(*self._contact_import_picker_frame_locator))
|
||||
select_contacts = self.marionette.find_element(*self._contact_import_picker_frame_locator)
|
||||
self.marionette.switch_to_frame(select_contacts)
|
||||
|
||||
def tap_import_button(self, wait_for_import = True):
|
||||
self.marionette.execute_script('window.wrappedJSObject.importer.ui.importAll();')
|
||||
# TODO uncomment this when Bug 932804 is resolved
|
||||
# self.marionette.find_element(*self._import_button_locator).tap()
|
||||
self.apps.switch_to_displayed_app()
|
||||
if wait_for_import:
|
||||
Wait(self.marionette, timeout=60).until(
|
||||
expected.element_not_displayed(*self._contact_import_picker_frame_locator))
|
||||
from gaiatest.apps.contacts.regions.settings_form import SettingsForm
|
||||
return SettingsForm(self.marionette)
|
||||
|
||||
def tap_first_friend(self):
|
||||
element = self.marionette.find_element(*self._friends_list_locator)
|
||||
# TODO replace this with proper tap when Bug 932804 is resolved
|
||||
self.marionette.execute_script("""
|
||||
window.wrappedJSObject.document.getElementById("friends-list")
|
||||
.getElementsByTagName("a")[1].click()
|
||||
""")
|
||||
Wait(self.marionette).until(expected.element_not_displayed(element))
|
||||
self.apps.switch_to_displayed_app()
|
||||
|
||||
def tap_select_all(self):
|
||||
# TODO replace this with proper tap when Bug 932804 is resolved
|
||||
self.marionette.execute_script('window.wrappedJSObject.importer.ui.selectAll();')
|
||||
el = self.marionette.find_element(*self._import_button_locator)
|
||||
Wait(self.marionette).until(expected.element_enabled(el))
|
||||
47
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/gmail.py
Executable file
47
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/gmail.py
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
# 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 GmailLogin(Base):
|
||||
|
||||
_gmail_sign_in_frame_locator = (By.CSS_SELECTOR, '.popupWindow.active iframe[data-url*="google"]')
|
||||
_email_locator = (By.ID, 'Email')
|
||||
_password_locator = (By.ID, 'Passwd')
|
||||
_sign_in_locator = (By.ID, 'signIn')
|
||||
_grant_access_button_locator = (By.ID, 'submit_approve_access')
|
||||
_next_locator = (By.ID, 'next')
|
||||
|
||||
def switch_to_gmail_login_frame(self):
|
||||
self.marionette.switch_to_frame()
|
||||
gmail_sign_in = self.marionette.find_element(*self._gmail_sign_in_frame_locator)
|
||||
self.marionette.switch_to_frame(gmail_sign_in)
|
||||
|
||||
def gmail_login(self, user, passwd):
|
||||
email = Wait(self.marionette).until(
|
||||
expected.element_present(*self._email_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(email))
|
||||
email.tap()
|
||||
email.send_keys(user)
|
||||
self.marionette.find_element(*self._next_locator).tap()
|
||||
password = Wait(self.marionette).until(
|
||||
expected.element_present(*self._password_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(password))
|
||||
password.tap()
|
||||
password.send_keys(passwd)
|
||||
self.keyboard.dismiss()
|
||||
self.marionette.find_element(*self._sign_in_locator).tap()
|
||||
|
||||
def tap_grant_access(self):
|
||||
grant_access = self.marionette.find_element(*self._grant_access_button_locator)
|
||||
Wait(self.marionette).until(expected.element_enabled(grant_access))
|
||||
grant_access.tap()
|
||||
# Go back to displayed Contacts app before waiting for the picker
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
Contacts(self.marionette).wait_to_be_displayed()
|
||||
self.apps.switch_to_displayed_app()
|
||||
from gaiatest.apps.contacts.regions.contact_import_picker import ContactImportPicker
|
||||
return ContactImportPicker(self.marionette)
|
||||
30
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/merge.py
Executable file
30
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/merge.py
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
# 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 Merge(Base):
|
||||
|
||||
_iframe_locator = (By.CSS_SELECTOR, '.popupWindow.active iframe[data-url*="matching"]')
|
||||
_body_locator = (By.TAG_NAME, 'body')
|
||||
_merge_button = (By.ID, 'merge-action')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
marionette.switch_to_frame()
|
||||
|
||||
merge_iframe = Wait(marionette).until(
|
||||
expected.element_present(*self._iframe_locator))
|
||||
Wait(marionette).until(expected.element_displayed(merge_iframe))
|
||||
marionette.switch_to_frame(merge_iframe)
|
||||
|
||||
body = marionette.find_element(*self._body_locator)
|
||||
Wait(marionette).until(lambda m: body.rect['y'] == 0)
|
||||
|
||||
def tap_on_merge(self):
|
||||
Wait(self.marionette).until(
|
||||
expected.element_present(*self._merge_button)).tap()
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# 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 import GaiaApps
|
||||
from gaiatest.apps.base import Base
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
from gaiatest.form_controls.header import GaiaHeader
|
||||
from gaiatest.form_controls.binarycontrol import GaiaBinaryControl
|
||||
|
||||
|
||||
class SetIceContacts(Base):
|
||||
|
||||
_toggle_locator = (By.CSS_SELECTOR, 'gaia-switch[name="ice-contact-1-enabled"]')
|
||||
_select_ice_contact_1_locator = (By.ID, 'select-ice-contact-1')
|
||||
_ice_settings_header_locator = (By.ID, 'ice-settings-header')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
GaiaApps(marionette).switch_to_displayed_app()
|
||||
header = self.marionette.find_element(*self._ice_settings_header_locator)
|
||||
Wait(self.marionette).until(lambda m: header.rect['x'] == 0 and header.is_displayed())
|
||||
|
||||
def enable_set_ice_contact(self):
|
||||
GaiaBinaryControl(self.marionette, self._toggle_locator).enable()
|
||||
return SetIceContacts(self.marionette)
|
||||
|
||||
def select_ice_contact(self):
|
||||
self.marionette.find_element(*self._select_ice_contact_1_locator).tap()
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
return Contacts(self.marionette)
|
||||
|
||||
def go_back(self):
|
||||
GaiaHeader(self.marionette, self._ice_settings_header_locator).go_back()
|
||||
from gaiatest.apps.contacts.regions.settings_form import SettingsForm
|
||||
return SettingsForm(self.marionette)
|
||||
179
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/settings_form.py
Executable file
179
gaia/tests/python/gaia-ui-tests/gaiatest/apps/contacts/regions/settings_form.py
Executable file
|
|
@ -0,0 +1,179 @@
|
|||
# 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 import GaiaApps
|
||||
from gaiatest.apps.base import Base
|
||||
from gaiatest.form_controls.binarycontrol import GaiaBinaryControl
|
||||
from gaiatest.apps.contacts.regions.set_ice_contacts import SetIceContacts
|
||||
|
||||
|
||||
class SettingsForm(Base):
|
||||
|
||||
_settings_view_locator = (By.ID, 'view-settings')
|
||||
_loading_overlay_locator = (By.ID, 'loading-overlay')
|
||||
_settings_close_button_locator = (By.ID, 'settings-close')
|
||||
_order_by_last_name_switch_locator = (By.CSS_SELECTOR, 'gaia-switch[name="order.lastname"]')
|
||||
_import_from_sim_button_locator = (By.CSS_SELECTOR, "li[id*='import-sim-option'] button")
|
||||
_import_from_sdcard_locator = (By.CSS_SELECTOR, 'button.icon-sd')
|
||||
_import_from_gmail_button_locator = (By.CSS_SELECTOR, 'button.icon-gmail')
|
||||
_import_from_windows_live_button_locator = (By.CSS_SELECTOR, 'button.icon-live')
|
||||
_import_settings_header = (By.ID, 'import-settings-header')
|
||||
_export_to_sd_button_locator = (By.CSS_SELECTOR, 'button[data-l10n-id="memoryCard"]')
|
||||
_export_to_sim_button_locator = (By.CSS_SELECTOR, '#export-options button.icon-sim')
|
||||
_import_contacts_locator = (By.CSS_SELECTOR, 'button[data-l10n-id="importContactsButton"]')
|
||||
_export_contacts_locator = (By.CSS_SELECTOR, 'button[data-l10n-id="exportContactsButton"]')
|
||||
_delete_contacts_locator = (By.ID, 'bulkDelete')
|
||||
_gmail_contacts_imported_locator = (By.CSS_SELECTOR, '.icon.icon-gmail > p > span')
|
||||
_gmail_import_option_locator = (By.ID, 'import-gmail-option')
|
||||
_import_settings_locator = (By.ID, 'import-settings')
|
||||
_select_contacts_locator = (By.ID, 'selectable-form')
|
||||
_import_error_message_locator = (By.CSS_SELECTOR, '#import-live-option > p.error-message')
|
||||
_outlook_import_option_locator = (By.ID, 'import-live-option')
|
||||
_import_from_outlook_button_locator = (By.CSS_SELECTOR, 'button.icon-live')
|
||||
_set_ice_contact_button_locator = (By.ID, 'set-ice')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
view = self.marionette.find_element(*self._settings_view_locator)
|
||||
Wait(self.marionette).until(lambda m: view.rect['y'] == 0)
|
||||
|
||||
def enable_order_by_last_name(self):
|
||||
self._order_by_last_name_switch.enable()
|
||||
|
||||
def disable_order_by_last_name(self):
|
||||
self._order_by_last_name_switch.disable()
|
||||
|
||||
@property
|
||||
def _order_by_last_name_switch(self):
|
||||
return GaiaBinaryControl(self.marionette, self._order_by_last_name_switch_locator)
|
||||
|
||||
def tap_import_contacts(self):
|
||||
import_contacts = Wait(self.marionette).until(
|
||||
expected.element_present(*self._import_contacts_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(import_contacts))
|
||||
import_contacts.tap()
|
||||
import_settings = self.marionette.find_element(*self._import_settings_locator)
|
||||
Wait(self.marionette).until(lambda m: import_settings.location['x'] == 0)
|
||||
|
||||
def tap_export_contacts(self):
|
||||
export_contacts = Wait(self.marionette).until(
|
||||
expected.element_present(*self._export_contacts_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(export_contacts))
|
||||
export_contacts.tap()
|
||||
import_settings = self.marionette.find_element(*self._import_settings_locator)
|
||||
Wait(self.marionette).until(lambda m: import_settings.location['x'] == 0)
|
||||
|
||||
def tap_delete_contacts(self):
|
||||
delete_contacts = Wait(self.marionette).until(
|
||||
expected.element_present(*self._delete_contacts_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(delete_contacts))
|
||||
delete_contacts.tap()
|
||||
select_contacts = self.marionette.find_element(*self._select_contacts_locator)
|
||||
Wait(self.marionette).until(lambda m: select_contacts.location['y'] == 0)
|
||||
|
||||
def tap_import_from_sim(self):
|
||||
import_from_sim = Wait(self.marionette).until(
|
||||
expected.element_present(*self._import_from_sim_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(import_from_sim))
|
||||
import_from_sim.tap()
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
status_message = Wait(self.marionette).until(
|
||||
expected.element_present(*Contacts._status_message_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(status_message))
|
||||
Wait(self.marionette).until(expected.element_not_displayed(status_message))
|
||||
|
||||
@property
|
||||
def gmail_imported_contacts(self):
|
||||
return self.marionette.find_element(*self._gmail_contacts_imported_locator).text
|
||||
|
||||
def tap_import_from_gmail(self):
|
||||
import_from_gmail = Wait(self.marionette).until(
|
||||
expected.element_present(*self._import_from_gmail_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(import_from_gmail))
|
||||
import_from_gmail.tap()
|
||||
from gaiatest.apps.contacts.regions.gmail import GmailLogin
|
||||
return GmailLogin(self.marionette)
|
||||
|
||||
def tap_import_from_sdcard(self):
|
||||
import_from_sdcard = Wait(self.marionette).until(
|
||||
expected.element_present(*self._import_from_sdcard_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(import_from_sdcard))
|
||||
import_from_sdcard.tap()
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
status_message = Wait(self.marionette).until(
|
||||
expected.element_present(*Contacts._status_message_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(status_message))
|
||||
Wait(self.marionette).until(expected.element_not_displayed(status_message))
|
||||
|
||||
def tap_export_to_sd(self):
|
||||
export_to_sdcard = Wait(self.marionette).until(
|
||||
expected.element_present(*self._export_to_sd_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(export_to_sdcard))
|
||||
export_to_sdcard.tap()
|
||||
select_contacts = self.marionette.find_element(*self._select_contacts_locator)
|
||||
Wait(self.marionette).until(lambda m: select_contacts.location['y'] == 0)
|
||||
|
||||
def tap_export_to_sim(self):
|
||||
export_to_sim = Wait(self.marionette).until(
|
||||
expected.element_present(*self._export_to_sim_button_locator))
|
||||
Wait(self.marionette).until(expected.element_displayed(export_to_sim))
|
||||
export_to_sim.tap()
|
||||
select_contacts = self.marionette.find_element(*self._select_contacts_locator)
|
||||
Wait(self.marionette).until(
|
||||
lambda m: select_contacts.rect['y'] == 0 and select_contacts.is_displayed())
|
||||
|
||||
def tap_done(self):
|
||||
close = self.marionette.find_element(*self._settings_close_button_locator)
|
||||
close.tap()
|
||||
Wait(self.marionette).until(expected.element_not_displayed(close))
|
||||
from gaiatest.apps.contacts.app import Contacts
|
||||
return Contacts(self.marionette)
|
||||
|
||||
def tap_back_from_import_contacts(self):
|
||||
header = self.marionette.find_element(*self._import_settings_header)
|
||||
# TODO: remove tap with coordinates after Bug 1061698 is fixed
|
||||
header.tap(25, 25)
|
||||
Wait(self.marionette).until(expected.element_not_displayed(header))
|
||||
|
||||
def tap_set_ice_contact(self):
|
||||
self.marionette.find_element(*self._set_ice_contact_button_locator).tap()
|
||||
return SetIceContacts(self.marionette)
|
||||
|
||||
@property
|
||||
def is_gmail_import_service_in_error(self):
|
||||
gmail_import_service = self.marionette.find_element(*self._gmail_import_option_locator)
|
||||
return 'error' in gmail_import_service.get_attribute('class')
|
||||
|
||||
@property
|
||||
def is_gmail_import_enabled(self):
|
||||
return self.marionette.find_element(*self._import_from_gmail_button_locator).is_enabled()
|
||||
|
||||
@property
|
||||
def is_error_message_displayed(self):
|
||||
return self.is_element_displayed(*self._import_error_message_locator)
|
||||
|
||||
@property
|
||||
def is_outlook_import_service_in_error(self):
|
||||
outlook_import_service = self.marionette.find_element(*self._outlook_import_option_locator)
|
||||
return 'error' in outlook_import_service.get_attribute('class')
|
||||
|
||||
@property
|
||||
def is_outlook_import_enabled(self):
|
||||
return self.marionette.find_element(*self._import_from_outlook_button_locator).is_enabled()
|
||||
|
||||
|
||||
class ConfirmationView(Base):
|
||||
|
||||
_confirmation_locator = (By.ID, 'confirmation-message')
|
||||
_error_message_locator = (By.CSS_SELECTOR, '#confirmation-message p')
|
||||
|
||||
def __init__(self, marionette):
|
||||
Base.__init__(self, marionette)
|
||||
view = self.marionette.find_element(*self._confirmation_locator)
|
||||
Wait(self.marionette).until(lambda m: view.location['y'] == 0)
|
||||
|
||||
@property
|
||||
def error_message(self):
|
||||
return self.marionette.find_element(*self._error_message_locator).text
|
||||
Loading…
Reference in a new issue