def test_TOC_closed_if_search_sidebar_is_displayed(selenium, base_url, book_slug, page_slug): # GIVEN: Book page is loaded content = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() toolbar = content.toolbar mobile = content.mobile_search_toolbar toc_sidebar = content.sidebar search_sidebar = content.search_sidebar # WHEN: Search is triggered for a string search_term = get_search_term(book_slug) if content.is_desktop: toolbar.search_for(search_term) if content.is_mobile: mobile.search_for(search_term) # THEN: TOC is not displayed assert not toc_sidebar.is_displayed # AND: Search sidebar is displayed assert search_sidebar.is_displayed
def test_search_results(selenium, base_url, page_slug): """Search sidebar shows total number of matches throughout the book""" book_list = Library() book_slugs = book_list.book_slugs_list # Repeat the test for all books in the library for book_slug in list(book_slugs): # GIVEN: Book page is loaded book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() # Skip any notification/nudge popups while book.notification_present: book.notification.got_it() # WHEN: Search is performed search_sidebar = book.search_sidebar search_term = get_search_term(book_slug) chapter_search_results_expected_value = expected_chapter_search_results_total( book_slug) rkt_results_expected_value = expected_rkt_search_results_total( book_slug) # AND: Search sidebar is open book.toolbar.search_for(search_term) try: assert search_sidebar.search_results_present except TimeoutException: # wait and check if search sidebar appears sleep(0.5) assert search_sidebar.search_results_present # THEN: Search sidebar shows total number of matches throughout the book assert search_sidebar.rkt_search_result_total == rkt_results_expected_value try: assert (search_sidebar.chapter_search_result_total == chapter_search_results_expected_value) except AssertionError: # Total search results vary slightly between environment/search sessions which is being worked on by the developers. # Till then asserting with a threshold value print( f"Search results mismatch for '{book_slug}', expected = '{chapter_search_results_expected_value}', actual = '{search_sidebar.chapter_search_result_total}'" ) tc = unittest.TestCase() tc.assertAlmostEqual( search_sidebar.chapter_search_result_total, chapter_search_results_expected_value, delta=3, )
def test_x_in_search_sidebar(selenium, base_url, book_slug, page_slug): """X in search sidebar closes sidebar, text in search input still visible""" # GIVEN: Book page is loaded book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() # Skip any notification/nudge popups while book.notification_present: book.notification.got_it() toolbar = book.toolbar mobile = book.mobile_search_toolbar search_sidebar = book.search_sidebar search_term = get_search_term(book_slug) if book.is_desktop: # AND: Search results are displayed in search sidebar book.toolbar.search_for(search_term) assert search_sidebar.search_results_present search_result_scroll_position = book.scroll_position # WHEN: Close search sidebar book.search_sidebar.close_search_sidebar() # THEN: Search sidebar is closed assert search_sidebar.search_results_not_displayed # AND: Search string in the search textbox is still visible assert toolbar.search_term_displayed_in_search_textbox == search_term # AND: User stays in the same location in the book content as before closing the sidebar scroll_position_after_closing_search_sidebar = book.scroll_position assert scroll_position_after_closing_search_sidebar == search_result_scroll_position if book.is_mobile: # AND: Search results are displayed in search sidebar mobile.search_for(search_term) assert search_sidebar.search_results_present # WHEN: Close search sidebar mobile.click_close_search_results_link() # THEN: Search sidebar is closed assert search_sidebar.search_results_not_displayed # AND search string in the search input box is still visible book.toolbar.click_search_icon() assert mobile.search_term_displayed_in_search_textbox == search_term
def test_x_in_search_textbox(selenium, base_url, book_slug, page_slug): """X in search textbox clears search string but search results are not affected""" # GIVEN: Book page is loaded book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() # Skip any notification/nudge popups while book.notification_present: book.notification.got_it() toolbar = book.toolbar mobile = book.mobile_search_toolbar search_sidebar = book.search_sidebar search_term = get_search_term(book_slug) if book.is_desktop: # AND: Search sidebar is open book.toolbar.search_for(search_term) assert search_sidebar.search_results_present # WHEN: Click X in the search textbox toolbar.click_search_textbox_x() # THEN: Search string is cleared from the search textbox assert toolbar.search_term_displayed_in_search_textbox == "" # AND: Search sidebar is still open assert search_sidebar.search_results_present if book.is_mobile: # AND: Search sidebar is open mobile.search_for(search_term) assert search_sidebar.search_results_present # WHEN: Click X in the search textbox mobile.click_search_textbox_x() # THEN: Search string is cleared from the search textbox assert mobile.search_term_displayed_in_search_textbox == "" # AND: Search sidebar is still open assert search_sidebar.search_results_present
def test_opening_TOC_closes_search_sidebar(selenium, base_url, book_slug, page_slug): """Opening TOC closes search sidebar and content stays in the same location""" # GIVEN: Book page is loaded book = Content(selenium, base_url, book_slug=book_slug, page_slug=page_slug).open() # Skip any notification/nudge popups while book.notification_present: book.notification.got_it() toolbar = book.toolbar mobile = book.mobile_search_toolbar toc_sidebar = book.sidebar search_sidebar = book.search_sidebar search_term = get_search_term(book_slug) if book.is_desktop: # WHEN: Search sidebar is displayed with search results toolbar.search_for(search_term) assert search_sidebar.search_results_present # Loop through the words in search term and assert if atleast one of them is highlighted in the book split_search_term = re.findall(r"\w+", search_term) for x in split_search_term: focussed_search_term = book.content.find_elements( By.XPATH, XPATH_SEARCH.format(term=x)) try: assert ( focussed_search_term ), f"the highlighted search term ('{x}') was not found on the page" assert book.element_in_viewport(focussed_search_term[0]) except AssertionError: continue except IndexError: # Wait till the focussed search term is scrolled to the viewport sleep(1) assert book.element_in_viewport(focussed_search_term[0]) break scroll_position_before_closing_search_sidebar = book.scroll_position # AND: TOC is opened toolbar.click_toc_toggle_button() # THEN: Search sidebar disappears assert search_sidebar.search_results_not_displayed # AND: TOC is displayed assert toc_sidebar.is_displayed # AND search string stays in the search box assert toolbar.search_term_displayed_in_search_textbox == search_term # AND Content page stays in the same location scroll_position_after_closing_search_sidebar = book.scroll_position within = scroll_position_before_closing_search_sidebar * 0.01 assert isclose( scroll_position_before_closing_search_sidebar, scroll_position_after_closing_search_sidebar, rel_tol=within, ), (r"vertical position after closing search sidebar not within 1% of position " "before closing search sidebar ({low} <= {target} <= {high})". format( low=scroll_position_before_closing_search_sidebar - within, high=scroll_position_before_closing_search_sidebar + within, target=scroll_position_after_closing_search_sidebar, )) # WHEN TOC is closed toc_sidebar.header.click_toc_toggle_button() scroll_position_after_closing_toc = book.scroll_position # THEN search sidebar does not re-appear assert search_sidebar.search_results_not_displayed # AND Content page still stays in the same location assert isclose( scroll_position_after_closing_toc, scroll_position_before_closing_search_sidebar, rel_tol=within, ), (r"vertical position after closing TOC not within 1% of position " "before closing TOC ({low} <= {target} <= {high})".format( low=scroll_position_after_closing_toc - within, high=scroll_position_after_closing_toc + within, target=scroll_position_before_closing_search_sidebar, )) # AND search string still stays in the search box assert toolbar.search_term_displayed_in_search_textbox == search_term if book.is_mobile: # WHEN: Search sidebar is displayed with search results mobile.search_for(search_term) assert search_sidebar.search_results_present # For mobile, content is not visible when search results are displayed. # So click on first search result to store the content scroll position. search_results = book.search_sidebar.search_results(search_term) Utilities.click_option(selenium, element=search_results[0]) # Loop through the words in search term and assert if atleast one of them is highlighted in the book split_search_term = re.findall(r"\w+", search_term) for x in split_search_term: focussed_search_term = book.content.find_elements( By.XPATH, XPATH_SEARCH.format(term=x)) try: assert ( focussed_search_term ), f"the highlighted search term ('{x}') was not found on the page" assert book.element_in_viewport(focussed_search_term[0]) except AssertionError: continue except IndexError: # Wait till the focussed search term is scrolled to the viewport sleep(1) assert book.element_in_viewport(focussed_search_term[0]) break search_result_scroll_position = book.scroll_position mobile.click_back_to_search_results_button() # AND: TOC is opened toolbar.click_toc_toggle_button() # THEN: Search sidebar disappears assert search_sidebar.search_results_not_displayed # AND: TOC is displayed assert toc_sidebar.is_displayed # WHEN: TOC is closed toc_sidebar.header.click_toc_toggle_button() # THEN search sidebar does not re-appear assert search_sidebar.search_results_not_displayed # AND Content page still stays in the same location scroll_position_after_closing_search = book.scroll_position within = search_result_scroll_position * 0.01 assert isclose( search_result_scroll_position, scroll_position_after_closing_search, rel_tol=within ), (r"vertical position after closing search sidebar not within 1% of position " "before closing search sidebar ({low} <= {target} <= {high})". format( low=search_result_scroll_position - within, high=search_result_scroll_position + within, target=scroll_position_after_closing_search, )) # AND: search string still stays in the search box toolbar.click_search_icon() assert mobile.search_term_displayed_in_search_textbox == search_term
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"