Skip to content
Open
95 changes: 60 additions & 35 deletions playwright/e2e/ui/pages/home.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import asyncio
import pytest

from playwright.async_api import expect

import re


class HomeRex:
def __init__(self, page):
Expand All @@ -22,7 +17,7 @@ async def main_menu_and_openstax_logo_is_visible(self):

@pytest.mark.asyncio
async def osweb_homepage_content_sections(self):
return await self.page.locator(f"main > section:nth-child(5)").is_visible()
return await self.page.locator("main > section:nth-child(5)").is_visible()

@pytest.mark.asyncio
async def upper_menu_options(self):
Expand Down Expand Up @@ -92,11 +87,11 @@ async def resources_tabs_are_visible(self):

@pytest.mark.asyncio
async def click_instructor_resources_tab(self):
await self.page.locator("id=Instructor resources-tab").click()
await self.page.locator(r"#Instructor\ resources-tab").click()

@pytest.mark.asyncio
async def click_student_resources_tab(self):
await self.page.locator("id=Student resources-tab").click()
await self.page.locator(r"#Student\ resources-tab").click()

@pytest.mark.asyncio
async def click_subjects_science_link(self):
Expand All @@ -120,7 +115,7 @@ async def subjects_title(self):

@pytest.mark.asyncio
async def highlights_option_is_visible(self):
return await self.page.locator("id=nudge-study-tools").is_visible()
return await self.page.locator("#nudge-study-tools").is_visible()

@pytest.mark.asyncio
async def click_highlights_option(self):
Expand Down Expand Up @@ -194,7 +189,7 @@ async def click_give_today_link(self):

@pytest.mark.asyncio
async def footer_section(self):
return await self.page.locator("id=footer").is_visible()
return await self.page.locator("#footer").is_visible()

@pytest.mark.asyncio
async def footer_section_help_is_visible(self):
Expand Down Expand Up @@ -310,11 +305,11 @@ async def click_login_other(self):

@pytest.mark.asyncio
async def fill_user_field(self, value):
await self.page.locator("id=login_form_email").fill(value)
await self.page.locator("#login_form_email").fill(value)

@pytest.mark.asyncio
async def fill_password_field(self, value):
await self.page.locator("id=login_form_password").fill(value)
await self.page.locator("#login_form_password").fill(value)

@pytest.mark.asyncio
async def click_continue_login(self):
Expand All @@ -340,6 +335,20 @@ async def logout_link_is_visible(self):
async def click_logout_link(self):
await self.page.get_by_role("menuitem", name="Log out").click()

@property
def small_login_box(self):
return self.page.get_by_text(
"Log in to highlight and take notes. It’s 100% free.Log inCancel"
)

@pytest.mark.asyncio
async def click_small_login_box_cancel(self):
await self.page.get_by_role("button", name="Cancel").click()

@pytest.mark.asyncio
async def click_small_login_box_login(self):
await self.page.get_by_test_id("confirm").click()

# Book chapter section

@pytest.mark.asyncio
Expand All @@ -354,27 +363,47 @@ async def click_other_text(self):
async def select_text(self):
await self.page.locator("p:has-text('impact history')").select_text()

@pytest.mark.asyncio
async def select_text_block_in_solution(self):
await self.page.locator(
"p:has-text('formula. Repeat with values')"
).select_text()

@pytest.mark.asyncio
async def click_astronomy_book_chapter93(self):
await self.page.get_by_test_id("content-link-test").get_by_text(
"Impact Craters"
).click()

# Highlight box and highlights

@pytest.mark.asyncio
async def highlight_box_trash_icon_is_visible(self):
return (
await self.page.locator("div")
.get_by_test_id("editcard-trash-icon")
.is_visible()
)
return await self.page.get_by_label("Deselect current highlight").is_visible()

@pytest.mark.asyncio
async def click_highlight_box_trash_icon(self):
await self.page.get_by_label("Deselect current highlight").click()

@pytest.mark.asyncio
async def oneclick_highlight_infobox(self):
await self.page.get_by_label("Edit highlighted note").click()

@property
def highlight_infobox(self):
return self.page.get_by_label("Edit highlighted note")

@pytest.mark.asyncio
async def highlight_box_is_visible(self):
return await self.page.locator("id=note-textarea").is_visible()
return await self.page.locator("#note-textarea").is_visible()

@pytest.mark.asyncio
async def click_highlight_box_note_field(self):
await self.page.locator("id=note-textarea").click()
await self.page.locator("#note-textarea").click()

@pytest.mark.asyncio
async def fill_highlight_box_note_field(self, value):
await self.page.locator("id=note-textarea").fill(value)
await self.page.locator("#note-textarea").fill(value)

@pytest.mark.asyncio
async def highlight_box_colours_are_visible(self):
Expand All @@ -392,25 +421,13 @@ async def click_highlight_box_purple_colour(self):
async def click_highlights_option_green_colour(self):
await self.page.locator("div").get_by_title("green").first.click()

@property
def highlights_option_text_colour_purple(self):
return self.page.locator(
"div.HighlightListElement__HighlightContentWrapper-s4j4lf-1.ibAyfS"
)

@property
def highlights_option_text_colour_green(self):
return self.page.locator(
"div.HighlightListElement__HighlightContentWrapper-s4j4lf-1.kuxHtj"
)

@property
def highlights_option_text_colour_check_purple(self):
return self.highlights_option_text_colour_purple.get_attribute("color")
return self.page.locator('div[color="purple"]').get_attribute("color")

@property
def highlights_option_text_colour_check_green(self):
return self.highlights_option_text_colour_green.get_attribute("color")
return self.page.locator('div[color="green"]').get_attribute("color")

@pytest.mark.asyncio
async def small_highlighted_note_box_is_visible(self):
Expand All @@ -428,6 +445,10 @@ async def click_small_highlight_box_delete_button(self):
async def click_delete_highlight_button(self):
await self.page.locator("div").get_by_test_id("confirm").click()

@pytest.mark.asyncio
async def click_small_highlight_box_edit_button(self):
await self.page.get_by_test_id("card").get_by_text("Edit").click()

@pytest.mark.asyncio
async def yellow_highlighted_text_is_visible(self):
return await self.page.locator("mark > span:nth-child(1)").all()
Expand All @@ -454,7 +475,7 @@ async def click_new_chapter(self):

@pytest.mark.asyncio
async def click_show_hide_solution_link(self):
await self.page.locator("id=fs-id1165134108429").get_by_title(
await self.page.locator("#fs-id1165134108429").get_by_title(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these ids are book page-specific, it's probably not great to rely on them.

Copy link
Contributor Author

@omehes omehes Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I need a book/page/text block specific element within the solution box as per the aim of the test and this is the best I was able to come up... targetting this text block with this id

"Show/Hide Solution"
).click()

Expand Down Expand Up @@ -520,6 +541,10 @@ async def click_search(self):
async def fill_search_field(self, value):
await self.content_search_field_is_visible.fill(value)

@pytest.mark.asyncio
async def click_search_magnifier_icon(self):
await self.page.get_by_role("button", name="Search").click()

@property
def search_result_is_visible(self):
return self.page.get_by_test_id("search-results-sidebar")
Expand Down
113 changes: 100 additions & 13 deletions playwright/e2e/ui/test_highlight_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@pytest.mark.parametrize(
"book_slug, page_slug", [("astronomy-2e", "9-3-impact-craters")]
)
async def test_highlight_box_dismiss_with_esc(
async def test_highlight_box_opens_on_enter(
chrome_page, base_url, book_slug, page_slug, rex_user, rex_password
):

Expand All @@ -24,29 +24,36 @@ async def test_highlight_box_dismiss_with_esc(

await home.click_continue_login()

# THEN: Book page opens, highlight box appears, then disappears on Escape key
# THEN: Book page opens, highlight infobox and edit box appears

await chrome_page.keyboard.press("Escape")

await home.double_click_text()

assert await home.highlight_infobox.is_visible()

await chrome_page.keyboard.press("Enter")

assert await home.highlight_box_is_visible()

assert await home.highlight_box_colours_are_visible()
assert await home.highlight_box_trash_icon_is_visible()

await chrome_page.keyboard.press("Escape")
await home.click_highlight_box_trash_icon()

# Adjusting the test until the expected behaviour is implemented for Escape key (to avoid test fail)
assert await home.highlight_box_is_visible()
# await home.click_highlights_option()
# assert "You have no highlights in this book" not in await home.highlights_option_page_is_empty.inner_text()
await home.click_highlights_option()

assert (
"You have no highlights in this book"
in await home.highlights_option_page_is_empty.inner_text()
)


@pytest.mark.asyncio
@pytest.mark.parametrize(
"book_slug, page_slug", [("astronomy-2e", "9-3-impact-craters")]
)
async def test_highlight_box_dismiss_with_click(
async def test_highlight_box_opens_on_one_click(
chrome_page, base_url, book_slug, page_slug, rex_user, rex_password
):

Expand All @@ -63,17 +70,22 @@ async def test_highlight_box_dismiss_with_click(

await home.click_continue_login()

# THEN: Book page opens, highlight box appears, then disappears on clicking away from the box
# THEN: Book page opens, highlight infobox and edit box appears

await chrome_page.keyboard.press("Escape")

await home.double_click_text()

assert await home.highlight_infobox.is_visible()

await home.oneclick_highlight_infobox()

assert await home.highlight_box_is_visible()

await home.click_other_text()
assert await home.highlight_box_colours_are_visible()
assert await home.highlight_box_trash_icon_is_visible()

assert not await home.highlight_box_is_visible()
await home.click_highlight_box_trash_icon()

await home.click_highlights_option()

Expand All @@ -87,7 +99,7 @@ async def test_highlight_box_dismiss_with_click(
@pytest.mark.parametrize(
"book_slug, page_slug", [("astronomy-2e", "9-3-impact-craters")]
)
async def test_highlight_box_click_highlights_option_after_highlighting_text(
async def test_highlight_is_created_without_annotation_on_enter(
chrome_page, base_url, book_slug, page_slug, rex_user, rex_password
):

Expand All @@ -104,21 +116,96 @@ async def test_highlight_box_click_highlights_option_after_highlighting_text(

await home.click_continue_login()

# THEN: Book page opens, highlight box appears, then disappears on clicking the highlights option page
# THEN: Book page opens, highlight infobox and edit box appears

await chrome_page.keyboard.press("Escape")

await home.double_click_text()

assert await home.highlight_infobox.is_visible()

await chrome_page.keyboard.press("Enter")

assert await home.highlight_box_is_visible()

await chrome_page.keyboard.press("Escape")

assert not await home.highlight_box_is_visible()

await chrome_page.keyboard.press("Enter")

await home.click_highlights_option()

assert (
"You have no highlights in this book"
not in await home.highlights_option_page_is_empty.inner_text()
)

# THEN: Delete the created highlight

await home.click_highlights_option_page_menu()

await home.click_highlights_option_page_menu_delete()
await home.click_highlights_option_page_menu_delete_delete()

assert (
"You have no highlights in this book"
in await home.highlights_option_page_is_empty.inner_text()
)


@pytest.mark.asyncio
@pytest.mark.parametrize(
"book_slug, page_slug", [("astronomy-2e", "9-3-impact-craters")]
)
async def test_highlight_is_created_without_annotation_on_one_click(
chrome_page, base_url, book_slug, page_slug, rex_user, rex_password
):

# GIVEN: Playwright, chromium and the rex_base_url

# WHEN: The Home page is fully loaded
await chrome_page.goto(f"{base_url}/books/{book_slug}/pages/{page_slug}")
home = HomeRex(chrome_page)

await home.click_login()

await home.fill_user_field(rex_user)
await home.fill_password_field(rex_password)

await home.click_continue_login()

# THEN: Book page opens, highlight infobox and edit box appears

await chrome_page.keyboard.press("Escape")

await home.double_click_text()

assert await home.highlight_infobox.is_visible()

await home.oneclick_highlight_infobox()

assert await home.highlight_box_is_visible()

await chrome_page.keyboard.press("Escape")

assert not await home.highlight_box_is_visible()

await home.click_highlights_option()

assert (
"You have no highlights in this book"
not in await home.highlights_option_page_is_empty.inner_text()
)

# THEN: Delete the created highlight

await home.click_highlights_option_page_menu()

await home.click_highlights_option_page_menu_delete()
await home.click_highlights_option_page_menu_delete_delete()

assert (
"You have no highlights in this book"
in await home.highlights_option_page_is_empty.inner_text()
)
Loading
Loading