"""The Subjects page."""
from time import sleep
from pypom import Region
from pypom.exception import UsageError
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from pages.web.base import WebBase
from utils.utilities import Utility, go_to_
from utils.web import Library, Web, WebException
[docs]class Subjects(WebBase):
"""The subjects page."""
URL_TEMPLATE = '/subjects'
AUTHORS = 0
SEQUENCE = 1
PEER_REVIEWED = 2
category_xpath = '//div[h2[text()="{subject}"]]'
_loader_locator = (By.CSS_SELECTOR, '.subjects-page.loaded')
_banner_locator = (By.CSS_SELECTOR, '.hero')
_slogan_locator = (By.CSS_SELECTOR, '.hero h2')
_blurb_locator = (By.CSS_SELECTOR, '.hero p')
_filter_toggle_locator = (By.CSS_SELECTOR, '.filter-buttons')
_filter_button_locator = (By.CLASS_NAME, 'filter-button')
_filter_by_locator = (By.CSS_SELECTOR,
'.filter-buttons [aria-pressed=true]')
_about_our_textbooks_locator = (By.CSS_SELECTOR, '.text-content')
_about_blurb_locator = (By.CSS_SELECTOR, '.text-content ~ div .blurb')
_category_locator = (By.CSS_SELECTOR, '.book-category')
_math_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_MATH))
_science_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_SCIENCE))
_social_sciences_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_SOCIAL_SCIENCES))
_humanities_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_HUMANITIES))
_business_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_BUSINESS))
_essentials_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_ESSENTIALS))
_college_success_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_COLLEGE_SUCCESS))
_ap_category_locator = (
By.XPATH, category_xpath.format(subject=Web.VIEW_AP.replace('®', '')))
_book_locator = (By.CSS_SELECTOR, 'div.book-category:not(.hidden) .cover')
_image_locators = (By.CSS_SELECTOR, _book_locator[1] + ' img')
@property
def loaded(self):
"""Override the base loader."""
return (
self.find_element(*self._loader_locator) and
self.find_element(*self._category_locator) and
Utility.is_image_visible(self.driver,
locator=self._image_locators))
[docs] def wait_for_page_to_load(self):
"""Override the page wait."""
WebDriverWait(self.driver, 15).until(
lambda _: self.loaded)
self.pm.hook.pypom_after_wait_for_page_to_load(page=self)
return self
[docs] def open(self):
"""Open the page."""
if self.seed_url:
tries = 0
while tries < 1:
try:
self.driver_adapter.open(self.seed_url)
self.wait_for_page_to_load()
break
except WebDriverException:
tries = tries + 1
return self
raise UsageError("Set a base URL or URL_TEMPLATE to open this page.")
[docs] def is_displayed(self):
"""Return True if the subjects page is displayed."""
if self.URL_TEMPLATE not in self.location:
return False
return self.loaded
@property
def filters(self):
"""Return the available filters."""
return [self.Filter(self, button)
for button in self.find_elements(*self._filter_button_locator)]
[docs] def filter_toggle(self):
"""Click on the filter menu to show the filter options."""
toggle = self.find_element(*self._filter_toggle_locator)
Utility.click_option(self.driver, element=toggle)
return self
@property
def total_filters(self):
"""Return the number the filter options available."""
return len(self.filters)
[docs] def is_filtered_by(self, subject_filter):
"""Return True if the books are filtered by the submitted subject."""
return (subject_filter
in self.find_element(*self._filter_by_locator)
.get_attribute('textContent'))
@property
def math(self):
"""Return the subjects filtered by math titles."""
math_root = self.find_element(*self._math_category_locator)
return self.Category(self, math_root)
@property
def science(self):
"""Return the subjects filtered by the science titles."""
science_root = self.find_element(*self._science_category_locator)
return self.Category(self, science_root)
@property
def social_sciences(self):
"""Return the subjects filtered by the social sciences titles."""
social_root = self.find_element(
*self._social_sciences_category_locator)
return self.Category(self, social_root)
@property
def humanities(self):
"""Return the subjects filtered by the humanities titles."""
humanities_root = self.find_element(*self._humanities_category_locator)
return self.Category(self, humanities_root)
@property
def business(self):
"""Return the subjects filtered by the business titles."""
business_root = self.find_element(*self._business_category_locator)
return self.Category(self, business_root)
@property
def essentials(self):
"""Return the subjects filtered by the essentials titles."""
essentials_root = self.find_element(*self._essentials_category_locator)
return self.Category(self, essentials_root)
@property
def college_success(self):
"""Return the subjects filtered by the College Success titles."""
success_root = self.find_element(
*self._college_success_category_locator)
return self.Category(self, success_root)
@property
def ap(self):
"""Return the subjects filtered by the AP titles."""
ap_root = self.find_element(*self._ap_category_locator)
return self.Category(self, ap_root)
@property
def _active_books(self):
"""Select active books for use by the class."""
return [Book(self, book)
for book in self.find_elements(*self._book_locator)]
@property
def ap_books(self):
"""Select active AP books."""
return self._selection_helper(Library().ap)
@property
def available_books(self):
"""Select active books."""
return self._selection_helper(Library().available)
@property
def bookshare_books(self):
"""Select active books available through Bookshare."""
return self._selection_helper(Library().bookshare)
@property
def business_books(self):
"""Select active business books."""
return self._selection_helper(Library().business)
@property
def comp_copy(self):
"""Select the current editions of each book."""
return self._selection_helper(Library().comp_copy)
@property
def current_books(self):
"""Select the current editions of each book."""
return self._selection_helper(Library().current)
@property
def essentials_books(self):
"""Select active essentials books."""
return self._selection_helper(Library().essentials)
@property
def humanities_books(self):
"""Select active humanities books."""
return self._selection_helper(Library().humanities)
@property
def kindle_books(self):
"""Select active books with a Kindle edition available."""
return self._selection_helper(Library().kindle)
@property
def itunes_books(self):
"""Select active books with an iBook eddition available."""
return self._selection_helper(Library().itunes)
@property
def locked_instructor(self):
"""Select active books with locked instructor resources."""
return self._selection_helper(Library().locked_instructor)
@property
def locked_student(self):
"""Select active books with locked student resources."""
return self._selection_helper(Library().locked_student)
@property
def math_books(self):
"""Select active math books."""
return self._selection_helper(Library().math)
@property
def old_book_editions(self):
"""Select the books with a newer editions available."""
return self._selection_helper(Library().superseded)
@property
def openstax_books(self, filter_current=False):
"""Select active books while excluding Polish versions."""
return [book for book in self._active_books
if book.language == Library.ENGLISH]
@property
def polish_books(self):
"""Select active books in Polish."""
return [book for book in self._active_books
if book.language == Library.POLISH]
@property
def print_books(self):
"""Select the books with a current print edition available."""
return self._selection_helper(Library().print)
@property
def science_books(self):
"""Select active science books."""
return self._selection_helper(Library().science)
@property
def social_sciences_books(self):
"""Select active social science books."""
return self._selection_helper(Library().social_sciences)
@property
def unlocked_instructor(self):
"""Select active books with unlocked instructor resources."""
return self._selection_helper(Library().unlocked_instructor)
@property
def unlocked_student(self):
"""Select active books with unlocked student resources."""
return self._selection_helper(Library().unlocked_student)
[docs] def select_book(self, book_title):
"""Return the book page for a specific title.
:param str book_title: the full book title found in the alt field
:return: the book page for the selected title
:rtype: :py:class:`~pages.web.book.Book`
"""
append = Library().get(book_title, field=Library.DETAILS)
selector = '[href$="{book_details}"]'.format(book_details=append)
book = self.find_element(By.CSS_SELECTOR, selector)
Utility.click_option(self.driver, element=book)
from pages.web.book import Book as Details
return go_to_(Details(self.driver, book_name=append))
[docs] def select_random_book(self, _from=Library.OPENSTAX, filter_current=False):
"""Return a random book from the active list."""
using = {
Library.ALL_BOOKS: self._active_books,
Library.AP: self.ap_books,
Library.AVAILABLE: self.available_books,
Library.BOOKSHARE: self.bookshare_books,
Library.BUSINESS: self.business_books,
Library.COMP_COPY: self.comp_copy,
Library.CURRENT: self.current_books,
Library.HAS_I_LOCK: self.locked_instructor,
Library.HAS_I_UNLOCK: self.unlocked_instructor,
Library.HAS_S_LOCK: self.locked_student,
Library.HAS_S_UNLOCK: self.unlocked_student,
Library.HUMANITIES: self.humanities_books,
Library.ITUNES: self.itunes_books,
Library.KINDLE: self.kindle_books,
Library.MATH: self.math_books,
Library.OPENSTAX: self.openstax_books,
Library.POLISH: self.polish_books,
Library.PRINT_COPY: self.print_books,
Library.SCIENCE: self.science_books,
Library.SOCIAL: self.social_sciences_books,
Library.SUPERSEDED: self.old_book_editions,
}.get(_from)
if filter_current:
using = list(filter(
lambda book: book.title not in Library.OLD_EDITIONS, using))
total = len(using)
if total <= 0:
raise WebException('No books are available for selection')
book = Utility.random(0, total - 1)
selected = using[book]
print('Selected book: {0}'.format(selected.title))
destination = selected.url_append
selected.select()
sleep(1.0)
from pages.web.book import Book as Details
return go_to_(Details(self.driver, book_name=destination))
def _selection_helper(self, modifier):
"""Return a list of books for a modified collection."""
library = Library()
collection = library.get_titles(modifier)
return [book for book in self._active_books
if book.title in collection]
[docs] def view_about_our_textbooks(self):
"""Scroll to the textbook blurbs."""
Utility.scroll_to(self.driver, self._about_our_textbooks_locator)
return self
@property
def about(self):
"""Return the about blurb texts."""
return [self.About(self, blurb)
for blurb in self.find_elements(*self._about_blurb_locator)]
[docs] class Filter(Region):
"""Subject filters."""
_subject_locator = (By.CSS_SELECTOR, '[data-html]')
@property
def subject(self):
"""Return the filter subject."""
return self.find_element(*self._subject_locator).text
@property
def value(self):
"""Return the category value."""
return self.root.get_attribute('data-value')
[docs] def view_books(self):
"""Select the filter category to view the topic textbooks."""
Utility.click_option(self.driver, element=self.root)
return self.page
@property
def is_selected(self):
"""Return True if the filter is active."""
return self.root.get_attribute('aria-pressed') == 'true'
[docs] class Category(Region):
"""Subject category information."""
_category_name_locator = (By.CSS_SELECTOR, 'h2')
_book_locator = (By.CSS_SELECTOR, '.cover')
@property
def section(self):
"""Return the category title."""
return self.find_element(*self._category_name_locator).text
@property
def is_visible(self):
"""Return True if the category is displayed."""
return 'hidden' not in self.root.get_attribute('class')
@property
def books(self):
"""Return category books."""
return [Book(self, book)
for book in self.find_elements(*self._book_locator)]
[docs] class About(Region):
"""An About Our Textbooks blurb."""
_title_locator = (By.CSS_SELECTOR, '.title')
_blurb_locator = (By.CSS_SELECTOR, '.text p')
@property
def title(self):
"""Return the blurb title."""
return self.find_element(*self._title_locator).text
@property
def blurb(self):
"""Return the blurb text."""
return self.find_element(*self._blurb_locator).text
[docs]class Book(Region):
"""A single book title."""
_url_locator = (By.TAG_NAME, 'a')
_image_locator = (By.TAG_NAME, 'img')
@property
def title(self):
"""Return the book title."""
return self.image.get_attribute('alt')
@property
def image(self):
"""Return the image element."""
return self.find_element(*self._image_locator)
@property
def image_source(self):
"""Return the image source URL."""
return self.image.get_attribute('src')
@property
def url(self):
"""Return the book URL."""
return self.find_element(*self._url_locator).get_attribute('href')
@property
def url_append(self):
"""Return the last part of the URL."""
return self.url.split('/')[-1]
@property
def language(self):
"""Return the book language."""
if 'Fizyka' in self.title:
return 'Polish'
return 'English'
[docs] def select(self):
"""Click on the book cover."""
book_name = self.url_append
Utility.click_option(
self.driver, element=self.find_element(*self._url_locator))
from pages.web.book import Book as Details
return go_to_(Details(self.driver,
self.page.base_url,
self.page.timeout,
book_name=book_name))