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 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 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 test_color_auto_selected_if_a_note_is_added( selenium, base_url, book_slug, page_slug): """The first highlight color is auto-selected if a note is typed.""" # GIVEN: the Astronomy book section 1.0 introduction is displayed # AND: a user is logged in # AND: all content is visible # AND: some content is selected 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() Signup(selenium).register() book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() book.content.show_solutions() paragraph = random.choice(book.content.paragraphs) book.content.highlight(target=paragraph, offset=Highlight.RANDOM, color=None) expected_color = Color.YELLOW # WHEN: they type a note in the create note box book.content.highlight_box.note = Utilities.random_string() highlight_ids = book.content.highlight_ids # THEN: the first hightlight color is automatically selected (yellow) # AND: the selected color in the color picker is checked assert(highlight_ids), "no highlights found" highlight_classes = (book.content .get_highlight(by_id=highlight_ids[0])[0] .get_attribute("class")) current_color = Color.from_html_class(highlight_classes) assert(current_color == expected_color), \ "the current highlight color does not match the default color" assert(book.content.highlight_box.is_checked(expected_color)), \ "highlight color yellow is not currently selected"
def test_note_indicator_added_when_highlight_without_a_note_has_a_note_added( selenium, base_url, book_slug, page_slug): """Adding a note to a highlight also adds the indicator to the highlight. """ # GIVEN: a book page is displayed # AND: a user is logged in # AND: all content is visible # AND: some content is highlighted without a note 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() width, height = book.get_window_size() paragraph = random.choice(book.content.paragraphs) book.content.highlight(paragraph, Highlight.ENTIRE, Color.YELLOW) highlight_id = book.content.highlight_ids[0] highlight = book.content.get_highlight(by_id=highlight_id)[0] # WHEN: they click the highlight # AND: add a note # AND: click the 'Save' button Utilities.click_option(selenium, element=highlight, scroll_to=-130) book.content.highlight_box.note = Utilities.random_string() book.content.highlight_box.save() # THEN: the note indicator is present on the highlight assert(selenium.execute_script(HAS_INDICATOR, highlight)), \ "indicator not found after adding a note"
def test_add_note_from_MH_page(selenium, base_url, book_slug, page_slug): """Adding note 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) ) my_highlights = book.toolbar.my_highlights() highlights = my_highlights.highlights.edit_highlight note_added = Utilities.random_string() for highlight in highlights: # WHEN: From MH page, add a note for the highlight that does not have a note if not highlight.note_present: highlight_id = highlight.mh_highlight_id highlight.add_note() (ActionChains(selenium).send_keys(note_added).perform()) highlight.save() my_highlights.close() # THEN: The corresponding highlight in the content page is updated with the note added in MH page Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_id)[0], scroll_to=-130, ) assert ( book.content.highlight_box.note == note_added ), "the note text does not match the note added or note added to incorrect highlight" highlight_id_1 = ( content_highlight_ids[0] if content_highlight_ids[0] != highlight_id else content_highlight_ids[1] ) Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_id_1)[0], scroll_to=-130, ) # AND: The highlight with note that was not updated in MH page is not affected assert ( book.content.highlight_box.note == data[0][2] ), "the note is added to incorrect highlight" break else: continue
def test_clicking_on_the_note_indicator_opens_the_note_card( selenium, base_url, book_slug, page_slug): """Open the note card for various highlights with notes.""" # GIVEN: a book page is displayed # AND: a user is logged in # AND: all content is visible # AND: several types of content are highlighted with notes 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() # making a highlight requires a non-mobile window width temporarily width, height = book.get_window_size() if width < DESKTOP[0]: selenium.set_window_size(width=DESKTOP[0], height=height) highlight_options = [ (random.choice(book.content.figures_and_captions), Utilities.random_string()), (random.choice(book.content.lists), Utilities.random_string()), (random.choice(book.content.math), Utilities.random_string()), (random.choice(book.content.paragraphs), Utilities.random_string()), (random.choice(book.content.tables), Utilities.random_string()) ] highlight_list = {} for content, note in highlight_options: highlight_ids = book.content.highlight_ids book.content.highlight(target=content, offset=Highlight.ENTIRE, color=Highlight.random_color(), note=note) new_id = list(set(book.content.highlight_ids) - set(highlight_ids))[0] highlight_list[new_id] = note if width != DESKTOP[0]: # reset the window width for a mobile test selenium.set_window_size(width=width, height=height) for _id in book.content.highlight_ids: # WHEN: they select each highlight Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=_id)[0], scroll_to=-130) # THEN: the highlight card and note are displayed try: book.content.highlight_box except NoSuchElementException: pytest.fail("the highlight note card is not open") assert(book.content.highlight_box.note == highlight_list[_id]), \ "Displayed note does not match"
def test_modal_for_unsaved_notes_appears_on_clicking_search_result_different_page( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & selecting search result in different page.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() toolbar = book.toolbar search_sidebar = book.search_sidebar 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: Search results are displayed in sidebar search_term = get_search_term(book_slug) toolbar.search_for(search_term) book.wait_for_page_to_load() search_results = search_sidebar.search_results(search_term) # AND: Highlight a paragraph, add a note & do not save paragraph = random.sample(book.content.paragraphs, 1) book.content.highlight(target=paragraph[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 search result in different page Utilities.click_option(selenium, element=search_results[2]) # 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 book.discard_modal.click_cancel_changes() # THEN: The modal is closed and the unsaved note is retained in 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 search result again Utilities.click_option(selenium, element=search_results[2]) # AND: Click Discard changes in the modal book.click_and_wait_for_load(book.discard_modal.discard_button) # THEN: The selected search result is highlighted in the new page phrase_searched = book.content.find_elements(By.XPATH, XPATH_SEARCH.format(term=search_term)) assert phrase_searched, f"the highlight phrase ('{search_term}') was not found on the page" assert "focus" in phrase_searched[0].get_attribute( "class" ), "search phrase does not have the search focus highlight" # AND: No highlight box is open in the new page with pytest.raises(NoSuchElementException) as e: book.content.highlight_box assert "No open highlight boxes found" in str(e.value), "highlight box is open in the new page" # AND: No existing highlights present in the new page try: assert not book.content.highlights except NoSuchElementException: pytest.fail("existing highlight present in the page") # WHEN: Navigate back to the initial page book.click_and_wait_for_load(search_results[0]) # THEN: The unsaved note in the initial page is not saved id_1 = book.content.highlight_ids[0] highlight = book.content.get_highlight(by_id=id_1)[0] assert not selenium.execute_script(HAS_INDICATOR, highlight), "note is saved for the highlight"
def test_delete_highlight_from_MH_page(selenium, base_url, book_slug, page_slug): """Deleting highlight from MH page, removes 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(length=50) 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) my_highlights = book.toolbar.my_highlights() highlights = my_highlights.highlights.edit_highlight # WHEN: Click delete option from the highlight's context menu highlights[0].click_delete() # THEN: Delete confirmation message is displayed assert ( highlights[0].confirm_delete_message == "Are you sure you want to delete this note and highlight?" if highlights[0].note_present else "Are you sure you want to delete this highlight?" ), ( "delete confirmation message is incorrect" f"message displayed: {highlights[0].confirm_delete_message}" ) # WHEN: Hit Cancel in the delete confirmation dialog highlights[0].cancel() # THEN: The highlight is not removed from MH page assert ( len(my_highlights.all_highlights) == 1 ), "Highlight is removed from MH page even on hitting Cancel in delete confirmation dialog" # WHEN: Click delete option from the highlight's context menu # AND: Hit save in the delete confirmation dialog highlights[0].delete() # THEN: The highlight is removed from the MH page assert ( len(my_highlights.all_highlights) == 0 ), "Highlight is not removed from MH page even on hitting Save in delete confirmation dialog" my_highlights.close() # AND: The highlight deleted in MH page is removed from the content page assert book.content.highlight_count == 0, ( "Highlight deleted in MH page is not removed from content page: " f"found {book.content.highlight_count}, expected {0}" ) with pytest.raises(NoSuchElementException) as ex: book.content.highlight_box assert "No open highlight boxes found" in str(ex.value)
def test_display_highlights_for_returning_users( selenium, base_url, book_slug, page_slug): """Existing highlights are displayed for returning users.""" # GIVEN: a book section is displayed # AND: a user is logged in # AND: all content is visible # AND: some content is highlighted # AND: some content is highlighted with a note 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, password = Signup(selenium).register(True) book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() book.content.show_solutions() # making a highlight requires a non-mobile window width temporarily width, height = book.get_window_size() if width <= DESKTOP[0]: selenium.set_window_size(width=DESKTOP[0], height=height) paragraphs = random.sample(book.content.paragraphs, 2) first_highlight_color = Color.YELLOW book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=first_highlight_color) highlight_id_one = book.content.highlight_ids[0] second_highlight_color = Color.BLUE book.content.highlight(target=paragraphs[1], offset=Highlight.ENTIRE, color=second_highlight_color, note=Utilities.random_string()) highlight_ids = book.content.highlight_ids highlight_id_two = highlight_ids[1] \ if highlight_id_one == highlight_ids[0] \ else highlight_ids[0] if width != DESKTOP[0]: # reset the window width for a mobile test selenium.set_window_size(width=width, height=height) # WHEN: they log out book.navbar.click_user_name() book.navbar.click_logout() # THEN: the highlights and notes are no longer displayed assert(not book.content.highlight_count), \ "highlights found without a logged in user" # WHEN: they log in book.navbar.click_login() Login(selenium).login(email.address, password) book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() book.content.show_solutions() highlight_ids = book.content.highlight_ids # THEN: the highlights and notes are displayed assert(highlight_ids), "no highlights found after log in" assert(highlight_id_one in highlight_ids), "highlight not found" assert(highlight_id_two in highlight_ids), "highlight with note not found"
def test_modal_for_unsaved_notes_appears_on_page_navigation_using_toc( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & clicking TOC link.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() toc = book.sidebar.toc 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 highlight_id = book.content.highlight_ids[0] # WHEN: Click on a TOC link book.offscreen_click(toc.sections[3].root) # 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=highlight_id)[0] assert "focus" in highlight.get_attribute("class"), "highlight is not in focus" assert book.content.highlight_box.note == note # WHEN: Click the TOC link again book.offscreen_click(toc.sections[3].root) # AND: click Discard changes in the modal book.click_and_wait_for_load(book.discard_modal.discard_button) # THEN: New page is loaded assert toc.sections[3].is_active # AND: No highlight box is open in the new page with pytest.raises(NoSuchElementException) as e: book.content.highlight_box assert "No open highlight boxes found" in str(e.value), "highlight box is open in the new page" # AND: No existing highlights present in the new page try: assert not book.content.highlights except NoSuchElementException: pytest.fail("existing highlight present in the page") # WHEN: Navigate back to the initial page book.click_and_wait_for_load(toc.sections[1].root) # THEN: The unsaved note in the initial page is not saved highlight = book.content.get_highlight(by_id=highlight_id)[0] assert not selenium.execute_script(HAS_INDICATOR, highlight), "note is saved for the highlight"
def test_modal_for_unsaved_notes_appears_on_selecting_new_text( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & selecting new text.""" # 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() # WHEN: Highlight a paragraph, add a note & do not save paragraph = random.sample(book.content.paragraphs, 2) book.content.highlight(target=paragraph[0], offset=Highlight.ENTIRE, close_box=False) note = Utilities.random_string() book.content.highlight_box.note = note id_1 = book.content.highlight_ids[0] # AND: Select some text in the page paragraph_1 = paragraph[1] if paragraph[1] != paragraph[0] else paragraph[0] # Highlight.Entire is flaky probably because of bug 1270, so using Random book.content.select(target=paragraph_1, offset=Highlight.RANDOM) # 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 book.discard_modal.click_cancel_changes() # THEN: The modal is closed and the unsaved note is retained in 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: Select some text in the page again book.content.select(target=paragraph_1, offset=Highlight.RANDOM) # AND: Click Discard changes in the modal book.discard_modal.click_discard_changes() # THEN: The new text is selected selected_text = selenium.execute_script("return window.getSelection().toString()") assert selected_text in paragraph_1.get_attribute("textContent") # AND: The highlight box is opened for the selected text assert book.content.highlight_box.is_open, "Highlight box not open" assert book.content.highlight_box.note == "" # AND: The selected text is not a saved highlight assert len(book.content.highlight_ids) == 1, "the selected text is already a saved highlight" # AND: Unsaved note of the first highlight is abandoned highlight = book.content.get_highlight(by_id=id_1)[0] assert not selenium.execute_script(HAS_INDICATOR, highlight), "note is saved for the highlight"
def test_my_highlights_summary_shows_highlights_and_notes_on_current_page( selenium, base_url, book_slug, page_slug): """My Highlights and Notes summary shows page highlights and notes.""" # SETUP: ONE, TWO, THREE, FOUR = range(4) color = Highlight.random_color highlight_ids = [""] * 4 highlight_colors = [color(), color(), color(), color()] highlight_notes = [ "", Utilities.random_string(), "", Utilities.random_string() ] highlight_partial_text = [""] * 4 chapter_one = ("1", "Essential Ideas") sections = [("", "Introduction"), ("1.1", "Chemistry in Context")] # GIVEN: the Chemistry 2e book section 1.0 is displayed # AND: a user is logged in # AND: all content is visible # AND: some content is highlighted without a note # AND: some content is highlighted with a note # AND: some content is highlighted in section 1.1 without a note # AND: some content is highlighted in section 1.1 with a note 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, password = Signup(selenium).register(True) book.wait_for_page_to_load() while book.notification_present: book.notification.got_it() book.content.show_solutions() # making a highlight requires a non-mobile window width temporarily width, height = book.get_window_size() if width <= DESKTOP[0]: selenium.set_window_size(width=DESKTOP[0], height=height) paragraphs = random.sample(book.content.paragraphs, 2) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=highlight_colors[ONE]) highlight_ids[ONE] = book.content.highlight_ids[0] highlight_partial_text[ONE] = book.content.get_highlight( by_id=highlight_ids[ONE])[0].text book.content.highlight( target=paragraphs[1], offset=Highlight.ENTIRE, color=highlight_colors[TWO], note=highlight_notes[TWO], ) page_highlight_ids = book.content.highlight_ids highlight_ids[TWO] = (page_highlight_ids[1] if highlight_ids[ONE] == page_highlight_ids[0] else page_highlight_ids[0]) highlight_partial_text[TWO] = book.content.get_highlight( by_id=highlight_ids[TWO])[0].text book.click_next_link() paragraphs = random.sample(book.content.paragraphs, 2) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=highlight_colors[THREE]) highlight_ids[THREE] = book.content.highlight_ids[0] highlight_partial_text[THREE] = book.content.get_highlight( by_id=highlight_ids[THREE])[0].text book.content.highlight( target=paragraphs[1], offset=Highlight.ENTIRE, color=highlight_colors[FOUR], note=highlight_notes[FOUR], ) page_highlight_ids = book.content.highlight_ids highlight_ids[FOUR] = (page_highlight_ids[1] if highlight_ids[THREE] == page_highlight_ids[0] else page_highlight_ids[0]) highlight_partial_text[FOUR] = book.content.get_highlight( by_id=highlight_ids[FOUR])[0].text if width != DESKTOP[0]: # reset the window width for a mobile test selenium.set_window_size(width=width, height=height) # WHEN: they click on the My highlights button my_highlights = book.toolbar.my_highlights() # THEN: the My Highlights and Notes modal is displayed # AND: sections without highlights are not included in the placeholders # AND: all highlights for the chapter are displayed # AND: each highlight color matches the corresponding page highlight color # AND: each note matches the corresponding page highlight note assert book.my_highlights_open, "My Highlights modal not open" assert my_highlights.root.is_displayed( ), "My Highlights modal not displayed" assert (len(my_highlights.highlights.chapters) == 1 ), "chapter heading not displayed in the highlights summary" highlight_chapter = ( my_highlights.highlights.chapters[0].number, my_highlights.highlights.chapters[0].title, ) assert highlight_chapter == chapter_one, "chapter number and title do not match in the summary" assert len(my_highlights.highlights.sections ) == 2, "did not find two section headings" highlight_sections = [(section.number, section.title) for section in my_highlights.highlights.sections] assert set(highlight_sections) == set( sections), "mismatched section numbers and/or names" current_summary_highlights = len(my_highlights.all_highlights) assert current_summary_highlights == len(highlight_ids), ( "unexpected number of highlights found on the summary page (" f"found {current_summary_highlights}, expected {len(highlight_ids)})") # ordering could be in sequence or reversed so check against both section # highlights for index, highlight in enumerate(my_highlights.all_highlights): option_1, option_2 = (ONE, TWO) if index <= TWO else (THREE, FOUR) assert (highlight.color == highlight_colors[option_1] or highlight.color == highlight_colors[option_2] ), f"highlight color for highlight {index + 1} does not match" content = highlight.content assert ( highlight_partial_text[option_1] in content or highlight_partial_text[option_2] in content ), f"partial note text not found in summary highlight {index + 1}" # currently the summary trims extra spaces and removes carriage returns note_1 = highlight_notes[option_1].replace("\n", " ").replace(" ", " ") note_2 = highlight_notes[option_2].replace("\n", " ").replace(" ", " ") assert (highlight.note == note_1 or highlight.note == note_2 ), f"highlight note {index + 1} does not match content note"
def test_note_indicator_not_present_for_highlights_without_notes( selenium, base_url, book_slug, page_slug): """The note indicator is not present on highlights without notes. .. note:: The note indicator has been temporarily been replaced by off-color underlining (bottom border). """ # GIVEN: a book page is displayed # AND: a user is logged in # AND: all content is visible # AND: some content is highlighted without a note # AND: some content is highlighted with a note 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() # making a highlight requires a non-mobile window width temporarily width, height = book.get_window_size() if width < DESKTOP[0]: selenium.set_window_size(width=DESKTOP[0], height=height) paragraphs = random.sample(book.content.paragraphs, 2) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=Highlight.random_color()) no_note = list(set(book.content.highlight_ids))[0] book.content.highlight(target=paragraphs[1], offset=Highlight.ENTIRE, color=Highlight.random_color(), note=Utilities.random_string()) _ids = book.content.highlight_ids with_note = _ids[0] if _ids[0] != no_note else _ids[1] if width != DESKTOP[0]: # reset the window width for a mobile test selenium.set_window_size(width=width, height=height) # WHEN: # THEN: the note indicator is not present on the highlight # AND: the note indicator is present on the highlight with a note no_note = book.content.get_highlight(by_id=no_note)[0] assert(not selenium.execute_script(HAS_INDICATOR, no_note)), \ "indicator found on a highlight without a note" with_note = book.content.get_highlight(by_id=with_note)[0] assert(selenium.execute_script(HAS_INDICATOR, with_note)), \ "indicator not found on a highlight with a note"
def test_toggle_MH_page_context_menu_using_keyboard(selenium, base_url, book_slug, page_slug): """Open/close context menu in MH page using keyboard.""" # 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 sets of text in the page paragraph = random.sample(book.content.paragraphs, 2) note = Utilities.random_string() 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) # AND: Open MH page my_highlights = book.toolbar.my_highlights() highlights = my_highlights.highlights.edit_highlight # WHEN: Tab to the first context menu (present after the last breadcrumb) # AND: Hit Return (ActionChains(selenium).send_keys(Keys.TAB * 8).send_keys( Keys.RETURN).perform()) # THEN: Highlight edit box of the first highlight is open assert highlights[0].highlight_edit_box_open # AND: The focus is on the context menu of the first highlight assert selenium.switch_to.active_element == highlights[0].context_menu # WHEN: Hit Return (ActionChains(selenium).send_keys(Keys.RETURN).perform()) # THEN: The highlight edit box of the first highlight is closed assert not highlights[0].highlight_edit_box_open # AND: The focus is on the context menu of the same highlight assert selenium.switch_to.active_element == highlights[0].context_menu # WHEN: Hit tab once and Enter (ActionChains(selenium).send_keys(Keys.TAB * 1).send_keys( Keys.ENTER).perform()) # THEN: Highlight edit box of the second highlight is open assert highlights[1].highlight_edit_box_open # AND: The focus is on the context menu of the second highlight assert selenium.switch_to.active_element == highlights[1].context_menu # WHEN: Hit Escape (ActionChains(selenium).send_keys(Keys.ESCAPE).perform()) # THEN: The highlight edit box of the second highlight is closed assert not highlights[1].highlight_edit_box_open # AND: The focus is on the context menu of the same highlight assert selenium.switch_to.active_element == highlights[1].context_menu # WHEN: Hit Esc (ActionChains(selenium).send_keys(Keys.ESCAPE).perform()) # THEN: MH page is closed assert not book.my_highlights_open, "My Highlights and Notes modal is still open"
def test_delete_note_using_keyboard_content_page(selenium, base_url, book_slug, page_slug): """Delete note using keyboard navigation.""" # 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 with a note paragraphs = random.sample(book.content.paragraphs, 1) note_text = Utilities.random_string(length=15) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=Color.GREEN, note=note_text) highlight_with_note = book.content.highlight_ids[0] book.reload() # WHEN: Tab to the highlight and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Select Delete option from the context menu and hit Cancel (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB * 2).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB * 2).send_keys( Keys.ENTER).perform()) # THEN: The highlight/note is not deleted Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_with_note)[0], scroll_to=-130, ) assert (book.content.highlight_box.note == note_text ), "the highlight and note is deleted even on clicking Cancel" book.reload() # WHEN: Tab to the highlight and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Select Edit option from the context menu and hit Delete (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB * 2).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) # THEN: The highlight and note is deleted assert book.content.highlight_count == 0, ( "Highlight is not removed from content page: " f"found {book.content.highlight_count}, expected {0}") with pytest.raises(NoSuchElementException) as ex: book.content.highlight_box assert "No open highlight boxes found" in str(ex.value)
def test_change_highlight_color_using_keyboard_content_page( selenium, base_url, book_slug, page_slug): """Highlight color can be changed using keyboard navigation.""" # 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 without a note paragraphs = random.sample(book.content.paragraphs, 1) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=Color.GREEN) highlight_no_note = book.content.highlight_ids[0] # AND: Navigate to next page and highlight some text with a note book.click_next_link() paragraphs = random.sample(book.content.paragraphs, 1) book.content.highlight( target=paragraphs[0], offset=Highlight.ENTIRE, color=Color.YELLOW, note=Utilities.random_string(), ) highlight_with_note = book.content.highlight_ids[0] book.reload() # WHEN: Tab to the highlight and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Change the highlight color in the active notecard using shift tab and spacebar keys (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.SHIFT + Keys.TAB + Keys.SHIFT).send_keys( Keys.SPACE).perform()) # AND: Navigate out of the highlight (ActionChains(selenium).send_keys("H").perform()) # THEN: The highlight color is changed highlight_classes_0 = book.content.get_highlight( by_id=highlight_with_note)[0].get_attribute("class") highlight_0_color_after_color_change = Color.from_html_class( highlight_classes_0) assert ( highlight_0_color_after_color_change == Color.PINK ), f"Highlight color in the page {selenium.current_url} is {highlight_0_color_after_color_change}" # WHEN: Navigate to the previous page, tab to the highlight without note and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Change the highlight color and navigate out of the highlight (ActionChains(selenium).send_keys(Keys.SHIFT + Keys.TAB + Keys.SHIFT).perform()) (ActionChains(selenium).send_keys(Keys.SPACE).perform()) (ActionChains(selenium).send_keys("H").send_keys(Keys.TAB).perform()) # THEN: The highlight color is changed highlight_classes_1 = book.content.get_highlight( by_id=highlight_no_note)[0].get_attribute("class") highlight_1_color_after_color_change = Color.from_html_class( highlight_classes_1) assert ( highlight_1_color_after_color_change == Color.PINK ), f"Highlight color in the page {selenium.current_url} is {highlight_1_color_after_color_change}"
def test_edit_note_using_keyboard_content_page(selenium, base_url, book_slug, page_slug): """Edit note using keyboard navigation.""" # 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 with a note paragraphs = random.sample(book.content.paragraphs, 1) note_text = Utilities.random_string(length=15) book.content.highlight(target=paragraphs[0], offset=Highlight.ENTIRE, color=Color.GREEN, note=note_text) highlight_with_note = book.content.highlight_ids[0] note_append = Utilities.random_string(length=15) book.reload() # WHEN: Tab to the highlight and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Select Edit option from the context menu (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) # AND: Enter the note in the textbox and hit cancel ActionChains(selenium).send_keys(note_append).perform() ActionChains(selenium).send_keys(Keys.TAB * 2).send_keys( Keys.ENTER).perform() # THEN: The note in the content page is not updated Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_with_note)[0], scroll_to=-130, ) assert (book.content.highlight_box.note == note_text ), "the note is updated even on clicking Cancel" book.reload() # WHEN: Tab to the highlight and hit H key (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys("H").perform()) # AND: Select Edit option from the context menu (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) # AND: Enter the new note in the textbox and hit save (ActionChains(selenium).send_keys(note_append).send_keys( Keys.TAB).send_keys(Keys.ENTER).perform()) # THEN: The note in the content page is updated Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_with_note)[0], scroll_to=-130, ) assert (book.content.highlight_box.note == note_append + note_text), "the note text does not match the updated text"
def test_edit_note_from_MH_page_using_keyboard_navigation( selenium, base_url, book_slug, page_slug): """Edit note from MH page using keyboard navigation.""" # 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, note=note) # AND: Open MH page my_highlights = book.toolbar.my_highlights() highlight = my_highlights.highlights.edit_highlight highlight_id = highlight[0].mh_highlight_id note_append = Utilities.random_string() # WHEN: Open the context menu (ActionChains(selenium).send_keys(Keys.TAB * 7).send_keys( Keys.RETURN).perform()) # AND: Select Edit note (ActionChains(selenium).send_keys(Keys.TAB * 6).send_keys( Keys.RETURN).perform()) # AND: Update the note in the textbox and hit cancel (ActionChains(selenium).send_keys(note_append).send_keys( Keys.TAB * 2).send_keys(Keys.ENTER).perform()) # AND: Close the MH page (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) # THEN: The corresponding highlight in the content page is not updated with new note info Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_id)[0], scroll_to=-130) assert (book.content.highlight_box.note == note ), "the note is updated even on clicking Cancel in MH page" book.toolbar.my_highlights() # WHEN: Open the context menu (ActionChains(selenium).send_keys(Keys.TAB * 7).send_keys( Keys.RETURN).perform()) # AND: Select Edit note (ActionChains(selenium).send_keys(Keys.TAB * 6).send_keys( Keys.RETURN).perform()) # AND: Update the note in the textbox and hit save (ActionChains(selenium).send_keys(note_append).send_keys( Keys.TAB).send_keys(Keys.ENTER).perform()) # AND: Close the MH page (ActionChains(selenium).send_keys(Keys.TAB).send_keys( Keys.ENTER).perform()) # THEN: The corresponding highlight in the content page is updated with the new note text Utilities.click_option( driver=selenium, element=book.content.get_highlight(by_id=highlight_id)[0], scroll_to=-130) assert (book.content.highlight_box.note == note_append + note), "the note text does not match the note updated in MH page"
def test_modal_for_unsaved_notes_appears_on_clicking_book_title( selenium, base_url, book_slug, page_slug ): """Discard modal appears when unsaved notes are present & book title is clicked.""" # GIVEN: Login book page book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() book_banner = book.bookbanner 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 highlight_id = book.content.highlight_ids[0] # WHEN: Click on book title book_banner.book_title.click() # 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=highlight_id)[0] assert "focus" in highlight.get_attribute("class"), "highlight is not in focus" assert book.content.highlight_box.note == note # WHEN: Click on book title again book_banner.book_title.click() # AND: click Discard changes in the modal book.discard_modal.click_discard_changes() # THEN: The page navigates to osweb book details page osweb = WebBase(selenium) osweb.wait_for_page_to_load() expected_page_url = base_url + "/details/books/" + book_slug assert expected_page_url == osweb.current_url # WHEN: Click the view online link in osweb book detail page osweb.fix_view_online_url(base_url) book.click_and_wait_for_load(osweb.view_online) # THEN: The unsaved note in the initial page is not saved highlight = book.content.get_highlight(by_id=highlight_id)[0] assert not selenium.execute_script(HAS_INDICATOR, highlight), "note is saved for the highlight" # AND: No highlight box is open in the page with pytest.raises(NoSuchElementException) as e: book.content.highlight_box assert "No open highlight boxes found" in str(e.value), "highlight box is open in the page"