# 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 re
import time
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.form_controls.binarycontrol import GaiaBinaryControl
[docs]class Ftu(Base):
name = 'FTU'
_next_button_locator = (By.ID, 'forward')
# Step Languages section
_section_languages_locator = (By.ID, 'languages')
_listed_languages_locator = (By.CSS_SELECTOR, "#languages ul li")
_language_locator = (By.CSS_SELECTOR, "#languages ul li[data-value='%s']")
_language_input_locator = (By.CSS_SELECTOR,
"#languages ul li gaia-radio[name='language.current'][value='%s']")
_selected_language_input_locator = (By.CSS_SELECTOR, "#languages ul li gaia-radio:checked")
# Step Cell data section
_section_cell_data_locator = (By.ID, 'data_3g')
_enable_data_checkbox_locator = (By.ID, 'data-connection-switch')
# Step Wifi
_section_wifi_locator = (By.ID, 'wifi')
_found_wifi_networks_locator = (By.CSS_SELECTOR, 'ul#networks-list li')
_password_input_locator = (By.ID, 'wifi_password')
_join_network_locator = (By.ID, 'wifi-join-button')
_loading_overlay_locator = (By.ID, 'loading-overlay')
# Step Date & Time
_section_date_time_locator = (By.ID, 'date_and_time')
_timezone_continent_locator = (By.CSS_SELECTOR, '#time-form li:nth-child(1) > .change.icon.icon-dialog')
_timezone_city_locator = (By.CSS_SELECTOR, '#time-form li:nth-child(2) > .change.icon.icon-dialog')
_time_zone_title_locator = (By.ID, 'time-zone-title')
# Step Geolocation
_section_geolocation_locator = (By.ID, 'geolocation')
_enable_geolocation_checkbox_locator = (By.ID, 'geolocation-switch')
# Section Import contacts
_section_import_contacts_locator = (By.ID, 'import_contacts')
_import_from_sim_locator = (By.ID, 'sim-import-button')
_sim_import_feedback_locator = (By.ID, 'statusMsg')
# Step Firefox Accounts
_section_firefox_accounts_locator = (By.ID, 'firefox_accounts')
# Section late customization
_section_late_customization_locator = (By.ID, 'late_customization')
# Section Welcome Browser
_section_welcome_browser_locator = (By.ID, 'welcome_browser')
_metrics_basic_locator = (By.ID, 'metrics-basic')
_metrics_enhanced_locator = (By.ID, 'metrics-enhanced')
_metrics_none_locator = (By.ID, 'metrics-none')
# Section Privacy Choices
_section_browser_privacy_locator = (By.ID, 'browser_privacy')
_email_field_locator = (By.CSS_SELECTOR, 'input[type="email"]')
# Section Finish
_section_finish_locator = (By.ID, 'finish-screen')
_skip_tour_button_locator = (By.ID, 'skip-tutorial-button')
_take_tour_button_locator = (By.ID, 'lets-go-button')
# Section Tour
_step_header_locator = (By.ID, 'tutorial-step-title')
_tour_next_button_locator = (By.ID, 'forward-tutorial')
_tour_back_button_locator = (By.ID, 'back-tutorial')
# Section Tutorial Finish
_section_tutorial_finish_locator = (By.ID, 'tutorial-finish-tiny')
_lets_go_button_locator = (By.ID, 'tutorialFinished')
# Pattern for import sim contacts message
_pattern_contacts = re.compile("^No contacts detected on SIM to import$|^Imported one contact$|^Imported [0-9]+ contacts$")
_pattern_contacts_0 = re.compile("^No contacts detected on SIM to import$")
_pattern_contacts_1 = re.compile("^Imported one contact$")
_pattern_contacts_N = re.compile("^Imported ([0-9]+) contacts$")
[docs] def launch(self):
Base.launch(self)
Wait(self.marionette).until(expected.element_displayed(*self._section_languages_locator))
@property
def languages_list(self):
return len(self.marionette.find_elements(*self._listed_languages_locator))
@property
def selected_language(self):
return self.marionette.find_element(*self._selected_language_input_locator).get_attribute(
'value')
[docs] def tap_language(self, language):
self.marionette.find_element(self._language_locator[0], self._language_locator[1] % language).tap()
[docs] def a11y_click_language(self, language):
self.accessibility.click(self.marionette.find_element(self._language_input_locator[0],
self._language_input_locator[1] % language))
@property
def is_take_tour_button_visible(self):
return self.is_element_displayed(*self._take_tour_button_locator)
@property
def is_lets_go_button_visible(self):
return self.is_element_displayed(*self._lets_go_button_locator)
[docs] def tap_next(self):
next_button = Wait(self.marionette).until(
expected.element_present(*self._next_button_locator))
Wait(self.marionette).until(expected.element_displayed(next_button))
Wait(self.marionette).until(expected.element_enabled(next_button))
# In b2g desktop builds, this sleep prevents intermittent failures
time.sleep(0.2)
next_button.tap()
[docs] def a11y_click_next(self):
self.accessibility.click(self.marionette.find_element(*self._next_button_locator))
[docs] def tap_next_to_cell_data_section(self):
self.tap_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_cell_data_locator))
[docs] def a11y_click_next_to_cell_data_section(self):
self.a11y_click_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_cell_data_locator))
[docs] def enable_data(self):
checkbox = Wait(self.marionette).until(
expected.element_present(*self._enable_data_checkbox_locator))
Wait(self.marionette).until(expected.element_displayed(checkbox))
checkbox.tap()
[docs] def a11y_enable_data(self):
checkbox = Wait(self.marionette).until(
expected.element_present(*self._enable_data_checkbox_locator))
Wait(self.marionette).until(expected.element_displayed(checkbox))
self.accessibility.click(checkbox)
[docs] def tap_next_to_wifi_section(self):
progress = self.marionette.find_element(*self._loading_overlay_locator)
self.tap_next()
Wait(self.marionette).until(expected.element_not_displayed(progress))
Wait(self.marionette).until(expected.element_displayed(*self._section_wifi_locator))
[docs] def a11y_click_next_to_wifi_section(self):
self.a11y_click_next()
Wait(self.marionette).until(
expected.element_not_displayed(*self._loading_overlay_locator))
Wait(self.marionette).until(expected.element_displayed(*self._section_wifi_locator))
[docs] def wait_for_networks_available(self):
Wait(self.marionette).until(lambda m: len(m.find_elements(
*self._found_wifi_networks_locator)) > 0,
message='No networks listed on screen')
[docs] def find_wifi_network(self, network_ssid):
wifi_network_locator = (By.CSS_SELECTOR, '#networks-list li[data-ssid="%s"]' % network_ssid)
wifi_network = Wait(self.marionette).until(
expected.element_present(*wifi_network_locator))
self.marionette.execute_script("arguments[0].scrollIntoView(false);", [wifi_network])
Wait(self.marionette).until(expected.element_displayed(wifi_network))
return wifi_network
[docs] def connect_to_wifi(self, network_ssid, password, key_management=None):
wifi_network = self.find_wifi_network(network_ssid)
wifi_network.tap()
# This is in the event we are using a Wifi Network that requires a password
# We cannot be sure of this thus need the logic
if key_management:
password_element = Wait(self.marionette).until(
expected.element_present(*self._password_input_locator))
Wait(self.marionette).until(expected.element_displayed(password_element))
password_element.send_keys(password)
self.marionette.find_element(*self._join_network_locator).tap()
[docs] def a11y_connect_to_wifi(self, network_ssid, password, key_management=None):
wifi_network = self.find_wifi_network(network_ssid)
self.accessibility.click(wifi_network)
# This is in the event we are using a Wifi Network that requires a password
# We cannot be sure of this thus need the logic
if key_management:
password_element = Wait(self.marionette).until(
expected.element_present(*self._password_input_locator))
Wait(self.marionette).until(expected.element_displayed(password_element))
password_element.send_keys(password)
self.accessibility.click(self.marionette.find_element(*self._join_network_locator))
[docs] def tap_next_to_timezone_section(self):
self.tap_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_date_time_locator))
[docs] def a11y_click_next_to_timezone_section(self):
self.a11y_click_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_date_time_locator))
[docs] def set_timezone_continent(self, continent):
element = Wait(self.marionette).until(
expected.element_present(*self._timezone_continent_locator))
Wait(self.marionette).until(expected.element_displayed(element))
element.tap()
self.select(continent)
[docs] def a11y_set_timezone_continent(self, continent):
element = Wait(self.marionette).until(
expected.element_present(*self._timezone_continent_locator))
Wait(self.marionette).until(expected.element_displayed(element))
self.accessibility.click(element)
self.a11y_select(continent)
[docs] def set_timezone_city(self, city):
element = Wait(self.marionette).until(
expected.element_present(*self._timezone_city_locator))
Wait(self.marionette).until(expected.element_displayed(element))
element.tap()
self.select(city)
[docs] def a11y_set_timezone_city(self, city):
element = Wait(self.marionette).until(
expected.element_present(*self._timezone_city_locator))
Wait(self.marionette).until(expected.element_displayed(element))
self.accessibility.click(element)
self.a11y_select(city)
@property
def timezone_title(self):
return self.marionette.find_element(*self._time_zone_title_locator).text
[docs] def tap_next_to_geolocation_section(self):
self.tap_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_geolocation_locator))
[docs] def a11y_click_next_to_geolocation_section(self):
self.a11y_click_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_geolocation_locator))
[docs] def disable_geolocation(self):
self._geolocation_switch.disable()
@property
def is_geolocation_enabled(self):
return self._geolocation_switch.is_checked
@property
def _geolocation_switch(self):
return GaiaBinaryControl(self.marionette, self._enable_geolocation_checkbox_locator)
[docs] def a11y_disable_geolocation(self):
element = Wait(self.marionette).until(
expected.element_present(*self._enable_geolocation_checkbox_locator))
Wait(self.marionette).until(expected.element_displayed(element))
self.accessibility.click(element)
[docs] def tap_import_from_sim(self):
self.marionette.find_element(*self._import_from_sim_locator).tap()
@property
def count_imported_contacts(self):
import_sim_message = self.marionette.find_element(*self._sim_import_feedback_locator).text
import_sim_count = None
if self._pattern_contacts_0.match(import_sim_message) is not None:
import_sim_count = 0
elif self._pattern_contacts_1.match(import_sim_message) is not None:
import_sim_count = 1
elif self._pattern_contacts_N.match(import_sim_message) is not None:
count = self._pattern_contacts_N.match(import_sim_message).group(1)
import_sim_count = int(count)
return import_sim_count
[docs] def tap_next_to_firefox_accounts_section(self):
self.tap_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_firefox_accounts_locator))
[docs] def a11y_click_next_to_firefox_accounts_section(self):
self.a11y_click_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_firefox_accounts_locator))
[docs] def tap_next_to_late_customization_section(self):
self.tap_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_late_customization_locator))
[docs] def tap_next_to_welcome_browser_section(self):
self.tap_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_welcome_browser_locator))
[docs] def a11y_click_next_to_welcome_browser_section(self):
self.a11y_click_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_welcome_browser_locator))
@property
def is_metrics_basic_enabled(self):
return self._metrics_basic_radio.is_checked
[docs] def enable_metrics_basic(self):
self._metrics_basic_radio.enable()
@property
def _metrics_basic_radio(self):
return GaiaBinaryControl(self.marionette, self._metrics_basic_locator)
@property
def is_metrics_enhanced_enabled(self):
return self._metrics_enhanced_radio.is_checked
[docs] def enable_metrics_enhanced(self):
self._metrics_enhanced_radio.enable()
@property
def _metrics_enhanced_radio(self):
return GaiaBinaryControl(self.marionette, self._metrics_enhanced_locator)
@property
def is_metrics_none_enabled(self):
return self._metrics_none_radio.is_checked
[docs] def enable_metrics_none(self):
self._metrics_none_radio.enable()
@property
def _metrics_none_radio(self):
return GaiaBinaryControl(self.marionette, self._metrics_none_locator)
[docs] def tap_next_to_privacy_browser_section(self):
self.tap_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_browser_privacy_locator))
[docs] def a11y_click_next_to_privacy_browser_section(self):
self.a11y_click_next()
Wait(self.marionette).until(
expected.element_displayed(*self._section_browser_privacy_locator))
[docs] def enter_email_address(self, email):
# TODO assert that this is preserved in the system somewhere. Currently it is not used
self.marionette.find_element(*self._email_field_locator).send_keys(email)
self.marionette.switch_to_frame()
Wait(self.marionette).until(lambda m: self.keyboard.is_keyboard_displayed)
self.apps.switch_to_displayed_app()
[docs] def tap_next_to_finish_section(self):
self.tap_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_finish_locator))
[docs] def a11y_click_next_to_finish_section(self):
self.a11y_click_next()
Wait(self.marionette).until(expected.element_displayed(*self._section_finish_locator))
[docs] def tap_skip_tour(self):
element = self.marionette.find_element(*self._skip_tour_button_locator)
self.tap_element_from_system_app(element, add_statusbar_height=True)
[docs] def a11y_click_skip_tour(self):
self.accessibility.click(self.marionette.find_element(*self._skip_tour_button_locator))
[docs] def run_ftu_setup_with_default_values(self):
count = 0
while not self.is_element_displayed(*self._take_tour_button_locator):
if self.is_element_displayed(*self._next_button_locator):
self.tap_next()
else:
count = count + 1
if count > 5:
break
[docs] def tap_take_tour(self):
take_tour = Wait(self.marionette).until(
expected.element_present(*self._take_tour_button_locator))
Wait(self.marionette).until(expected.element_displayed(take_tour))
Wait(self.marionette).until(expected.element_enabled(take_tour))
take_tour.tap()
@property
def step1_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
[docs] def tap_tour_next(self):
next = Wait(self.marionette).until(
expected.element_present(*self._tour_next_button_locator))
Wait(self.marionette).until(expected.element_displayed(next))
Wait(self.marionette).until(expected.element_enabled(next))
next.tap()
[docs] def tap_back(self):
back = Wait(self.marionette).until(
expected.element_present(*self._tour_back_button_locator))
Wait(self.marionette).until(expected.element_displayed(back))
back.tap()
@property
def step2_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
@property
def step3_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
@property
def step4_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
@property
def step5_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
@property
def step6_header_text(self):
header = Wait(self.marionette).until(
expected.element_present(*self._step_header_locator))
Wait(self.marionette).until(expected.element_displayed(header))
return header.text
[docs] def wait_for_finish_tutorial_section(self):
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._section_tutorial_finish_locator))))