def test_modal_for_unsaved_notes_appears_on_clicking_another_highlight( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & clicking another highlight.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() while book.notification_present: book.notification.got_it() book.navbar.click_login() name, email = Signup(selenium).register() book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() book.content.show_solutions() # AND: Highlight 2 paragraphs paragraphs = random.sample(book.content.paragraphs, 2) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE) id_1 = list(set(book.content.highlight_ids))[0] book.content.highlight(target=paragraphs[1], offset=Highlight.ENTIRE, close_box=False) _ids = book.content.highlight_ids id_2 = _ids[0] if _ids[0] != id_1 else _ids[1] # AND: Add note to the 2nd highlight and do not save note = Utilities.random_string() book.content.highlight_box.note = note # WHEN: click the first highlight highlight = book.content.get_highlight(by_id=id_1) Utilities.click_option(driver=selenium, element=highlight[0], scroll_to=-150) # THEN: Discard modal is displayed assert book.discard_changes_modal_displayed assert book.discard_modal.content == "You have an unsaved note on this page." assert book.discard_modal.title == "Discard unsaved changes?" # AND: Clicking Cancel closes the modal and the unsaved note is retained in the page book.discard_modal.click_cancel_changes() assert book.content.highlight_box.is_open, "Highlight box not open" assert book.content.highlight_box.is_edit_box highlight = book.content.get_highlight(by_id=id_2)[0] assert "focus" in highlight.get_attribute("class"), "highlight is not in focus" assert book.content.highlight_box.note == note # WHEN: click the 1st highlight again highlight = book.content.get_highlight(by_id=id_1) Utilities.click_option(driver=selenium, element=highlight[0], scroll_to=-150) # AND: click Discard changes in the modal book.discard_modal.click_discard_changes() # THEN: Unsaved note is abandoned and the highlight box is opened for the 1st highlight assert book.content.highlight_box.is_open, "Highlight box not open" highlight = book.content.get_highlight(by_id=id_1)[0] assert "focus" in highlight.get_attribute("class"), "highlight is not in focus" assert book.content.highlight_box.note == ""
def click_login(self): if self.is_desktop: log_in = self.find_element(*self._desktop_log_in_link_locator) else: self.click_mobile_user_nav() log_in = self.find_element(*self._mobile_log_in_link_locator) Utilities.click_option(self.driver, element=log_in)
def click(self): """Click the filter checkbox. Toggles between selected and unchecked. """ checkbox = self.find_element(*self._checkbox_locator) Utilities.click_option(self.driver, element=checkbox)
def sign_up(self): """Click the sign up link.""" WebDriverWait(self.driver, 1).until( expect.visibility_of_element_located( self._signup_link_or_tab_locator)) signup_link = self.find_element(*self._signup_link_or_tab_locator) Utilities.click_option(self.driver, element=signup_link)
def toggle_menu(self) -> MyHighlights.Highlights.EditHighlight: """Toggle the highlight context menu open or close. :return: the edit highlight box :rtype: :py:class:`~MyHighlights.Highlights.EditHighlight` """ Utilities.click_option(self.driver, element=self.toggle) return self
def remove_tag(self) -> MyHighlights: """Click the remove filter 'x' button. :return: the My Highlights and Notes modal :rtype: :py:class:`~MyHighlights` """ Utilities.click_option(self.driver, element=self.remove_tag_icon) return self.page.page
def save(self) -> MyHighlights: """Click the save note button. :return: the My Highlights and Notes modal :rtype: :py:class:`~MyHighlights` """ Utilities.click_option(self.driver, element=self.save_button) return self.page
def close(self) -> Page: """Close the Practice modal. :return: the parent page :rtype: :py:class:`~pages.base.Page` """ Utilities.click_option(self.driver, element=self.close_x_button) return self.page
def close_search_sidebar(self): try: button = self.close_search_sidebar_button except NoSuchElementException: return Utilities.click_option(self.driver, element=button) self.wait.until( lambda _: not self.driver.execute_script( VISIBILITY, self.close_search_sidebar_button))
def select(self): """Select this answer for the current question. :return: None """ radio_button = self.find_element(*self._radio_button_locator) Utilities.click_option(self.driver, element=radio_button) sleep(0.2)
def toggle(self) -> Practice.Filters: """Toggle the chapter/section selector menu. :return: the practice selector menu :rtype: :py:class:`~regions.practice.Practice.Filters` """ Utilities.click_option(self.driver, element=self.root) sleep(0.1) return self.page
def close(self) -> Page: """Click the close 'x' button. :return: the modal's parent page :rtype: :py:class:`~pypom.Page` """ Utilities.click_option(self.driver, element=self.close_icon) self.wait.until(expect.staleness_of(self.root)) return self.page
def select(self) -> Practice: """Select the section to practice. :return: the practice modal :rtype: :py:class:`~regions.practice.Practice` """ Utilities.click_option(self.driver, element=self.root) sleep(0.25) return self.page.page.page
def click_notification_got_it(self): """Click the 'Got it!' button. :return: the home page :rtype: :py:class:`~pages.web.home.WebHome` """ button = self.find_element(*self._got_it_button_locator) Utilities.click_option(self.driver, element=button) self.wait.until(lambda _: not self.notification_dialog_displayed)
def select_none(self) -> MyHighlights: """Click the select None link to clear all filter options. :return: the My Highlights and Notes modal :rtype: :py:class:`~MyHighlights` """ link = self.find_element(*self._select_none_locator) Utilities.click_option(self.driver, element=link) return self.page
def toggle(self) -> Practice.Filters: """Toggle the chapter/section selector menu. :return: the practice selector menu :rtype: :py:class:`~regions.practice.Practice.Filters` """ button = self.find_element(*self._toggle_button_locator) Utilities.click_option(self.driver, element=button) sleep(0.1) return self
def test_modal_for_unsaved_notes_appears_on_clicking_content_links( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & clicking in-content link.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() while book.notification_present: book.notification.got_it() book.navbar.click_login() name, email = Signup(selenium).register() book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() # AND: Highlight a paragraph, add a note & do not save paragraphs = random.sample(book.content.paragraphs, 1) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, close_box=False) note = Utilities.random_string() book.content.highlight_box.note = note id_1 = book.content.highlight_ids[0] # WHEN: Click on a in-content link link = random.sample(book.content.links, 1) Utilities.click_option(selenium, element=link[0]) # THEN: Discard modal is displayed assert book.discard_changes_modal_displayed assert book.discard_modal.content == "You have an unsaved note on this page." assert book.discard_modal.title == "Discard unsaved changes?" # WHEN: Click Cancel on the modal book.discard_modal.click_cancel_changes() # THEN: The modal is closed and the unsaved note is retained on the page assert book.content.highlight_box.is_open, "Highlight box not open" assert book.content.highlight_box.is_edit_box highlight = book.content.get_highlight(by_id=id_1)[0] assert "focus" in highlight.get_attribute("class"), "highlight is not in focus" assert book.content.highlight_box.note == note # WHEN: Click the same link again Utilities.click_option(selenium, element=link[0]) # AND: click Discard changes in the modal book.discard_modal.click_discard_changes() book.wait_for_page_to_load() # THEN: The page scrolls to the clicked link assert book.element_in_viewport(link[0]) # AND: The unsaved note is not saved assert not selenium.execute_script(HAS_INDICATOR, highlight), "note is saved for the highlight"
def log_in(self) -> Login: """Click the 'Log in' link. :return: the Accounts log in page :rtype: :py:class:`~pages.accounts.Login` """ Utilities.click_option(self.driver, element=self.log_in_link) page = Login(self.driver) page.wait_for_page_to_load() return page
def click_delete(self) -> MyHighlights.Highlights.EditHighlight: """Toggle the highlight delete menu option. :return: the note delete box :rtype: :py:class:`~MyHighlights.Highlights.EditHighlight` """ self.toggle_menu() Utilities.click_option(self.driver, element=self.delete_button) return self
def edit_note(self) -> MyHighlights.Highlights.EditHighlight: """Toggle the annotation edit menu option. :return: the note edit box :rtype: :py:class:`~MyHighlights.Highlights.EditHighlight` """ self.toggle_menu() Utilities.click_option(self.driver, element=self.edit_button) return self
def back_to_top(self) -> MyHighlights: """Click the back to top arrow button. :return: the My Highlights and Notes modal scrolled to the top :rtype: :py:class:`~regions.my_highlights.MyHighlights` """ if self.back_to_top_available: button = self.find_element(*self._back_to_top_button_locator) Utilities.click_option(self.driver, element=button) sleep(0.33) return self
def _click_helper(self, locator: Locator) -> Practice.Content: """Click a link or button. :param locator: a By-style element selector :type locator: tuple(str, str) :return: the practice content pane :rtype: :py:class:`~regions.practice.Practice.Content` """ button = self.find_element(*locator) Utilities.click_option(self.driver, element=button) return self
def confirm_email(self, email: RestMail): """Confirm the user's email address. :param email: the user's RestMail instance :type email: :py:class:`~utils.utility.RestMail` """ inbox = email.wait_for_mail() verification_pin = inbox[-1].pin pin_field = self.find_element(*self._pin_entry_input_locator) pin_field.send_keys(verification_pin) confirm_button = self.find_element(*self._confirm_button_locator) Utilities.click_option(self.driver, element=confirm_button)
def select_password(self, password: str): """Select and confirm the user's password. :param str password: the user's password """ password_field = self.find_element( *self._password_select_input_locator) password_field.send_keys(password) password_confirmation_field = self.find_element( *self._password_confirmation_input_locator) password_confirmation_field.send_keys(password) submit_button = self.find_element(*self._submit_button_locator) Utilities.click_option(self.driver, element=submit_button)
def test_change_color_from_MH_page(selenium, base_url, book_slug, page_slug): """Changing highlight color from MH page, updates the highlight in content page.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() while book.notification_present: book.notification.got_it() book.navbar.click_login() name, email = Signup(selenium).register() book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() # AND: Highlight 2 set of texts in the page paragraph = random.sample(book.content.paragraphs, 2) note = Utilities.random_string() content_highlight_ids = book.content.highlight_ids data = [(paragraph[0], Color.GREEN, note), (paragraph[1], Color.YELLOW, note == "")] for paragraphs, colors, note in data: book.content.highlight(target=paragraphs, offset=Highlight.RANDOM, color=colors, note=note) content_highlight_ids = content_highlight_ids + list( set(book.content.highlight_ids) - set(content_highlight_ids) ) # WHEN: Change highlight color of the 2nd highlight from MH page my_highlights = book.toolbar.my_highlights() highlight = my_highlights.highlights.edit_highlight highlight_id_0 = highlight[0].mh_highlight_id highlight_id_1 = highlight[1].mh_highlight_id new_highlight_color = Color.PINK highlight[1].toggle_menu() highlight[1].toggle_color(new_highlight_color) highlight[1].toggle_menu() my_highlights.close() # Determine the current color of the highlights in the content page highlight_classes_0 = book.content.get_highlight(by_id=highlight_id_0)[0].get_attribute("class") highlight_0_color_after_MH_color_change = Color.from_html_class(highlight_classes_0) highlight_classes_1 = book.content.get_highlight(by_id=highlight_id_1)[0].get_attribute("class") highlight_1_color_after_MH_color_change = Color.from_html_class(highlight_classes_1) # THEN: The highlight color in the content page is changed correctly assert ( highlight_1_color_after_MH_color_change == new_highlight_color ), "the current highlight color does not match the new color" assert ( highlight_0_color_after_MH_color_change == data[0][1] if content_highlight_ids[0] == highlight_id_0 else data[1][1] ), "highlight color changed for different highlight"
def go_to_highlight(self) -> Page: """Click the 'Go to highlight' link. :return: the book page containing the highlight in a new tab :rtype: :py:class:`~pages.content.Content` """ link_url = self.go_to_highlight_link.get_attribute("href").split("/") book = link_url[2] page = link_url[4].split("?")[0] Utilities.switch_to(self.driver, element=self.go_to_highlight_link) from pages.content import Content return Content( driver=self.driver, base_url=Utilities.parent_page(self).base_url, book_slug=book, page_slug=page )
def select_role(self, email: str): """Select the user's role and enter their email address. :param str email: the user's email address """ if self._use_new_accounts_flow: as_a_student_button = self.find_element( *self._as_a_student_button_locator) Utilities.click_option(self.driver, element=as_a_student_button) return # old flow role_menu = Select(self.find_element(*self._user_select_role_locator)) role_menu.select_by_visible_text("Student") email_field = self.find_element(*self._email_signup_input_locator) email_field.send_keys(email) next_button = self.find_element(*self._next_button_locator) Utilities.click_option(self.driver, element=next_button)
def test_change_highlight_color_from_MH_page_context_menu_using_keyboard( selenium, base_url, book_slug, page_slug): """Change highlight color using keyboard navigation in MH page.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() while book.notification_present: book.notification.got_it() book.navbar.click_login() name, email = Signup(selenium).register() book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() # AND: Highlight some text in the page paragraph = random.sample(book.content.paragraphs, 1) note = Utilities.random_string() book.content.highlight(target=paragraph[0], offset=Highlight.RANDOM, color=Color.GREEN, note=note) # AND: Open MH page my_highlights = book.toolbar.my_highlights() highlights = my_highlights.highlights.edit_highlight highlight_id = highlights[0].mh_highlight_id # WHEN: Tab to the context menu and hit Return (ActionChains(selenium).send_keys(Keys.TAB * 7).send_keys( Keys.RETURN).perform()) # AND: Tab 4 times to select Purple color and hit Spacebar (ActionChains(selenium).send_keys(Keys.TAB * 4).send_keys( Keys.RETURN).send_keys(Keys.SPACE).perform()) # THEN: The highlight color in MH page is changed to purple assert highlights[0].highlight_color == "purple" # AND: The focus stays on purple color assert selenium.switch_to.active_element == highlights[0].purple # WHEN: Hit Esc twice to close the MH modal (ActionChains(selenium).send_keys(Keys.ESCAPE * 2).perform()) highlight_classes = book.content.get_highlight( by_id=highlight_id)[0].get_attribute("class") highlight_color_in_content_page_after_MH_color_change = Color.from_html_class( highlight_classes) # THEN: The highlight color in the content page is changed to purple assert (highlight_color_in_content_page_after_MH_color_change == Color. PURPLE), "the current highlight color does not match the new color"
def book_status_on_amazon(self): """Open the Book Order modal.""" try: print_locator = (self._print_copy_mobile_locator if self.is_mobile else self._print_copy_locator) individual_locator = (self._individual_copy_locator if self.is_mobile else self._order_a_personal_copy_locator) Utilities.click_option(self.driver, locator=print_locator) individual = self.find_elements(*individual_locator) if individual: Utilities.switch_to(self.driver, element=individual[0]) sleep(1) amazon_link = self.current_url self.driver.close() self.driver.switch_to.window(self.driver.window_handles[0]) return amazon_link except NoSuchElementException: return None
def toggle_color(self, color: Color) -> MyHighlights.Highlights.EditHighlight: """Toggle a highlight color. :param color: the color to toggle on or off :type color: :py:class:`~utils.utility.Color` :return: the edit highlight box :rtype: :py:class:`~MyHighlights.Highlights.EditHighlight` """ colors = { Color.PINK: self.pink, Color.GREEN: self.green, Color.BLUE: self.blue, Color.PURPLE: self.purple, Color.YELLOW: self.yellow, } Utilities.click_option(self.driver, element=colors[color]) return self