"""Basic page parent for all Accounts pages."""
from __future__ import annotations
from time import sleep
from typing import Union
from pypom import Page, Region
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By
from pages.rice.home import Rice
from utils.accounts import AccountsException
from utils.utilities import Utility, go_to_
[docs]class AccountsBase(Page):
"""The base page for each Accounts class."""
_body_tag_locator = (
By.CSS_SELECTOR, 'body')
_content_locator = (
By.CSS_SELECTOR, '.main-menu ~ .content:not([id]), #application-body')
_footer_locator = (
By.CSS_SELECTOR, '.main-menu ~ [id*=footer], #application-footer')
_main_menu_locator = (
By.CSS_SELECTOR, '.main-menu, #application-header')
@property
def content(self) -> AccountsBase.Content:
"""Access the Accounts' page content.
:return: the Accounts page content
:rtype: :py:class:`~pages.accounts.base.AccountsBase.Content`
"""
content_root = self.find_element(*self._content_locator)
return self.Content(self, content_root)
@property
def footer(self) -> AccountsBase.Footer:
"""Access the Accounts' page footer.
:return: the Accounts page footer
:rtype: :py:class:`~pages.accounts.base.AccountsBase.Footer`
"""
footer_root = self.find_element(*self._footer_locator)
return self.Footer(self, footer_root)
@property
def is_safari(self) -> bool:
"""Return True if the browser in use is Safari.
:return: ``True`` if the browser in use is Safari
:rtype: bool
"""
return self.driver.capabilities.get('browserName').lower() == 'safari'
[docs] def is_displayed(self) -> bool:
"""Return True when the Accounts content is displayed.
:return: ``True`` when the Accounts main body content is displayed
:rtype: bool
"""
try:
return self.find_element(*self._content_locator).is_displayed()
except NoSuchElementException:
return False
@property
def loaded(self) -> bool:
"""Return True when the Accounts page is loaded.
.. note::
We delay the check by 1/2 second for Safari and Firefox to insure
the page is loading prior to the full DOM ``load``.
:return: ``True`` when the Accounts content is found
:rtype: bool
"""
self.wait.until(
lambda _: self.find_elements(*self._body_tag_locator))
script = (r'document.addEventListener("load", function(event) {});')
sleep(0.5)
return self.driver.execute_script(script) or self.content
@property
def location(self) -> str:
"""Return the current URL.
:return: the current page URL
:rtype: str
"""
return self.driver.current_url
@property
def menu(self) -> Union[AccountsBase.MenuBar, None]:
"""Access the Accounts' page menu bar, if found.
:return: the Accounts' menu bar or ``None`` if it is missing (Profile)
:rtype: :py:class:`~pages.accounts.base.AccountsBase.MenuBar` or None
"""
bar_root = self.find_element(*self._main_menu_locator)
return self.MenuBar(self, bar_root)
@property
def page_source(self) -> str:
"""Return the current page source HTML.
:return: the current page source
:rtype: str
"""
return self.driver.page_source
@property
def url(self) -> str:
"""Return the last segment of the current URL.
:return: the final segment of the current URL (everything after the
last '/')
:rtype: str
"""
return self.location.split('/')[-1]
[docs] def back(self) -> Page:
"""Go to the previous page in the browser history.
:return: the current page
:rtype: :py:class:`~pages.accounts.base.AccountsBase`
"""
self.driver.execute_script(
'window.history.go(-1);'
r'document.addEventListener("DOMContent", function(event) {});')
return self
[docs] def close_tab(self):
"""Close the current tab and switch to the remaining one.
.. note::
Assumes 2 browser tabs are open; switches the window handle to the
remaining tab.
:return: None
"""
Utility.close_tab(self.driver)
[docs] def reload(self) -> Page:
"""Reload the current page.
:return: the current page
:rtype: :py:class:`~pages.accounts.base.AccountsBase`
"""
self.driver.refresh()
self.wait_for_page_to_load()
return self
[docs] def resize_window(self, width: int = 1024, height: int = 768):
"""Set the browser window size.
.. note::
We default to a standard 4:3 ratio 1024px x 768px.
:param int width: (optional) the desired browser window width
:param int height: (optional) the desired browser window height
:return: None
"""
self.driver.set_window_size(width, height)
sleep(1.0)
[docs] class Content(Region):
"""The main content region."""
_header_text_locator = (
By.CSS_SELECTOR, '.page-header')
_log_in_tab_locator = (
By.CSS_SELECTOR, '.tab.login')
_sign_up_tab_locator = (
By.CSS_SELECTOR, '.tab.signup')
@property
def header(self) -> str:
"""Return the page heading.
:return: the body content header
:rtype: str
"""
return self.find_element(*self._header_text_locator).text
[docs] def view_log_in(self) -> Page:
"""Click the Log in tab.
:return: the Accounts Log in page
:rtype: :py:class:`~pages.accounts.home.AccountsHome`
"""
tab = self.find_element(*self._log_in_tab_locator)
Utility.click_option(self.driver, element=tab)
from page.accounts.home import AccountsHome
return go_to_(AccountsHome(self.driver, self.page.base_url))
[docs] def view_sign_up(self) -> Page:
"""Click the Sign up tab.
:return: the Accounts Log in page
:rtype: :py:class:`~pages.accounts.home.AccountsHome`
"""
tab = self.find_element(*self._sign_up_tab_locator)
Utility.click_option(self.driver, element=tab)
from pages.accounts.signup import Signup
return go_to_(Signup(self.driver, self.page.base_url))