Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/browserify-sign-4.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
staxly[bot] authored Jun 13, 2024
2 parents 0f48c52 + 09339d2 commit 992a109
Show file tree
Hide file tree
Showing 87 changed files with 1,005 additions and 486 deletions.
2 changes: 1 addition & 1 deletion concourse/book-scan/script.bash
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ cloudfront_environment=$(< cloudfront-environment/version.txt)

cd rex-web

yarn
yarn install --network-timeout 60000

node script/entry.js domVisitor errorsExist --rootUrl="https://$cloudfront_environment" --queryString="validateLinks"
2 changes: 1 addition & 1 deletion concourse/create-test-plan-configs/task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ run:
- |
DEST=$(pwd)/test-plans
cd rex-web/concourse/create-test-plan-configs
yarn install
yarn install --network-timeout 60000
./script.js $DEST
12 changes: 12 additions & 0 deletions concourse/lighthouse/script.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euxo pipefail

base_dir=$(pwd)

cd rex-web

yarn install --network-timeout 60000

node script/entry.js lighthouse --pages="$LIGHTHOUSE_PAGES" \
--mostRecentReportDir="$base_dir/$LIGHTHOUSE_MOST_RECENT_REPORT_DIR" \
--reportDir="$base_dir/$LIGHTHOUSE_REPORT_DIR"
26 changes: 26 additions & 0 deletions concourse/lighthouse/task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
platform: linux

image_resource:
type: docker-image
source:
password: ((dockerhub-password))
username: ((dockerhub-username))
repository: openstax/rex-web
tag: CI-2023-08-10

inputs:
- name: rex-web
- name: most-recent-lighthouse-report
outputs:
- name: lighthouse-report

params:
AWS_ACCESS_KEY_ID: ((prod-aws-access-key-id))
AWS_SECRET_ACCESS_KEY: ((prod-aws-secret-access-key))
LIGHTHOUSE_PAGES: ((lighthouse-pages))
LIGHTHOUSE_MOST_RECENT_REPORT_DIR: most-recent-lighthouse-report
LIGHTHOUSE_REPORT_DIR: lighthouse-report

run:
path: rex-web/concourse/lighthouse/script.bash
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"test:prerender:specs": "REACT_APP_ENV=test SERVER_MODE=built jest --testPathPattern=\"(\\.|/)prerenderspec\\.tsx?\" --config jest-puppeteer.config.json",
"test:prerender:browser": "REACT_APP_ENV=test SERVER_MODE=built jest --testPathPattern=\"(\\.|/)browserspec\\.tsx?\" --config jest-puppeteer.config.json -i",
"test:prerender:screenshots": "REACT_APP_ENV=test SERVER_MODE=built jest --testPathPattern=\"(\\.|/)screenshotspec\\.tsx?\" --config jest-puppeteer.config.json",
"test:lighthouse-manual": "REACT_APP_ENV=test lighthouse --view --config-path=./src/test/audits/index.js",
"test:lighthouse:manual": "REACT_APP_ENV=test lighthouse --view --config-path=./src/test/audits/index.js",
"analyze:bundle": "craco build && source-map-explorer 'build/static/js/*.js' -m",
"analyze:dom": "node ./script/entry.js domVisitor",
"heroku-postbuild": "npm run-script build:clean"
Expand Down
7 changes: 7 additions & 0 deletions playwright/src/fixtures/content.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ class ContentPage {
.addCookies([{ name: 'nudge_study_guides_date', value: current_date, url: this.page.url() }])
}

async canonical() {
// Return canonical link of the current page
let canonicalPageSelector = await this.page.$('[rel="canonical"]')
const canonicalPage = await canonicalPageSelector.evaluate((e) => e.getAttribute('href'))
return canonicalPage
}

async colorLocator(color: string) {
// Return locator of the color
if (color === 'blue') {
Expand Down
2 changes: 1 addition & 1 deletion playwright/src/fixtures/toc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class TOC {
if ((await titleAfterClick) != (await titleBeforeClick)) {
return
} else {
sleep(1)
sleep(2)
}
} else {
console.log('The page number specified exceeds the total pages in the book')
Expand Down
98 changes: 98 additions & 0 deletions playwright/tests/rex-test/rex.behaviorspec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,3 +576,101 @@ test('MH page dropdown filters', async ({ page, isMobile }) => {
const highlightcount = await bookPage.highlightCount()
expect(highlightcount).toBe(2)
})


test('C543224 canonicals for books with no shared content', async ({ page, isMobile, browserName }) => {
test.skip(isMobile as boolean, 'test only desktop resolution')
test.skip(browserName == 'webkit', 'test only chrome')
test.skip(browserName == 'firefox', 'test only chrome')

// GIVEN: Open Rex page
const bookPage = new ContentPage(page)
const path = '/books/chemistry-2e/pages/1-1-chemistry-in-context'
await bookPage.open(path)

// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/chemistry-2e/pages/1-1-chemistry-in-context')

// WHEN: click EOC page
const Toc = new TOC(page)
await Toc.pageClick(9)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/chemistry-2e/pages/1-key-equations')

// WHEN: Click EOB page
await Toc.pageClick(221)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/chemistry-2e/pages/e-water-properties')

// WHEN: click nested EOB page
await Toc.pageClick(230)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/chemistry-2e/pages/chapter-1')
})


test('C543225 canonicals for pages derived from another book', async ({ page, isMobile, browserName }) => {
test.skip(isMobile as boolean, 'test only desktop resolution')
test.skip(browserName == 'webkit', 'test only chrome')
test.skip(browserName == 'firefox', 'test only chrome')

// GIVEN: Open Rex page derived from another book
const bookPage = new ContentPage(page)
const path = '/books/preparing-for-college-success/pages/2-1-why-college'
await bookPage.open(path)

// THEN: Canonical page points to original content
expect(await bookPage.canonical()).toBe('https://openstax.org/books/college-success-concise/pages/1-1-why-college')

// WHEN: click EOC page from a chapter derived from another book
const Toc = new TOC(page)
await Toc.pageClick(14)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/preparing-for-college-success/pages/2-summary')


// WHEN: Open page unique to this book
await Toc.pageClick(3)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/preparing-for-college-success/pages/1-2-your-academic-journey-and-personal-story')

// WHEN: Open EOC page from the chapter unique to this book
await Toc.pageClick(6)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/preparing-for-college-success/pages/1-family-friends-matter')

// WHEN: Open EOB page from the chapter unique to this book
await Toc.pageClick(71)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/preparing-for-college-success/pages/index')
})

test('C543225 canonicals for old editions point to the latest edition', async ({ page, isMobile, browserName }) => {
test.skip(isMobile as boolean, 'test only desktop resolution')
test.skip(browserName == 'webkit', 'test only chrome')
test.skip(browserName == 'firefox', 'test only chrome')

// GIVEN: Open older edition of Rex page derived from another book
const bookPage = new ContentPage(page)
const path = '/books/principles-macroeconomics-2e/pages/1-introduction'
await bookPage.open(path)
// THEN: Canonical page points to latest edition of the original content
expect(await bookPage.canonical()).toBe('https://openstax.org/books/principles-economics-3e/pages/1-introduction')

// WHEN: Open older edition of EOC page of a book derived from another book
const Toc = new TOC(page)
await Toc.pageClick(7)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/principles-macroeconomics-2e/pages/1-key-concepts-and-summary')

// WHEN: Open older edition of nested EOB page of a book derived from another book
await Toc.pageClick(243)
// THEN: Canonical page points to itself
expect(await bookPage.canonical()).toBe('https://openstax.org/books/principles-macroeconomics-2e/pages/chapter-2')


// WHEN: Open older edition of appendix page of a book derived from another book
await Toc.pageClick(241)
// THEN: Canonical page points to latest edition of the original content
expect(await bookPage.canonical()).toBe('https://openstax.org/books/principles-economics-3e/pages/d-the-expenditure-output-model')
})
20 changes: 1 addition & 19 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,8 @@
-->
<link rel="manifest" href="/dist/assets/manifest.json">


<!--
this style shows the osano widget after a delay, giving the app
a chance to explicitly hide it but still defaulting to showing it
as a safety fallback
-->
<style>
.osano-cm-widget {
animation: fadeInAnimation 5s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
@keyframes fadeInAnimation {
0% { opacity: 0; }
90% { opacity: 0; }
100% { opacity: 1; }
}
</style>
<link rel="stylesheet" href="https://ram.openstax.org/osano/osano.css">
<script src="https://cmp.osano.com/AzZqbXTbzhHsU3cv1/68d8e8ae-4024-4489-a000-72766ad284a6/osano.js"></script>
<script src="https://chat.research.openstax.org/assets/static/loader.js" async></script>

<!-- Google Tag Manager -->
<script>
Expand Down
13 changes: 13 additions & 0 deletions pytest-selenium/pages/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
BOUNDING_RECTANGLE = "return arguments[0].getBoundingClientRect();"
COMPUTED_STYLES = "return window.getComputedStyle(arguments[0]){field};"
ELEMENT_SELECT = "return document.querySelector('{selector}');"
FOCUSED_HIGHLIGHT_LOCATOR = "[data-highlight-id='{n}'][aria-current=true]"


class ContentError(Exception):
Expand Down Expand Up @@ -746,6 +747,18 @@ def highlight_ids(self) -> List[str]:
set([highlight.get_attribute("data-highlight-id") for highlight in self.highlights])
)

def highlight_focused(self, highlight_id) -> bool:
"""Return True if the highlight is focused.
:return: ``True`` if the highlight is focused
:rtype: bool
"""
focused_highlight_locator = self.find_elements(
By.CSS_SELECTOR, FOCUSED_HIGHLIGHT_LOCATOR.format(n=highlight_id)
)
return bool(focused_highlight_locator)

@property
def images(self) -> List[WebElement]:
"""Return the content images.
Expand Down
6 changes: 3 additions & 3 deletions pytest-selenium/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ certifi==2023.7.22
cffi==1.15.0
cfgv==3.3.1
chardet==4.0.0
chromedriver-binary==122.0.6261.94
cryptography==42.0.0
chromedriver-binary==124.0.6367.78.0
cryptography==42.0.4
Faker==13.3.4
identify==2.4.12
idna==2.10 # pyup: ignore
idna==3.7 # pyup: ignore
importlib-metadata==4.11.3
more-itertools==8.12.0
nodeenv==1.6.0
Expand Down
30 changes: 11 additions & 19 deletions pytest-selenium/tests/test_highlighting_56.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_another_highlight(

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_focused(id_2), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: click the 1st highlight again
Expand All @@ -79,8 +78,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_another_highlight(

# 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_focused(id_1), "highlight is not in focus"
assert book.content.highlight_box.note == ""


Expand Down Expand Up @@ -127,8 +125,7 @@ def test_modal_for_unsaved_notes_appears_on_page_navigation_using_toc(
# 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_focused(highlight_id), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click the TOC link again
Expand Down Expand Up @@ -202,8 +199,7 @@ def test_modal_for_unsaved_notes_appears_on_page_navigation_using_prev_link(
# 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_focused(highlight_id), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click previous link again
Expand Down Expand Up @@ -277,8 +273,7 @@ def test_modal_for_unsaved_notes_appears_on_page_navigation_using_next_link(
# 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_focused(highlight_id), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click next link again
Expand Down Expand Up @@ -351,8 +346,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_book_title(
# 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_focused(highlight_id), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click on book title again
Expand Down Expand Up @@ -424,8 +418,7 @@ def test_modal_for_unsaved_notes_appears_on_selecting_new_text(
# 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_focused(id_1), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Select some text in the page again
Expand Down Expand Up @@ -500,8 +493,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_search_result_same_page(
# 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_focused(id_1), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click the same search result again
Expand All @@ -512,6 +504,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_search_result_same_page(
book.wait_for_page_to_load()

# THEN: Unsaved note of the user 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"

# AND: The selected search result is highlighted
Expand Down Expand Up @@ -573,8 +566,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_search_result_different_pag
# 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_focused(id_1), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click the same search result again
Expand Down Expand Up @@ -654,7 +646,7 @@ def test_modal_for_unsaved_notes_appears_on_clicking_content_links(
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_focused(id_1), "highlight is not in focus"
assert book.content.highlight_box.note == note

# WHEN: Click the same link again
Expand Down
Loading

0 comments on commit 992a109

Please sign in to comment.