Source code for gaiatest.apps.contacts.app

# 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


[docs]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')
[docs] 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)
[docs] 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)]
[docs] 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))
[docs] def contact(self, name): for contact in self.contacts: if contact.name == name: return contact
[docs] 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
[docs] 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
[docs] 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)
[docs] 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()
[docs] def tap_export(self): self._tap_action_button()
[docs] 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()
[docs] 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()
[docs] 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)
[docs] 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()
[docs] 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')
[docs] 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)
[docs] 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()