# 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 (NoSuchElementException,
StaleElementException)
from marionette_driver.marionette import Actions
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
from gaiatest.apps.calendar.regions.event_details import EventDetails
[docs]class Calendar(Base):
name = 'Calendar'
_current_month_year_locator = (By.ID, 'current-month-year')
_current_month_day_agenda_locator = (By.ID, 'month-day-agenda')
_current_monthly_calendar_locator = (By.ID, 'month-view')
_add_event_button_locator = (By.XPATH, "//a[@href='/event/add/']")
_month_display_button_locator = (By.XPATH, "//a[@href='/month/']")
_week_display_button_locator = (By.XPATH, "//a[@href='/week/']")
_day_display_button_locator = (By.XPATH, "//a[@href='/day/']")
_day_view_locator = (By.ID, 'day-view')
_week_view_locator = (By.ID, 'week-view')
_time_views_locator = (By.ID, 'time-views')
_modify_event_view_locator = (By.ID, 'modify-event-view')
_event_view_locator = (By.ID, 'event-view')
_time_header_locator = (By.ID, 'time-header')
_create_account_button_locator = (By.CLASS_NAME, 'create-account')
_create_account_header_locator = (By.ID, 'create-account-header')
_create_account_view_locator = (By.ID, 'create-account-view')
_create_account_preset_locator = (By.CSS_SELECTOR,
'#create-account-presets a')
_modify_account_header_locator = (By.ID, 'modify-account-header')
_modify_account_view_locator = (By.ID, 'modify-account-view')
_settings_locator = (By.ID, 'settings')
_advanced_settings_view_locator = (By.ID, 'advanced-settings-view')
_advanced_settings_done_button_locator = (By.XPATH, "//a[@href='/settings/']")
_event_list_date_locator = (By.ID, 'event-list-date')
_event_list_empty_locator = (By.ID, 'empty-message')
_event_locator = (By.CLASS_NAME, 'event')
_today_locator = (By.CSS_SELECTOR, '.month.active .present')
_tomorrow_locator = (By.CSS_SELECTOR, '.month.active .present + li > .day')
_day_view_all_day_button = (By.CSS_SELECTOR,
'.day-view .md__allday:nth-child(2) .md__allday-events')
_day_view_event_link = (By.CSS_SELECTOR, '.day-view .md__day:nth-child(2) .md__event')
[docs] def launch(self):
Base.launch(self)
# empty message is only displayed after first MonthsDay#render,
# so we are sure app is "ready" after that
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._event_list_empty_locator))))
@property
def current_month_year(self):
return self.marionette.find_element(*self._current_month_year_locator).text
@property
def current_month_day(self):
return self.marionette.find_element(*self._current_month_day_agenda_locator).get_attribute('data-date')
@property
def event_list_date(self):
return self.marionette.find_element(*self._event_list_date_locator).text
@property
def events(self):
return [self.Event(marionette=self.marionette, element=event)
for event in self.marionette.find_elements(*self._event_locator)]
[docs] def wait_for_events(self, number_to_wait_for=1):
Wait(self.marionette).until(lambda m: len(m.find_elements(*self._event_locator)) == number_to_wait_for)
[docs] def event(self, title):
for event in self.events:
if event.title == title:
return event
@property
def accounts(self):
return [account for account in self.marionette.find_elements(
*self._create_account_preset_locator)]
[docs] def account(self, preset):
for account in self.accounts:
if account.get_attribute('data-provider') == preset:
return account
@property
def settings(self):
return self.Settings(marionette=self.marionette,
element=self.marionette.find_elements(*self._settings_locator))
[docs] def wait_for_new_event(self):
from gaiatest.apps.calendar.regions.event import NewEvent
new_event = NewEvent(self.marionette)
new_event.wait_for_panel_to_load()
return new_event
[docs] def displayed_events_in_month_view(self):
return self.marionette.find_element(*self._get_events_locator_in_month_view()).text
[docs] def displayed_events_in_week_view(self, data_date):
return self.marionette.find_element(*self._get_events_locator_in_week_view(data_date)).text
[docs] def displayed_events_in_day_view(self, data_date):
return self.marionette.find_element(*self._get_events_locator_in_day_view(data_date)).text
def _get_events_locator_in_day_view(self, data_date):
return (By.CSS_SELECTOR,
"#day-view .md__day[data-date*='%s'] .md__event" % data_date)
def _get_events_locator_in_month_view(self):
return (By.CSS_SELECTOR,
'#event-list .event')
def _get_events_locator_in_week_view(self, data_date):
return (By.CSS_SELECTOR,
"#week-view .md__day[data-date*='%s'] .md__event" % data_date)
[docs] def a11y_click_other_day(self, next, previous):
try:
# Try clicking tomorrow
self.accessibility.click(self.marionette.find_element(*self._tomorrow_locator))
return next
except NoSuchElementException:
# Tomorrow is next week or month, try clicking yesterday.
yesterday = self.marionette.execute_script(
"return arguments[0].previousSibling.querySelector('.day');",
[self.marionette.find_element(*self._today_locator)])
self.accessibility.click(yesterday)
return previous
[docs] def wait_fot_settings_drawer_animation(self):
el = self.marionette.find_element(*self.settings._settings_drawer_locator)
Wait(self.marionette).until(lambda m: el.get_attribute('data-animstate') == 'done')
[docs] def a11y_click_create_account_back(self):
self.a11y_click_header(self.marionette.find_element(*self._create_account_header_locator),
'button.action-button')
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._advanced_settings_view_locator))))
[docs] def a11y_click_modify_account_back(self):
self.a11y_click_header(self.marionette.find_element(*self._modify_account_header_locator),
'button.action-button')
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(
*self._create_account_view_locator))))
[docs] def a11y_click_settings(self):
self.a11y_click_header(self.marionette.find_element(*self._time_header_locator),
'button.action-button')
self.wait_fot_settings_drawer_animation()
[docs] def a11y_click_close_settings(self):
self.a11y_click_header(self.marionette.find_element(
*self.settings._settings_header_locator), 'button.action-button')
self.wait_fot_settings_drawer_animation()
[docs] def a11y_create_event(self, title):
new_event = self.a11y_click_add_event_button()
# create a new event
new_event.a11y_fill_event_title(title)
new_event.a11y_click_save_event()
self.wait_for_events(1)
[docs] def a11y_click_day_view_event(self):
self.accessibility.click(self.marionette.find_element(*self._day_view_event_link))
el = self.marionette.find_element(*self._event_view_locator)
Wait(self.marionette).until(expected.element_displayed(el))
return EventDetails(self.marionette)
[docs] def flick_to_next_month(self):
self._flick_to_month('next')
[docs] def flick_to_previous_month(self):
self._flick_to_month('previous')
[docs] def a11y_wheel_to_next_month(self):
self._a11y_wheel_to_month('left')
[docs] def a11y_wheel_to_previous_month(self):
self._a11y_wheel_to_month('right')
def _a11y_wheel_to_month(self, direction):
self.accessibility.wheel(self.marionette.find_element(
*self._current_monthly_calendar_locator), direction)
def _flick_to_month(self, direction):
"""Flick current monthly calendar to next or previous month.
@param direction: flick to next month if direction='next', else flick to previous month
"""
action = Actions(self.marionette)
month = self.marionette.find_element(
*self._current_monthly_calendar_locator)
month_year = self.current_month_year
x_start = (month.size['width'] / 100) * (direction == 'next' and 90 or 10)
x_end = (month.size['width'] / 100) * (direction == 'next' and 10 or 90)
y_start = month.size['height'] / 4
y_end = month.size['height'] / 4
action.flick(month, x_start, y_start, x_end, y_end, 200).perform()
Wait(self.marionette).until(lambda m: self.current_month_year != month_year)
[docs] class Settings(PageRegion):
_calendar_local_locator = (By.CSS_SELECTOR, '#calendar-local-first .pack-checkbox')
_calendar_local_checkbox_locator = (By.CSS_SELECTOR,
'#calendar-local-first input[type="checkbox"]')
_advanced_settings_button_locator = (By.CSS_SELECTOR, '.settings')
_settings_header_locator = (By.ID, 'settings-header')
_settings_drawer_locator = (By.CLASS_NAME, 'settings-drawer')
[docs] def wait_for_calendar_unchecked(self, timeout=None):
checkbox = self.marionette.find_element(*self._calendar_local_checkbox_locator)
Wait(self.marionette, timeout).until(expected.element_not_selected(checkbox))
[docs] def wait_for_a11y_calendar_unchecked(self, timeout=None):
Wait(self.marionette, timeout, ignored_exceptions=StaleElementException).until(
lambda m: not self.marionette.find_element(
*self._calendar_local_locator).get_attribute('aria-selected'))
[docs] class Event(PageRegion):
_title_locator = (By.TAG_NAME, 'h5')
_location_locator = (By.CLASS_NAME, 'location')
_event_view_locator = (By.ID, 'event-view')
@property
def title(self):
return self.root_element.find_element(*self._title_locator).text
@property
def location(self):
return self.root_element.find_element(*self._location_locator).text
[docs] def a11y_click(self):
self.accessibility.click(self.root_element)
el = self.marionette.find_element(*self._event_view_locator)
Wait(self.marionette).until(expected.element_displayed(el))
return EventDetails(self.marionette)