From c51e1171723b9e2c961588b40578ebcc5b528ccc Mon Sep 17 00:00:00 2001 From: duncdrum Date: Fri, 23 Jan 2026 11:27:07 +0100 Subject: [PATCH 1/8] feat: init cypress initial conversion of wdio tests --- .github/workflows/cypress.yml | 106 ++ .gitignore | 8 + README.md | 118 +- build.xml | 3 + cypress.config.cjs | 29 + package-lock.json | 1171 ++++++++++++++++- package.json | 6 + .../conferences/prod_conferences_titles.cy.js | 141 ++ .../conferences/uat_conferences_titles.cy.js | 161 +++ .../countries/prod_countries_landing.cy.js | 18 + .../e2e/countries/prod_countries_titles.cy.js | 56 + .../e2e/countries/uat_countries_landing.cy.js | 22 + .../e2e/countries/uat_countries_titles.cy.js | 73 + .../prod_buildings_titles.cy.js | 59 + .../prod_departmenthistory_titles.cy.js | 75 ++ .../prod_shorthistory_titles.cy.js | 38 + .../uat_buildings_titles.cy.js | 69 + .../uat_departmenthistory_titles.cy.js | 105 ++ .../uat_shorthistory_titles.cy.js | 42 + .../e2e/developer/prod_developer_titles.cy.js | 26 + .../e2e/developer/uat_developer_titles.cy.js | 26 + .../e2e/education/prod_education_titles.cy.js | 76 ++ .../e2e/education/uat_education_titles.cy.js | 96 ++ tests/cypress/e2e/error/prod_404.cy.js | 10 + tests/cypress/e2e/error/uat_404.cy.js | 10 + .../e2e/footnote/prod_footnote_popover.cy.js | 226 ++++ .../e2e/footnote/uat_footnote_popover.cy.js | 232 ++++ .../prod_frus-all-volumes.cy.js | 81 ++ .../prod_frus-volume-landing.cy.js | 57 + .../prod_frus_landing.cy.js | 28 + .../prod_frus_titles.cy.js | 82 ++ .../historical-documents/prod_frus_toc.cy.js | 16 + .../uat_frus-all-volumes.cy.js | 92 ++ .../uat_frus-volume-landing.cy.js | 57 + .../uat_frus_landing.cy.js | 30 + .../uat_frus_titles.cy.js | 99 ++ .../e2e/iiif-images/prod_iiif-viewer.cy.js | 27 + .../e2e/landing/prod_landing_title.cy.js | 10 + .../e2e/landing/prod_landing_twitter.cy.js | 10 + .../e2e/landing/uat_landing_title.cy.js | 10 + .../e2e/landing/uat_landing_twitter.cy.js | 10 + .../milestones/prod_milestones_chapter.cy.js | 15 + .../milestones/prod_milestones_titles.cy.js | 44 + .../milestones/uat_milestones_chapter.cy.js | 15 + .../milestones/uat_milestones_titles.cy.js | 51 + .../cypress/e2e/news/prod_news-article.cy.js | 103 ++ tests/cypress/e2e/news/prod_news-list.cy.js | 116 ++ tests/cypress/e2e/news/uat_news-article.cy.js | 103 ++ tests/cypress/e2e/news/uat_news-list.cy.js | 118 ++ tests/cypress/e2e/open/prod_open_titles.cy.js | 39 + tests/cypress/e2e/open/uat_open_titles.cy.js | 39 + .../e2e/replication/prod_replication.cy.js | 16 + .../e2e/replication/uat_replication.cy.js | 16 + tests/cypress/e2e/search/prod_search.cy.js | 35 + .../search/prod_search_filter_results.cy.js | 85 ++ .../e2e/search/prod_search_new-indexes.cy.js | 84 ++ tests/cypress/e2e/search/uat_search.cy.js | 35 + .../search/uat_search_filter_results.cy.js | 85 ++ tests/cypress/e2e/tags/prod_tags.cy.js | 59 + tests/cypress/e2e/tags/uat_tags.cy.js | 59 + .../e2e/ui-components/prod_breadcrumb.cy.js | 83 ++ .../e2e/ui-components/prod_tooltip.cy.js | 95 ++ .../e2e/ui-components/uat_breadcrumb.cy.js | 83 ++ .../e2e/ui-components/uat_tooltip.cy.js | 94 ++ tests/cypress/fixtures/example.json | 5 + tests/cypress/support/commands.js | 219 +++ tests/cypress/support/e2e.js | 19 + 67 files changed, 5209 insertions(+), 117 deletions(-) create mode 100644 .github/workflows/cypress.yml create mode 100644 cypress.config.cjs create mode 100644 tests/cypress/e2e/conferences/prod_conferences_titles.cy.js create mode 100644 tests/cypress/e2e/conferences/uat_conferences_titles.cy.js create mode 100644 tests/cypress/e2e/countries/prod_countries_landing.cy.js create mode 100644 tests/cypress/e2e/countries/prod_countries_titles.cy.js create mode 100644 tests/cypress/e2e/countries/uat_countries_landing.cy.js create mode 100644 tests/cypress/e2e/countries/uat_countries_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/prod_buildings_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/prod_departmenthistory_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/prod_shorthistory_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/uat_buildings_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/uat_departmenthistory_titles.cy.js create mode 100644 tests/cypress/e2e/departmenthistory/uat_shorthistory_titles.cy.js create mode 100644 tests/cypress/e2e/developer/prod_developer_titles.cy.js create mode 100644 tests/cypress/e2e/developer/uat_developer_titles.cy.js create mode 100644 tests/cypress/e2e/education/prod_education_titles.cy.js create mode 100644 tests/cypress/e2e/education/uat_education_titles.cy.js create mode 100644 tests/cypress/e2e/error/prod_404.cy.js create mode 100644 tests/cypress/e2e/error/uat_404.cy.js create mode 100644 tests/cypress/e2e/footnote/prod_footnote_popover.cy.js create mode 100644 tests/cypress/e2e/footnote/uat_footnote_popover.cy.js create mode 100644 tests/cypress/e2e/historical-documents/prod_frus-all-volumes.cy.js create mode 100644 tests/cypress/e2e/historical-documents/prod_frus-volume-landing.cy.js create mode 100644 tests/cypress/e2e/historical-documents/prod_frus_landing.cy.js create mode 100644 tests/cypress/e2e/historical-documents/prod_frus_titles.cy.js create mode 100644 tests/cypress/e2e/historical-documents/prod_frus_toc.cy.js create mode 100644 tests/cypress/e2e/historical-documents/uat_frus-all-volumes.cy.js create mode 100644 tests/cypress/e2e/historical-documents/uat_frus-volume-landing.cy.js create mode 100644 tests/cypress/e2e/historical-documents/uat_frus_landing.cy.js create mode 100644 tests/cypress/e2e/historical-documents/uat_frus_titles.cy.js create mode 100644 tests/cypress/e2e/iiif-images/prod_iiif-viewer.cy.js create mode 100644 tests/cypress/e2e/landing/prod_landing_title.cy.js create mode 100644 tests/cypress/e2e/landing/prod_landing_twitter.cy.js create mode 100644 tests/cypress/e2e/landing/uat_landing_title.cy.js create mode 100644 tests/cypress/e2e/landing/uat_landing_twitter.cy.js create mode 100644 tests/cypress/e2e/milestones/prod_milestones_chapter.cy.js create mode 100644 tests/cypress/e2e/milestones/prod_milestones_titles.cy.js create mode 100644 tests/cypress/e2e/milestones/uat_milestones_chapter.cy.js create mode 100644 tests/cypress/e2e/milestones/uat_milestones_titles.cy.js create mode 100644 tests/cypress/e2e/news/prod_news-article.cy.js create mode 100644 tests/cypress/e2e/news/prod_news-list.cy.js create mode 100644 tests/cypress/e2e/news/uat_news-article.cy.js create mode 100644 tests/cypress/e2e/news/uat_news-list.cy.js create mode 100644 tests/cypress/e2e/open/prod_open_titles.cy.js create mode 100644 tests/cypress/e2e/open/uat_open_titles.cy.js create mode 100644 tests/cypress/e2e/replication/prod_replication.cy.js create mode 100644 tests/cypress/e2e/replication/uat_replication.cy.js create mode 100644 tests/cypress/e2e/search/prod_search.cy.js create mode 100644 tests/cypress/e2e/search/prod_search_filter_results.cy.js create mode 100644 tests/cypress/e2e/search/prod_search_new-indexes.cy.js create mode 100644 tests/cypress/e2e/search/uat_search.cy.js create mode 100644 tests/cypress/e2e/search/uat_search_filter_results.cy.js create mode 100644 tests/cypress/e2e/tags/prod_tags.cy.js create mode 100644 tests/cypress/e2e/tags/uat_tags.cy.js create mode 100644 tests/cypress/e2e/ui-components/prod_breadcrumb.cy.js create mode 100644 tests/cypress/e2e/ui-components/prod_tooltip.cy.js create mode 100644 tests/cypress/e2e/ui-components/uat_breadcrumb.cy.js create mode 100644 tests/cypress/e2e/ui-components/uat_tooltip.cy.js create mode 100644 tests/cypress/fixtures/example.json create mode 100644 tests/cypress/support/commands.js create mode 100644 tests/cypress/support/e2e.js diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml new file mode 100644 index 00000000..bca85e52 --- /dev/null +++ b/.github/workflows/cypress.yml @@ -0,0 +1,106 @@ +# This workflow runs Cypress tests in Firefox against a running eXist-db instance. +# It mirrors the build workflow structure but executes Cypress tests instead of smoke tests. + +name: Cypress Tests + +on: [push] + +jobs: + cypress-tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Test against different eXist-db versions + exist-version: [latest, release] + java-version: [11, 21] + exclude: + - exist-version: release + java-version: 21 + - exist-version: latest + java-version: 11 + + steps: + # Checkout code + - uses: actions/checkout@v6 + + # Install Test Dependencies + - name: Install Test Dependencies + run: | + sudo apt-get update + sudo apt-get install -y libxml2-utils + + # Sanity check + - name: Ensure all XML files are well-formed + run: | + find . -type f -name '*.xml' -print0 | xargs -0 xmllint -noout + + # Setup Node.js + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + cache: npm + node-version: lts/* + + # Install dependencies + - name: Install dependencies + run: npm ci --no-optional + + # Build + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: ${{ matrix.java-version }} + + - name: Build Expath Package + run: ant -Dapp.version=1.0.0-SNAPSHOT + + - name: Add expath dependencies + working-directory: build + run: | + wget https://exist-db.org/exist/apps/public-repo/public/expath-crypto-module-6.0.1.xar -O 000.xar + wget http://exist-db.org/exist/apps/public-repo/public/templating-1.1.0.xar -O 001.xar + wget https://exist-db.org/exist/apps/public-repo/public/tei-publisher-lib-2.10.1.xar -O 002.xar + wget https://exist-db.org/exist/apps/public-repo/public/functx-1.0.1.xar -O 003.xar + wget https://github.com/HistoryAtState/aws.xq/releases/latest/download/aws-xq.xar -O 004.xar + + # Install and start eXist-db + - name: Start exist-ci containers + run: | + docker run -dit -p 8080:8080 -v ${{ github.workspace }}/build:/exist/autodeploy \ + --name exist --rm --health-interval=2s --health-start-period=4s \ + duncdrum/existdb:${{ matrix.exist-version }} + + - name: Wait for eXist-db to start + timeout-minutes: 10 + run: | + while ! docker logs exist | grep -q "Server has started"; \ + do sleep 2s; \ + done + + # Run Cypress tests in Firefox + - name: Run Cypress tests in Firefox + uses: cypress-io/github-action@v7 + with: + install: false + browser: firefox + spec: 'tests/cypress/e2e/**/prod_*.cy.js' + + + # Upload test results + - name: Upload Cypress screenshots + uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots-${{ matrix.exist-version }}-${{ matrix.java-version }} + path: tests/cypress/screenshots + retention-days: 7 + + - name: Upload Cypress videos + uses: actions/upload-artifact@v4 + if: always() + with: + name: cypress-videos-${{ matrix.exist-version }}-${{ matrix.java-version }} + path: tests/cypress/videos + retention-days: 7 diff --git a/.gitignore b/.gitignore index fec8a4f6..88f94ef0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,14 @@ resources/scripts/app.min.js tests/reports/errorShots/* tests/reports/junit-reports/* +test/cypress/screenshots/ +test/cypress/videos/ +test/cypress/downloads/ + +.DS_Store + +plan/ + # local properties local.node-exist.json diff --git a/README.md b/README.md index e3cf4ef3..50b2aff7 100644 --- a/README.md +++ b/README.md @@ -140,106 +140,80 @@ Verify you have a local hsg-project running at localhost:8080/exist/apps/hsg-she ### How to run local web tests -#### 1. Install Chrome +#### 1. Install Dependencies -Make sure you have Google Chrome >= 110 and all required node_modules installed (`npm install`). +Make sure you have all required node_modules installed (`npm install`). Cypress will be installed as part of the devDependencies. -##### Troubleshooting Chromedriver Problems +#### 2. Configuration -If you have problems with installing or running Chromedriver, have a look at these resources: [webdriver.io/docs/wdio-chromedriver-service.html](https://webdriver.io/docs/wdio-chromedriver-service.html), [stackoverflow](https://stackoverflow.com/questions/54940853/chrome-version-must-be-between-71-and-75-error-after-updating-to-chromedriver-2) +Test configuration is in `cypress.config.cjs`. The baseUrl is set to `http://localhost:8080/exist/apps/hsg-shell` by default. Test files are located in `tests/cypress/e2e/` and organized by feature area. -It might be helpful to run +Test files follow naming conventions: +- `prod_*.cy.js` - Production environment tests +- `uat_*.cy.js` - UAT environment tests -```shell -npm install chromedriver --detect_chromedriver_version -``` - -All available chromedriver versions are listed here: [https://chromedriver.storage.googleapis.com/](https://chromedriver.storage.googleapis.com/). - -If your current Chrome version doesn't match the required one. -This command will check the required version and install a suitable Chromedriver for you. - -Note: If you are using an Apple M1 computer, the filename for chromedriver has been changed by Chrome between version 105 and 106 [See fix for node_chromedriver: https://github.com/giggio/node-chromedriver/pull/386/](https://github.com/giggio/node-chromedriver/pull/386/commits/7bc8dc46583ca484ca17707d9d98f8a1f98b9be4#). -When running this project's ant script on an M1 with a Chrome version <=105, you should either update Chrome to 110 like defined in file `package.json`, or change the chromedriver version to your current Chrome version to match the expected chromedriver filename. - -#### 2. Optional: Edit configuration - -* Optional: Edit which test files or suites you would like to run. - Here is the part where to define the test suites: - ``` - suites: { - dev: [ - './tests/specs/**/dev_*.js' - ], - prod: [ - './tests/specs/**/prod_*.js' - ] - } - ``` - -#### 3. Run the web test +#### 3. Run the tests -Basic syntax of starting an entire test suite is +**Open Cypress Test Runner (Interactive Mode):** ```bash -npm test +npm run cy:open ``` -Use `npx` to execute different test suites - +**Run all tests (Headless Mode):** ```bash -npx wdio wdio.conf.js --suite +npm run cy:run ``` -for example (runs all development environment test that have been listed in the wdio configuration in `suites: {prod : ...}`): +**Run production tests only:** ```bash -npx wdio wdio.conf.js --suite test-prod +npm run cy:run:prod ``` -and for a single test it is +**Run UAT tests only:** ```bash -npx wdio wdio.conf.js --spec path-to-the-testspec +npm run cy:run:uat ``` -for example: + +**Run jenkins suite (production tests):** ```bash -npx wdio wdio.conf.js --spec tests/specs/error/prod_404.spec.js +npm run cy:run:jenkins ``` -In addition, you can define running the test commands in `package.json` -within the `scripts` key, for example: -```json -"test": "./node_modules/.bin/wdio wdio.conf.js --suite test-prod" -``` -and run this command with -```shell -npm run-script test-prod +**Run a specific test file:** +```bash +npx cypress run --spec "tests/cypress/e2e/landing/prod_landing_title.cy.js" ``` -This test runs in "headless" mode. It means the test will run in the background without opening a browser window. -If you want to observe all actions in the web test in a browser, just comment out the `headless` argument in the `wdio.conf.js`: +#### 4. Test Structure -``` -chromeOptions: { - args: [ - //'headless', - 'disable-gpu', - '--window-size=1280,1024', - 'ignore-certificate-errors', - 'ignore-urlfetcher-cert-requests' - ], - binary: process.env.WDIO_CHROME_BINARY -}, -``` +Tests are organized in `tests/cypress/e2e/` by feature: +- `conferences/` - Conference pages +- `countries/` - Countries pages +- `departmenthistory/` - Department history pages +- `developer/` - Developer resources +- `education/` - Education pages +- `error/` - Error pages (404, etc.) +- `historical-documents/` - FRUS and historical documents +- `iiif-images/` - IIIF image viewer tests +- `landing/` - Landing page tests +- `milestones/` - Milestones pages +- `open/` - Open Government Initiative +- `search/` - Search functionality +- `tags/` - Tags pages +- `ui-components/` - UI component tests (breadcrumb, etc.) + +Custom commands are available in `tests/cypress/support/commands.js` which provide helper methods converted from the original WebdriverIO Page Objects. -#### 4. Further documentation +#### 5. Further documentation -This web test is configured to use the framework `Mocha` with `Chai` and activated Chai plugin `assert` (`global.assert = chai.assert;`) for assertions. +This test suite uses Cypress with Mocha and Chai for assertions. The `assert` global is available (matching the previous WebdriverIO setup). Have a look at the documentation: -* General overview about "webdriver.io": [webdriver.io/docs/gettingstarted](https://webdriver.io/docs/gettingstarted.html) -* Webdriver.io functions: [webdriver.io/docs/api](https://webdriver.io/docs/api.html) -* List of all functions in the Chai Assertion library: [chaijs.com/api/assert](https://www.chaijs.com/api/assert/) -* Overview about mocha.js: [mochajs.org](https://mochajs.org/) +* Cypress documentation: [docs.cypress.io](https://docs.cypress.io/) +* Cypress API: [docs.cypress.io/api](https://docs.cypress.io/api) +* Chai Assertion library: [chaijs.com/api/assert](https://www.chaijs.com/api/assert/) +* Mocha documentation: [mochajs.org](https://mochajs.org/) ## Release diff --git a/build.xml b/build.xml index d2d311d2..4a39dfd3 100644 --- a/build.xml +++ b/build.xml @@ -94,11 +94,14 @@ + + + diff --git a/cypress.config.cjs b/cypress.config.cjs new file mode 100644 index 00000000..e9dac174 --- /dev/null +++ b/cypress.config.cjs @@ -0,0 +1,29 @@ +const { defineConfig } = require('cypress'); +const glob = require('glob'); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + on('task', { + findFiles({ pattern }) { + // Use glob.sync to get the files synchronously + return glob.sync(pattern, { nodir: true }); + } + }); + return config; + }, + baseUrl: 'http://localhost:8080/exist/apps/hsg-shell', + viewportWidth: 1280, + viewportHeight: 720, + trashAssetsBeforeRuns: true, + includeShadowDom: true, + retries: 1, + supportFile: 'tests/cypress/support/e2e.js', + specPattern: 'tests/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', + screenshotsFolder: 'tests/cypress/screenshots', + videosFolder: 'tests/cypress/videos', + fixturesFolder: 'tests/cypress/fixtures', + downloadsFolder: 'tests/cypress/downloads' + }, +}); + diff --git a/package-lock.json b/package-lock.json index 9eea591f..97bb0bdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "chai-as-promised": "^7.1.1", "chromedriver": "^131.0.5", "conventional-changelog-conventionalcommits": "^7.0.2", + "cypress": "^15.9.0", "del": "^6.1.1", "gulp": "^5.0.1", "gulp-autoprefixer": "^7.0.1", @@ -536,6 +537,67 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@cypress/request": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.10.tgz", + "integrity": "sha512-hauBrOdvu08vOsagkZ/Aju5XuiZx6ldsLfByg1htFeldhex+PeMrYauANzFsMJeAA0+dyPLbDoX2OYuvVoLDkQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~4.0.4", + "http-signature": "~1.4.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "~6.14.1", + "safe-buffer": "^5.1.2", + "tough-cookie": "^5.0.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/@existdb/gulp-exist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@existdb/gulp-exist/-/gulp-exist-5.0.0.tgz", @@ -2273,6 +2335,20 @@ "@types/node": "*" } }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sizzle": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz", + "integrity": "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -4591,8 +4667,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true + ] }, "node_modules/archive-type": { "version": "4.0.0", @@ -4891,6 +4966,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -4921,6 +5016,16 @@ "node": ">=4" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -5026,6 +5131,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" + }, "node_modules/axios": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", @@ -5093,6 +5215,16 @@ "node": ">=10.0.0" } }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/before-after-hook": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", @@ -5898,6 +6030,20 @@ "readable-stream": "^3.4.0" } }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -6285,6 +6431,16 @@ "node": ">=14.16" } }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -6304,6 +6460,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -6364,6 +6551,13 @@ } ] }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/caw": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", @@ -6675,6 +6869,23 @@ "@colors/colors": "1.5.0" } }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -6900,6 +7111,24 @@ "color-support": "bin.js" } }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -6919,6 +7148,16 @@ "dev": true, "optional": true }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -7338,6 +7577,206 @@ "node": ">=0.10.0" } }, + "node_modules/cypress": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-15.9.0.tgz", + "integrity": "sha512-Ks6Bdilz3TtkLZtTQyqYaqtL/WT3X3APKaSLhTV96TmTyudzSjc6EJsJCHmBb7DxO+3R12q3Jkbjgm/iPgmwfg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@cypress/request": "^3.0.10", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "@types/tmp": "^0.2.3", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "ci-info": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-table3": "0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "hasha": "5.2.2", + "is-installed-globally": "~0.4.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "supports-color": "^8.1.1", + "systeminformation": "^5.27.14", + "tmp": "~0.2.4", + "tree-kill": "1.2.2", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^20.1.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/cypress/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "colors": "1.4.0" + } + }, + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/cypress/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cypress/node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/d": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", @@ -7363,6 +7802,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", @@ -7432,6 +7884,13 @@ "node": ">=4.0" } }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8487,6 +8946,21 @@ "node": ">=0.10.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -8564,6 +9038,24 @@ "wcwidth": "^1.0.1" } }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, "node_modules/edge-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-2.2.1.tgz", @@ -8617,6 +9109,30 @@ "once": "^1.4.0" } }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/enquirer/node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -8901,13 +9417,11 @@ "dev": true }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -8922,10 +9436,11 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -8934,14 +9449,16 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -9111,6 +9628,13 @@ "es5-ext": "~0.10.14" } }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true, + "license": "MIT" + }, "node_modules/exec-buffer": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", @@ -9345,7 +9869,6 @@ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", "dev": true, - "optional": true, "dependencies": { "pify": "^2.2.0" }, @@ -9358,7 +9881,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" } @@ -9505,6 +10027,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, "node_modules/fancy-log": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-2.0.0.tgz", @@ -9879,14 +10411,27 @@ "node": ">=0.10.0" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -10094,16 +10639,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -10112,6 +10663,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -10179,6 +10744,16 @@ "node": ">= 14" } }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/gifsicle": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-5.3.0.tgz", @@ -10355,6 +10930,32 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -10502,12 +11103,13 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11228,10 +11830,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11267,6 +11870,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -11365,6 +11995,21 @@ "node": ">= 14" } }, + "node_modules/http-signature": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.18.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -12300,6 +12945,23 @@ "node": ">=0.10.0" } }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -12581,6 +13243,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -12694,6 +13363,13 @@ "node": ">=0.10.0" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, "node_modules/issue-parser": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", @@ -12909,6 +13585,13 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -12958,6 +13641,22 @@ "node": "*" } }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "node_modules/junit-report-builder": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/junit-report-builder/-/junit-report-builder-3.2.1.tgz", @@ -13118,6 +13817,34 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -13277,6 +14004,13 @@ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.pickby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", @@ -13400,6 +14134,58 @@ "node": ">=4" } }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/logalot": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", @@ -13988,6 +14774,16 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "dev": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -16973,10 +17769,14 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17183,6 +17983,13 @@ "node": ">=0.10.0" } }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true, + "license": "MIT" + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -17591,6 +18398,13 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", @@ -17916,6 +18730,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -18043,6 +18867,22 @@ "teleport": ">=0.2.0" } }, + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/query-selector-shadow-dom": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", @@ -18396,6 +19236,16 @@ "node": ">= 10.13.0" } }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "throttleit": "^1.0.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18524,6 +19374,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rgb2hex": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz", @@ -19431,15 +20288,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -19564,6 +20479,21 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -19794,6 +20724,39 @@ "node": ">=0.8.0" } }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -20326,6 +21289,33 @@ "node": ">=4" } }, + "node_modules/systeminformation": { + "version": "5.30.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.5.tgz", + "integrity": "sha512-DpWmpCckhwR3hG+6udb6/aQB7PpiqVnvSljrjbKxNSvTRsGsg7NVE3/vouoYf96xgwMxXFKcS4Ux+cnkFwYM7A==", + "dev": true, + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", @@ -20593,6 +21583,16 @@ "node": ">=0.8" } }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -20753,6 +21753,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -20796,6 +21816,19 @@ "node": ">=10.13.0" } }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -20819,6 +21852,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -20853,7 +21896,6 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, - "optional": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -20861,6 +21903,13 @@ "node": "*" } }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, "node_modules/type": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", @@ -21154,6 +22203,16 @@ "dev": true, "optional": true }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -21293,6 +22352,28 @@ "node": ">= 10.13.0" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vinyl": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", diff --git a/package.json b/package.json index e7cdee24..058c5b1c 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "chai-as-promised": "^7.1.1", "chromedriver": "^131.0.5", "conventional-changelog-conventionalcommits": "^7.0.2", + "cypress": "^15.9.0", "del": "^6.1.1", "gulp": "^5.0.1", "gulp-autoprefixer": "^7.0.1", @@ -48,6 +49,11 @@ "scripts": { "test": "./node_modules/.bin/wdio wdio.conf.js --suite jenkins", "test-prod": "./node_modules/.bin/wdio wdio.conf.js --suite prod", + "cy:open": "cypress open", + "cy:run": "cypress run", + "cy:run:prod": "cypress run --spec 'tests/cypress/e2e/**/prod_*.cy.js'", + "cy:run:uat": "cypress run --spec 'tests/cypress/e2e/**/uat_*.cy.js'", + "cy:run:jenkins": "cypress run --spec 'tests/cypress/e2e/**/prod_*.cy.js'", "update": "npm update && gulp", "start": "npm install --quiet && gulp" }, diff --git a/tests/cypress/e2e/conferences/prod_conferences_titles.cy.js b/tests/cypress/e2e/conferences/prod_conferences_titles.cy.js new file mode 100644 index 00000000..e21af2ec --- /dev/null +++ b/tests/cypress/e2e/conferences/prod_conferences_titles.cy.js @@ -0,0 +1,141 @@ +/** + * Checks if conference pages have the correct titles + */ + +const regex = /(\<|\/)[a-z]*>/gi + +const page = { link: 'conferences', title: 'Conferences', h: 1 } +const headline = { + 1: '#content-inner h1', + 2: '#content-inner h2', + 3: '#content-inner h3' +} + +const subpages = [ + // 1. conference landing + { + name: 'p2', + link: 'conferences/2012-national-security-policy-salt', + title: '"National Security Policy and SALT I, 1969-1972"', + h: 1 + }, + // 2. conference landing + { + name: 'p3', + link: 'conferences/2011-foreign-economic-policy', + title: '"Foreign Economic Policy, 1973-1976"', + h: 1 + }, + // 2nd level + { + name: 'p4', + link: 'conferences/2011-foreign-economic-policy/audio-transcripts', + title: 'Audio and Transcripts', + h: 3 + }, + // 3rd level, 1st "subpage" of videos-transcripts but is not represented in the URL! + { + name: 'p5', + link: 'conferences/2011-foreign-economic-policy/opening-remarks-and-editors-talk', + title: 'Opening Remarks and Editor\'s Talk on Foreign Economic Policy, 1973-1976', + h: 2 + }, + // 3rd level, 2nd "subpage" of audio-transcripts but is not represented in the URL! Hidden in page navigation (-> next) + { + name: 'p6', + link: 'conferences/2011-foreign-economic-policy/panel', + title: 'Panel Discussion', + h: 2 + }, + // 3. conference landing page + { + name: 'p7', + link: 'conferences/2010-southeast-asia', + title: 'Program', + h: 1 + }, + // 3rd level TODO: Check images + { + name: 'p8', + link: 'conferences/2010-southeast-asia/photos', + title: 'Vietnam Photo Gallery', + h: 1 + }, + // 3rd level TODO: Check video embedding + { + name: 'p9', + link: 'conferences/2010-southeast-asia/videos-transcripts', + title: 'Videos and Transcripts', + h: 3 + }, + // 4th level 1st "subpage" of videos-transcripts but is not represented in the URL! + { + name: 'p10', + link: 'conferences/2010-southeast-asia/secretary-clinton', + title: 'Opening Address by Secretary of State Hillary Rodham Clinton', + h: 2 + }, + // 3rd level + { + name: 'p11', + link: 'conferences/2010-southeast-asia/background-materials', + title: 'Background Materials', + h: 3 + }, + // 4th level TODO: Check images + { + name: 'p11', + link: 'conferences/2010-southeast-asia/maps', + title: 'Maps', + h: 2 + }, + // 4. conference landing + { + name: 'p13', + link: 'conferences/2007-detente', + title: 'Schedule', + h: 1 + }, + // 2nd level + { + name: 'p14', + link: 'conferences/2007-detente/roundtable1', + title: 'Introduction to Roundtable Discussion of Former Government Officials', + h: 1 + }, + // 5. conference landing + { + name: 'p15', + link: 'conferences/2006-china-cold-war', + title: '"Transforming the Cold War: The United States and China, 1969-1980"', + h: 1 + }, + // 2nd level + { + name: 'p16', + link: 'conferences/2006-china-cold-war/susser', + title: 'Introductions', + h: 2 + } +] + +describe('The conference page', function () { + it('should display the headline', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(page.title) + }) + }) + + // Subpage titles check + describe('Each "Conference" subpage should be displayed and subsequently', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.get(headline[page.h]).invoke('text').then((title) => { + expect(title.replace(regex, '')).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/conferences/uat_conferences_titles.cy.js b/tests/cypress/e2e/conferences/uat_conferences_titles.cy.js new file mode 100644 index 00000000..aa8e8666 --- /dev/null +++ b/tests/cypress/e2e/conferences/uat_conferences_titles.cy.js @@ -0,0 +1,161 @@ +/** + * Checks if conference pages have the correct titles + */ + +const regex = /(\<|\/)[a-z]*>/gi + +const subpages = { + links: { + p1: 'conferences', + p2: 'conferences/2012-national-security-policy-salt', // 1. conference landing + p3: 'conferences/2011-foreign-economic-policy', // 2. conference landing + p4: 'conferences/2011-foreign-economic-policy/audio-transcripts', // 2nd level + p5: 'conferences/2011-foreign-economic-policy/opening-remarks-and-editors-talk', // 3rd level, 1st "subpage" of videos-transcripts but is not represented in the URL! + p6: 'conferences/2011-foreign-economic-policy/panel', // 3rd level, 2nd "subpage" of audio-transcripts but is not represented in the URL! Hidden in page navigation (-> next) + p7: 'conferences/2010-southeast-asia', // 3. conference landing page + p8: 'conferences/2010-southeast-asia/photos', // 3rd level TODO: Check images + p9: 'conferences/2010-southeast-asia/videos-transcripts', // 3rd level TODO: Check video embedding + p10: 'conferences/2010-southeast-asia/secretary-clinton', // 4th level 1st "subpage" of videos-transcripts but is not represented in the URL! + p11: 'conferences/2010-southeast-asia/background-materials', // 3rd level + p12: 'conferences/2010-southeast-asia/maps', // 4th level TODO: Check images + p13: 'conferences/2007-detente', // 4. conference landing + p14: 'conferences/2007-detente/roundtable1', // 2nd level + p15: 'conferences/2006-china-cold-war', // 5. conference landing + p16: 'conferences/2006-china-cold-war/susser' // 2nd level + }, + titles: { + p1: 'Conferences', // h1 + p2: '"National Security Policy and SALT I, 1969-1972"', // h1 + p3: '"Foreign Economic Policy, 1973-1976"', // h1 + p4: 'Audio and Transcripts', // h3 + p5: 'Opening Remarks and Editor\'s Talk on Foreign Economic Policy, 1973-1976', // h2 + p6: 'Panel Discussion', // h2 + p7: 'Program', // h1 + p8: 'Vietnam Photo Gallery', // h1 + p9: 'Videos and Transcripts', // h3 + p10: 'Opening Address by Secretary of State Hillary Rodham Clinton', // h2 + p11: 'Background Materials', // h3 + p12: 'Maps', // h2 + p13: 'Schedule', // h1 + p14: 'Introduction to Roundtable Discussion of Former Government Officials', // h1 + p15: '"Transforming the Cold War: The United States and China, 1969-1980"', // h1 + p16: 'Introductions' // h2 + } +} + +describe('Conference pages: ', function () { + // Subpage titles check + describe('Each "Conference" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH3().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH2().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH2().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p6) + }) + }) + + it('should display the headline "' + subpages.titles.p7 + '" ', function () { + cy.openPage(subpages.links.p7) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p7) + }) + }) + + it('should display the headline "' + subpages.titles.p8 + '" ', function () { + cy.openPage(subpages.links.p8) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p8) + }) + }) + + it('should display the headline "' + subpages.titles.p9 + '" ', function () { + cy.openPage(subpages.links.p9) + cy.getHeadlineH3().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p9) + }) + }) + + it('should display the headline "' + subpages.titles.p10 + '" ', function () { + cy.openPage(subpages.links.p10) + cy.getHeadlineH2().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p10) + }) + }) + + it('should display the headline "' + subpages.titles.p11 + '" ', function () { + cy.openPage(subpages.links.p11) + cy.getHeadlineH3().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p11) + }) + }) + + it('should display the headline "' + subpages.titles.p12 + '" ', function () { + cy.openPage(subpages.links.p12) + cy.getHeadlineH2().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p12) + }) + }) + + it('should display the headline "' + subpages.titles.p13 + '" ', function () { + cy.openPage(subpages.links.p13) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p13) + }) + }) + + it('should display the headline "' + subpages.titles.p14 + '" ', function () { + cy.openPage(subpages.links.p14) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p14) + }) + }) + + it('should display the headline "' + subpages.titles.p15 + '" ', function () { + cy.openPage(subpages.links.p15) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p15) + }) + }) + + it('should display the headline "' + subpages.titles.p16 + '" ', function () { + cy.openPage(subpages.links.p16) + cy.getHeadlineH2().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p16) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/countries/prod_countries_landing.cy.js b/tests/cypress/e2e/countries/prod_countries_landing.cy.js new file mode 100644 index 00000000..d4a79c66 --- /dev/null +++ b/tests/cypress/e2e/countries/prod_countries_landing.cy.js @@ -0,0 +1,18 @@ +/** + * Checks departmenthistory page type + */ + +const mainpage = { + link: 'countries', // 1st level subpage (landing) + title: 'Countries' +} + +describe('The "Countries" landing page', function () { + it('should display a select input for choosing countries', function () { + cy.openPage(mainpage.link) + cy.get('select[data-template="countries:load-countries"]').should('exist') + }) + + // TODO: Check interacting with select input and choose countries + // TODO: Check sidebar +}) \ No newline at end of file diff --git a/tests/cypress/e2e/countries/prod_countries_titles.cy.js b/tests/cypress/e2e/countries/prod_countries_titles.cy.js new file mode 100644 index 00000000..c7437101 --- /dev/null +++ b/tests/cypress/e2e/countries/prod_countries_titles.cy.js @@ -0,0 +1,56 @@ +/** + * Checks departmenthistory page type + */ + +const regex = /(\<|\/)[a-z]*>/gi + +const mainpage = { name: 'p1', link: 'countries', title: 'Countries' } + +const subpages = [ + { + name: 'p2', + link: 'countries/archives', + title: 'World Wide Diplomatic Archives Index' + }, + { + name: 'p3', + link: 'countries/archives/all', + title: 'All Countries' + }, + { + name: 'p4', + link: 'countries/archives/afghanistan', + title: 'World Wide Diplomatic Archives Index: Afghanistan' + }, + { + name: 'p5', + link: 'countries/archives/bahamas', + title: 'World Wide Diplomatic Archives Index: Bahamas' + }, + { + name: 'p6', + link: 'countries/archives/zimbabwe', + title: 'World Wide Diplomatic Archives Index: Zimbabwe' + } +] + +describe('On the Countries page ', function () { + it('should display the headline', function () { + cy.openPage(mainpage.link) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(mainpage.title) + }) + }) + + // Subpage titles check + describe('Each Countries subpage', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/countries/uat_countries_landing.cy.js b/tests/cypress/e2e/countries/uat_countries_landing.cy.js new file mode 100644 index 00000000..afd62c70 --- /dev/null +++ b/tests/cypress/e2e/countries/uat_countries_landing.cy.js @@ -0,0 +1,22 @@ +/** + * Checks departmenthistory page type + */ + +const subpages = { + links: { + p1: 'countries' // 1st level subpage (landing) + }, + titles: { + p1: 'Countries' + } +} + +describe('The "Countries" landing page', function () { + it('should display a select input for choosing countries', function () { + cy.openPage(subpages.links.p1) + cy.get('select[data-template="countries:load-countries"]').should('exist') + }) + + // TODO: Check interacting with select input and choose countries + // TODO: Check sidebar +}) \ No newline at end of file diff --git a/tests/cypress/e2e/countries/uat_countries_titles.cy.js b/tests/cypress/e2e/countries/uat_countries_titles.cy.js new file mode 100644 index 00000000..a2d60178 --- /dev/null +++ b/tests/cypress/e2e/countries/uat_countries_titles.cy.js @@ -0,0 +1,73 @@ +/** + * Checks departmenthistory page type + */ + +const regex = /(\<|\/)[a-z]*>/gi + +const subpages = { + links: { + p1: 'countries', // 1st level subpage (landing) + p2: 'countries/archives', // 2nd level sub page + p3: 'countries/archives/all', // 3rd level overview page + p4: 'countries/archives/afghanistan', // 4th level sub page + p5: 'countries/archives/bahamas', // 4th level sub page + p6: 'countries/archives/zimbabwe' // 4th level sub page + }, + titles: { + p1: 'Countries', + p2: 'World Wide Diplomatic Archives Index', + p3: 'All Countries', + p4: 'World Wide Diplomatic Archives Index: Afghanistan', + p5: 'World Wide Diplomatic Archives Index: Bahamas', + p6: 'World Wide Diplomatic Archives Index: Zimbabwe' + } +} + +describe('Countries pages: ', function () { + // Subpage titles check + describe('Each Countries subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p2) + }) + }) + + // 3rd level sub page, archives overview page with countries list + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p3) + }) + }) + + // 4th level sub page - random pin-point checks on third level subpages from here on + it('should display the headline "' + subpages.titles.p4 + '"', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH1().then((title) => { + expect(title.replace(regex, '')).to.equal(subpages.titles.p6) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/prod_buildings_titles.cy.js b/tests/cypress/e2e/departmenthistory/prod_buildings_titles.cy.js new file mode 100644 index 00000000..5d5d581b --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/prod_buildings_titles.cy.js @@ -0,0 +1,59 @@ +/** + * Checks departmenthistory subpage type "buildings" + */ + +const mainpage = { + name: 'p1', + link: 'departmenthistory/buildings', + title: 'Buildings of the Department of State' +} + +const subpages = [ + { + name: 'p2', + link: 'departmenthistory/buildings/intro', + title: 'Introduction' + }, + { + name: 'p3', + link: 'departmenthistory/buildings/foreword', + title: 'Original Foreword' + }, + { + name: 'p4', + link: 'departmenthistory/buildings/section1', + title: 'The Period of the Continental Congress' + }, + { + name: 'p5', + link: 'departmenthistory/buildings/section2', + title: 'Carpenters\' Hall, Philadelphia\nSept. 5, 1774—Oct. 26, 1774' + }, + { + name: 'p6', + link: 'departmenthistory/buildings/section3', + title: 'Pennsylvania State House (Independence Hall), Philadelphia\n' + + 'Intermittingly from May 10, 1775 to March 1, 1781' + } +] + +describe('Buildings pages: ', function () { + it('should display the headline', function () { + cy.openPage(mainpage.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(mainpage.title) + }) + }) + + // Subpage titles check + describe('Each "Buildings" subpage', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/prod_departmenthistory_titles.cy.js b/tests/cypress/e2e/departmenthistory/prod_departmenthistory_titles.cy.js new file mode 100644 index 00000000..58395764 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/prod_departmenthistory_titles.cy.js @@ -0,0 +1,75 @@ +/** + * Checks departmenthistory page type + */ + +/** + * REMOVED TIMELIEN FROM TESTS + * + { + name: 'p2', + link: 'departmenthistory/timeline', + title: 'Administrative Timeline of the Department of State' + }, + */ + +const subpages = [ + { + name: 'p1', + link: 'departmenthistory', + title: 'Department History' + }, + { + name: 'p3', + link: 'departmenthistory/people/secretaries', + title: 'Biographies of the Secretaries of State' + }, + { + name: 'p4', + link: 'departmenthistory/people/principals-chiefs', + title: 'Principal Officers and Chiefs of Mission' + }, + { + name: 'p5', + link: 'departmenthistory/travels/secretary', + title: 'Travels Abroad of the Secretary of State' + }, + { + name: 'p6', + link: 'departmenthistory/travels/president', + title: 'Travels Abroad of the President' + }, + { + name: 'p7', + link: 'departmenthistory/visits', + title: 'Visits by Foreign Leaders' + }, + { + name: 'p8', + link: 'departmenthistory/wwi', + title: 'World War I and the Department' + }, + { + name: 'p9', + link: 'departmenthistory/buildings', + title: 'Buildings of the Department of State' + }, + { + name: 'p10', + link: 'departmenthistory/diplomatic-couriers', + title: 'U.S. Diplomatic Couriers' + } +] + +describe('Department History pages: ', function () { + // Subpage titles check + describe('Each "Department History" subpage', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/prod_shorthistory_titles.cy.js b/tests/cypress/e2e/departmenthistory/prod_shorthistory_titles.cy.js new file mode 100644 index 00000000..cb40cf94 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/prod_shorthistory_titles.cy.js @@ -0,0 +1,38 @@ +/** + * Checks departmenthistory short-history page type + */ + +const subpages = [ + { + name: 'p1', + link: 'departmenthistory/short-history', + level: 'h1', + title: 'A Short History of the Department of State' + }, + { + name: 'p2', + link: 'departmenthistory/short-history/foundations', + level: 'h3', + title: 'Foundations of Foreign Affairs, 1775-1823' + }, + { + name: 'p3', + link: 'departmenthistory/short-history/origins', + level: 'h2', + title: 'Origins of a Diplomatic Tradition' + } +] + +describe('Short-history pages: ', function () { + // Subpage titles check + describe('Each "Short-history" subpage', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.get('#content-inner ' + page.level).invoke('text').then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/uat_buildings_titles.cy.js b/tests/cypress/e2e/departmenthistory/uat_buildings_titles.cy.js new file mode 100644 index 00000000..d9c52173 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/uat_buildings_titles.cy.js @@ -0,0 +1,69 @@ +/** + * Checks departmenthistory subpage type "buildings" + */ + +const subpages = { + links: { + p1: 'departmenthistory/buildings', + p2: 'departmenthistory/buildings/intro', + p3: 'departmenthistory/buildings/foreword', + p4: 'departmenthistory/buildings/section1', + p5: 'departmenthistory/buildings/section2', // TODO: Check footnotes and references + p6: 'departmenthistory/buildings/section3' + }, + titles: { + p1: 'Buildings of the Department of State', // h1 + p2: 'Introduction', + p3: 'Original Foreword', + p4: 'The Period of the Continental Congress', + p5: 'Carpenters\' Hall, Philadelphia\nSept. 5, 1774—Oct. 26, 1774', + p6: 'Pennsylvania State House (Independence Hall), Philadelphia\nIntermittingly from May 10, 1775 to March 1, 1781' + } +} + +describe('Buildings pages: ', function () { + // Subpage titles check + describe('Each "Buildings" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p6) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/uat_departmenthistory_titles.cy.js b/tests/cypress/e2e/departmenthistory/uat_departmenthistory_titles.cy.js new file mode 100644 index 00000000..ed21f687 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/uat_departmenthistory_titles.cy.js @@ -0,0 +1,105 @@ +/** + * Checks departmenthistory page type + */ + +const subpages = { + links: { + p1: 'departmenthistory', + p2: 'departmenthistory/timeline', + p3: 'departmenthistory/people/secretaries', + p4: 'departmenthistory/people/principals-chiefs', + p5: 'departmenthistory/travels/secretary', + p6: 'departmenthistory/travels/president', + p7: 'departmenthistory/visits', + p8: 'departmenthistory/wwi', + p9: 'departmenthistory/buildings', + p10: 'departmenthistory/diplomatic-couriers' + }, + titles: { + p1: 'Department History', + p2: 'Administrative Timeline of the Department of State', + p3: 'Biographies of the Secretaries of State', + p4: 'Principal Officers and Chiefs of Mission', + p5: 'Travels Abroad of the Secretary of State', + p6: 'Travels Abroad of the President', + p7: 'Visits by Foreign Leaders', + p8: 'World War I and the Department', + p9: 'Buildings of the Department of State', + p10: 'U.S. Diplomatic Couriers' + } +} + +describe('Department History pages: ', function () { + // Subpage titles check + describe('Each "Department History" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p6) + }) + }) + + it('should display the headline "' + subpages.titles.p7 + '" ', function () { + cy.openPage(subpages.links.p7) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p7) + }) + }) + + it('should display the headline "' + subpages.titles.p8 + '" ', function () { + cy.openPage(subpages.links.p8) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p8) + }) + }) + + it('should display the headline "' + subpages.titles.p9 + '" ', function () { + cy.openPage(subpages.links.p9) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p9) + }) + }) + + it('should display the headline "' + subpages.titles.p10 + '" ', function () { + cy.openPage(subpages.links.p10) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p10) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/departmenthistory/uat_shorthistory_titles.cy.js b/tests/cypress/e2e/departmenthistory/uat_shorthistory_titles.cy.js new file mode 100644 index 00000000..c7137dc1 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/uat_shorthistory_titles.cy.js @@ -0,0 +1,42 @@ +/** + * Checks departmenthistory short-history page type + */ + +const subpages = { + links: { + p1: 'departmenthistory/short-history', + p2: 'departmenthistory/short-history/foundations', + p3: 'departmenthistory/short-history/origins' + }, + titles: { + p1: 'A Short History of the Department of State', + p2: 'Foundations of Foreign Affairs, 1775-1823', + p3: 'Origins of a Diplomatic Tradition' + } +} + +describe('Short-history pages: ', function () { + // Subpage titles check + describe('Each "Short-history" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH3().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH2().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/developer/prod_developer_titles.cy.js b/tests/cypress/e2e/developer/prod_developer_titles.cy.js new file mode 100644 index 00000000..897e7fa7 --- /dev/null +++ b/tests/cypress/e2e/developer/prod_developer_titles.cy.js @@ -0,0 +1,26 @@ +/** + * Checks if developer pages have the correct titles + */ + +const subpages = [ + { name: 'p1', link: 'developer', title: 'Developer Resources' }, + { + name: 'p2', + link: 'developer/catalog', + title: 'Office of the Historian Ebook Catalog API' + } +] + +describe('Developer pages: ', function () { + // Subpage titles check + describe('Each "Developer" subpage should be displayed and subsequently', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/developer/uat_developer_titles.cy.js b/tests/cypress/e2e/developer/uat_developer_titles.cy.js new file mode 100644 index 00000000..897e7fa7 --- /dev/null +++ b/tests/cypress/e2e/developer/uat_developer_titles.cy.js @@ -0,0 +1,26 @@ +/** + * Checks if developer pages have the correct titles + */ + +const subpages = [ + { name: 'p1', link: 'developer', title: 'Developer Resources' }, + { + name: 'p2', + link: 'developer/catalog', + title: 'Office of the Historian Ebook Catalog API' + } +] + +describe('Developer pages: ', function () { + // Subpage titles check + describe('Each "Developer" subpage should be displayed and subsequently', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/education/prod_education_titles.cy.js b/tests/cypress/e2e/education/prod_education_titles.cy.js new file mode 100644 index 00000000..3371904e --- /dev/null +++ b/tests/cypress/e2e/education/prod_education_titles.cy.js @@ -0,0 +1,76 @@ +/** + * Checks if education pages have the correct titles + */ + +const pages = [ + { name: 'p1', link: 'education', title: 'Education' }, + { + name: 'p2', + link: 'education/modules', + title: 'Curriculum Modules' + } +] + +const subpages = [ + { + name: 'p3', + link: 'education/modules/documents-intro', + title: 'Introduction to Curriculum Packet on "Documents on Diplomacy: Primary Source Documents and Lessons from the World of Foreign Affairs, 1775-2011"' + }, + { + name: 'p4', + link: 'education/modules/border-vanishes-intro', + title: 'Introduction to Curriculum Packet on "When the Border Vanishes: Diplomacy and the Threat to our Health and Environment"' + }, + { + name: 'p5', + link: 'education/modules/media-intro', + title: 'Introduction to Curriculum Packet on "Today in Washington: The Media and Diplomacy"' + }, + { + name: 'p6', + link: 'education/modules/journey-shared-intro', + title: 'Introduction to Curriculum Packet on "A Journey Shared: The United States and China"' + }, + { + name: 'p7', + link: 'education/modules/sports-intro', + title: 'Introduction to Curriculum Packet on "Sports and Diplomacy in the Global Arena"' + }, + { + name: 'p8', + link: 'education/modules/history-diplomacy-intro', + title: 'Introduction to Curriculum Packet on "A History of Diplomacy"' + }, + { + name: 'p9', + link: 'education/modules/terrorism-intro', + title: 'Introduction to Curriculum Packet on "Terrorism: A War Without Borders"' + } +] + +describe('Education pages: ', function () { + // page titles check + describe('Each "Education" page should be displayed and subsequently', function () { + pages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) + // Subpage titles check + describe('Each "Education" subpage should be displayed and subsequently', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + // SubPage.headline_h2 would select the title of the red alert box + cy.get('#content-inner div:nth-child(2) h2').invoke('text').then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/education/uat_education_titles.cy.js b/tests/cypress/e2e/education/uat_education_titles.cy.js new file mode 100644 index 00000000..3cd5d061 --- /dev/null +++ b/tests/cypress/e2e/education/uat_education_titles.cy.js @@ -0,0 +1,96 @@ +/** + * Checks if education pages have the correct titles + */ + +const subpages = { + links: { + p1: 'education', // 1st level subpage (landing) + p2: 'education/modules', // 2nd level sub page and modules landing page + p3: 'education/modules/documents-intro', // 3rd level sub page (1. module detail) + p4: 'education/modules/border-vanishes-intro', // 3nd level sub page (2. module detail, PDF landing) TODO: Check PDF download + p5: 'education/modules/media-intro', // 3nd level sub page (3. module detail) TODO: Check PDF download + p6: 'education/modules/journey-shared-intro', // 3nd level sub page (3. module detail) TODO: Check PDF download + p7: 'education/modules/sports-intro', // 3nd level sub page (3. module detail) TODO: Check PDF download + p8: 'education/modules/history-diplomacy-intro', // 3nd level sub page (3. module detail) TODO: Check PDF download + p9: 'education/modules/terrorism-intro' // 3nd level sub page (3. module detail) TODO: Check PDF download + }, + titles: { + p1: 'Education', // h1 + p2: 'Curriculum Modules', // h1 + p3: 'Introduction', // h1 + p4: 'Introduction', // h1 + p5: 'Introduction', // h1 + p6: 'Introduction', // h1 + p7: 'Introduction', // h1 + p8: 'Introduction', // h1 + p9: 'Introduction' // h1 + } +} + +describe('Education pages: ', function () { + // Subpage titles check + describe('Each "Education" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p6) + }) + }) + + it('should display the headline "' + subpages.titles.p7 + '" ', function () { + cy.openPage(subpages.links.p7) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p7) + }) + }) + + it('should display the headline "' + subpages.titles.p8 + '" ', function () { + cy.openPage(subpages.links.p8) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p8) + }) + }) + + it('should display the headline "' + subpages.titles.p9 + '" ', function () { + cy.openPage(subpages.links.p9) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p9) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/error/prod_404.cy.js b/tests/cypress/e2e/error/prod_404.cy.js new file mode 100644 index 00000000..87d51a2a --- /dev/null +++ b/tests/cypress/e2e/error/prod_404.cy.js @@ -0,0 +1,10 @@ +/** + * Checks 404 error page + */ + +describe('Requesting a non existing page', () => { + it('should redirect to the 404 error page', () => { + cy.openPage('asdfg') + cy.title().should('include', 'Page not found - Office of the Historian') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/error/uat_404.cy.js b/tests/cypress/e2e/error/uat_404.cy.js new file mode 100644 index 00000000..707bc11a --- /dev/null +++ b/tests/cypress/e2e/error/uat_404.cy.js @@ -0,0 +1,10 @@ +/** + * Checks 404 error page + */ + +describe('Requesting a non existing page', () => { + it('should redirect to the 404 error page', () => { + cy.openPage('asdfg') + cy.title().should('include', 'An error has occurred - Office of the Historian') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/footnote/prod_footnote_popover.cy.js b/tests/cypress/e2e/footnote/prod_footnote_popover.cy.js new file mode 100644 index 00000000..9d389140 --- /dev/null +++ b/tests/cypress/e2e/footnote/prod_footnote_popover.cy.js @@ -0,0 +1,226 @@ +/** + * Checks footnote popover + */ + +function escape (value) { + return value.replace(/([\.:])/g, '\\$1') +} + +describe('footnote popover', function () { + describe('footnote popover look and behavior on desktop', function () { + beforeEach(function () { + cy.openPage('historicaldocuments/frus-history/introduction') + cy.window().then((win) => { + if (win.$) { + win.$('#touch-detector').hide() + } else { + // Fallback if jQuery not available + cy.get('#touch-detector').invoke('css', 'display', 'none') + } + }) + }) + + it('should have a footnote', function () { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').then(($footnoteLink) => { + expect($footnoteLink.text()).to.equal('1') + const href = $footnoteLink.attr('href') + cy.get(escape(href)).then(($footnote) => { + expect($footnote.attr('value')).to.equal('1') + expect($footnote.attr('class')).to.include('footnote') + }) + }) + }) + + it('footnote popover should appear on hover', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should not have the "back" link', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.get('.popover .footnote-body a.fn-back').should('exist') + cy.get('.popover .footnote-body a.fn-back').should('not.be.visible') + }) + + it('footnote popover should not disappear with the cursor on it', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.get('.popover').trigger('mouseenter') + cy.wait(1000) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should disappear when the cursor leaves', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('body').trigger('mouseenter', { x: 100, y: 100 }) + cy.wait(1000) + cy.get('.popover').should('not.be.visible') + }) + + it('footnote popover should not disappear when the cursor leaves for a brief moment', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('body').trigger('mouseenter', { x: 100, y: 100 }) + cy.wait(200) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.wait(1000) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should disappear when the user clicks outside', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('body').click(100, 100) + cy.wait(200) + cy.get('.popover').should('not.be.visible') + }) + + it('footnote popover should not disappear when the user clicks on it', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('.popover').click() + cy.wait(200) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should disappear when another one appears', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').should('have.length.at.least', 2) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').first().scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').first().trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.get('.popover').invoke('text').then((popoverText1) => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').eq(1).scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').eq(1).trigger('mouseenter') + cy.wait(100) + cy.get('.popover').should('be.visible') + cy.get('.popover').invoke('text').then((popoverText2) => { + expect(popoverText2).to.not.equal(popoverText1) + }) + }) + }) + + it('footnote popover should disappear when the user clicks on its link', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter') + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('.popover').should('not.be.visible') + }) + + it('page should scroll to a footnote when the user clicks on its link', function () { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').then(($footnoteLink) => { + const href = $footnoteLink.attr('href') + cy.get(escape(href)).then(($footnote) => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.isVisibleWithinViewport(escape(href)).then((isVisible) => { + expect(isVisible).to.be.false + }) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.isVisibleWithinViewport(escape(href)).then((isVisible) => { + expect(isVisible).to.be.true + }) + }) + }) + }) + }) + + describe('footnote popover look and behavior on touch devices', function () { + beforeEach(function () { + cy.openPage('historicaldocuments/frus-history/introduction') + cy.window().then((win) => { + if (win.$) { + win.$('#touch-detector').show() + } else { + // Fallback if jQuery not available + cy.get('#touch-detector').invoke('css', 'display', 'block') + } + }) + }) + + it('footnote popover should appear on tap', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + }) + + it('footnote popover should not have the "back" link', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-body #footnote a.fn-back').should('exist') + cy.get('#footnote-modal .modal-body #footnote a.fn-back').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps outside of it', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('body').click(5, 5) + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps on the close button', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-header button.close').click() + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps on "View footnotes"', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-body #link a').click() + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + + it('page should scroll to the footnotes section when the user taps on "View footnotes"', function () { + cy.get('.footnotes').then(($footnote) => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.isVisibleWithinViewport('.footnotes').then((isVisible) => { + expect(isVisible).to.be.false + }) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('#footnote-modal .modal-body #link a').click() + cy.isVisibleWithinViewport('.footnotes').then((isVisible) => { + expect(isVisible).to.be.true + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/footnote/uat_footnote_popover.cy.js b/tests/cypress/e2e/footnote/uat_footnote_popover.cy.js new file mode 100644 index 00000000..807fe612 --- /dev/null +++ b/tests/cypress/e2e/footnote/uat_footnote_popover.cy.js @@ -0,0 +1,232 @@ +/** + * Checks footnote popover + */ + +function escape (value) { + return value.replace(/([\.:])/g, '\\$1') +} + +describe('footnote popover', function () { + describe('footnote popover looks and behavior on desktop', function () { + beforeEach(function () { + cy.openPage('historicaldocuments/frus-history/introduction') + cy.window().then((win) => { + win.$('#touch-detector').hide() + }) + }) + + it('should have a footnote', function () { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').then(($footnoteLink) => { + expect($footnoteLink.text()).to.equal('1') + const href = $footnoteLink.attr('href') + cy.get(escape(href)).then(($footnote) => { + expect($footnote.attr('value')).to.equal('1') + expect($footnote.attr('class')).to.include('footnote') + }) + }) + }) + + it('footnote popover should appear on hover', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(2000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.wait(2000) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should not have the "back" link', function () { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.get('.popover').should('not.be.visible') + cy.wait(2000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.wait(2000) + cy.get('.popover').should('be.visible') + cy.get('.popover .footnote-body a.fn-back').should('not.be.visible') + }) + + it('footnote popover should not disappear with the cursor on it', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(2000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.wait(2000) + cy.get('.popover').should('be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mousemove', { offsetX: 1, offsetY: 10 }) + cy.wait(2000) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should disappear when the cursor leaves', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(2000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseleave') + cy.wait(2000) + cy.get('.popover').should('not.be.visible') + }) + + it('footnote popover should not disappear when the cursor leaves for a brief moment', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseleave') + cy.wait(200) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.wait(1000) + cy.get('.popover').should('be.visible') + }) + + it('footnote popover should disappear when the user clicks outside', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.wait(1000) + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('body').click(100, 100) + cy.wait(200) + cy.get('.popover').should('not.be.visible') + }) + + it.skip('footnote popover should not disappear when the user clicks on it', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.get('.popover').should('be.visible') + cy.wait(1000) + cy.get('.popover').click() + cy.wait(1000) + cy.get('.popover').should('be.visible') + }) + + it.skip('footnote popover should disappear when another one appears', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').should('have.length.at.least', 2) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').first().scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').first().trigger('mouseenter', { force: true }) + cy.get('.popover').should('be.visible') + cy.get('.popover').invoke('text').then((popoverText1) => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').eq(1).scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').eq(1).trigger('mouseenter', { force: true }) + cy.wait(100) + cy.get('.popover').should('be.visible') + cy.get('.popover').invoke('text').then((popoverText2) => { + expect(popoverText2).to.not.equal(popoverText1) + }) + }) + }) + + it.skip('footnote popover should disappear when the user clicks on its link', function () { + cy.get('.popover').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').trigger('mouseenter', { force: true }) + cy.get('.popover').should('be.visible') + cy.wait(100) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('.popover').should('not.be.visible') + }) + + it('page should scroll to a footnote when the user clicks on its link', function () { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').then(($footnoteLink) => { + const href = $footnoteLink.attr('href') + cy.get(escape(href)).then(() => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }) + cy.wait(1000) + cy.isVisibleWithinViewport(escape(href)).then((isVisible) => { + expect(isVisible).to.be.false + }) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.isVisibleWithinViewport(escape(href)).then((isVisible) => { + expect(isVisible).to.be.true + }) + }) + }) + }) + }) + + describe('footnote popover looks and behavior on touch devices', function () { + beforeEach(function () { + cy.openPage('historicaldocuments/frus-history/introduction') + cy.window().then((win) => { + win.$('#touch-detector').show() + }) + }) + + it('footnote popover should appear on tap', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + }) + + it('footnote popover should not have the "back" link', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-body #footnote a.fn-back').should('exist') + cy.get('#footnote-modal .modal-body #footnote a.fn-back').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps outside of it', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('body').click(5, 5) + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps on the close button', function () { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-header button.close').click() + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + + it('footnote popover should disappear when the user taps on "View footnotes"', function () { + cy.get('.footnotes').then(() => { + cy.get('#footnote-modal').should('not.be.visible') + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('#footnote-modal').should('be.visible') + cy.get('#footnote-modal .modal-body #link a').click() + cy.wait(200) + cy.get('#footnote-modal').should('not.be.visible') + }) + }) + + it('page should scroll to the footnotes section when the user taps on "View footnotes"', function () { + cy.get('.footnotes').then(() => { + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').scrollIntoView() + cy.isVisibleWithinViewport('.footnotes').then((isVisible) => { + expect(isVisible).to.be.false + }) + cy.get('#content-inner a.note[href^="#fn\\:"][rel=footnote]').click() + cy.wait(200) + cy.get('#footnote-modal .modal-body #link a').click() + cy.isVisibleWithinViewport('.footnotes').then((isVisible) => { + expect(isVisible).to.be.true + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/prod_frus-all-volumes.cy.js b/tests/cypress/e2e/historical-documents/prod_frus-all-volumes.cy.js new file mode 100644 index 00000000..d4eaa398 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/prod_frus-all-volumes.cy.js @@ -0,0 +1,81 @@ +/** + * Checks all frus all volumes + */ + +const titles = [ + 'Message of the President of the United States to the Two Houses of Congress, at the Commencement of the Second Session of the Thirty-seventh Congress', + 'General Index to the Published Volumes of the Diplomatic Correspondence and Foreign Relations of the United States, 1861–1899', + 'Papers Relating to Foreign Affairs, Accompanying the Annual Message of the President to the Third Session Thirty-seventh Congress' +] + +const links = [ + 'historicaldocuments/frus1861', + '/historicaldocuments/frus1861-99Index', + 'historicaldocuments/frus1862' +] + +describe('FRUS "All Volumes" page', () => { + before(() => { + cy.openPage('historicaldocuments/volume-titles') + cy.wait(500) + }) + + it('should display a title', () => { + cy.getElementText('h1').then((title) => { + expect(title).to.equal('All Titles in the Foreign Relations Series') + }) + }) + + it.skip('should display a sidebar with citation option', () => { + cy.get('hsg-cite__button--sidebar').should('exist') + }) + + it('should display a list containing a thumbnail', () => { + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(1) img', 'src').then((t_0) => { + expect(t_0).to.include('https://static.history.state.gov/images/document-image.jpg') + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(2) img', 'src').then((t_1) => { + expect(t_1).to.include('https://static.history.state.gov/images/document-image.jpg') + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(3) img', 'src').then((t_2) => { + expect(t_2).to.include('https://static.history.state.gov/images/document-image.jpg') + }) + }) + + it('should display a list containing a title', () => { + cy.getElementText('ul.hsg-list__volumes li:nth-child(1) h3 a').then((title_0) => { + expect(title_0).to.equal(titles[0]) + }) + cy.getElementText('ul.hsg-list__volumes li:nth-child(2) h3 a').then((title_1) => { + expect(title_1).to.equal(titles[1]) + }) + cy.getElementText('ul.hsg-list__volumes li:nth-child(3) h3 a').then((title_2) => { + expect(title_2).to.equal(titles[2]) + }) + }) + + it('should display a list containing a link to the volume', () => { + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(1) h3 a', 'href').then((link_0) => { + expect(link_0).to.include(links[0]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(2) h3 a', 'href').then((link_1) => { + expect(link_1).to.include(links[1]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(3) h3 a', 'href').then((link_2) => { + expect(link_2).to.include(links[2]) + }) + }) + + it('should display a list containing a published status and date, if available', () => { + cy.getElementText('ul.hsg-list__volumes li:nth-child(1) dl dd:nth-of-type(1)').then((publishedDate_0) => { + expect(publishedDate_0).to.include('1861') + }) + }) + + // Download does not seem to exist anymore + // it('should display a list containing download buttons, if available', () => { + // cy.getElementText('ul.hsg-list__volumes li:nth-child(1) ul.hsg-list__media__download > li > button span').then((dl) => { + // expect(dl).to.exist + // }) + // }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/prod_frus-volume-landing.cy.js b/tests/cypress/e2e/historical-documents/prod_frus-volume-landing.cy.js new file mode 100644 index 00000000..5732789d --- /dev/null +++ b/tests/cypress/e2e/historical-documents/prod_frus-volume-landing.cy.js @@ -0,0 +1,57 @@ +/** + * Checks the cover image of a volume landing page + */ + +const s3_Prod = 'https://static.history.state.gov' + +describe('Volume landing page frus1951-54IranEd2 with a cover image', () => { + before(() => { + cy.openPage('historicaldocuments/frus1951-54IranEd2') + }) + + it('should display a cover image loaded from S3 production bucket', () => { + cy.getElementAttribute('#volume #content-inner > img', 'src').then((src) => { + expect(src).to.equal(s3_Prod + '/frus/frus1951-54IranEd2/covers/frus1951-54IranEd2.jpg') + }) + }) + + it('should display a cover image with an alt text attribute', () => { + cy.getElementAttribute('#volume img', 'alt').then((alt) => { + expect(alt).to.equal('Book Cover of Foreign Relations of the United States, 1952–1954, Iran, 1951–1954, Second Edition') + }) + }) + + it('should display a h1 heading before the image', () => { + cy.getElementText('#volume #content-inner > h1').then((title) => { + expect(title).to.equal('Foreign Relations of the United States, 1952–1954, Iran, 1951–1954, Second Edition', 'No h1 rendered') + }) + }) + + it('should NOT display a h1 heading generated from TEI', () => { + cy.getCssProperty('#volume .content h1', 'display').then((teiHeading) => { + expect(teiHeading.value).to.equal('none', 'TEI heading is displayed') + }) + }) +}) + +describe('Volume landing page "frus1861-99Index" without a cover image', () => { + before(() => { + cy.openPage('historicaldocuments/frus1861-99Index') + }) + + it('should NOT display a cover image', () => { + cy.get('#volume #content-inner > img').should('not.exist') + }) + + it('should display a h1 heading before the image', () => { + cy.getElementText('#volume #content-inner > h1').then((title) => { + expect(title).to.equal('General Index to the Published Volumes of the Diplomatic Correspondence and Foreign Relations of the United States, 1861–1899', 'No h1 rendered') + }) + }) + + it('should NOT display a h1 heading generated from TEI', () => { + cy.getCssProperty('#volume .content h1', 'display').then((teiHeading) => { + expect(teiHeading.value).to.equal('none', 'TEI heading is displayed') + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/prod_frus_landing.cy.js b/tests/cypress/e2e/historical-documents/prod_frus_landing.cy.js new file mode 100644 index 00000000..5363c2fd --- /dev/null +++ b/tests/cypress/e2e/historical-documents/prod_frus_landing.cy.js @@ -0,0 +1,28 @@ +/** + * Checks all frus subpage titles + * and the functionality of the dropdown menu + */ + +const s3_Prod = 'https://static.history.state.gov' + +const images = [ + s3_Prod + '/images/alincoln.jpg', + s3_Prod + '/images/ajohnson.jpg', + s3_Prod + '/images/usgrant.jpg' +] + +describe('FRUS landing page: The first 3 tiles', function () { + before(function () { + cy.openPage('historicaldocuments') + }) + + images.forEach(function (image, index) { + describe('Each tile on the landing page', function () { + it('should display an image', function () { + cy.getElementAttribute('#content-inner div article:nth-child(' + (index + 1) + ') a img', 'src').then((imgSrc) => { + expect(imgSrc).to.include(image) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/prod_frus_titles.cy.js b/tests/cypress/e2e/historical-documents/prod_frus_titles.cy.js new file mode 100644 index 00000000..fa85d1d1 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/prod_frus_titles.cy.js @@ -0,0 +1,82 @@ +/** + * Checks all frus subpage titles + * and the functionality of the dropdown menu + */ + +const mainpage = { + name: 'p1', + link: 'historicaldocuments', + title: 'Historical Documents' +} + +const subpages = [ + { + name: 'p2', + link: 'historicaldocuments/about-frus', + title: 'About the Foreign Relations of the United States Series', + level: 'h1' + }, + { + name: 'p3', + link: 'historicaldocuments/status-of-the-series', + title: 'Status of the Foreign Relations of the United States Series', + level: 'h1' + }, + { + name: 'p4', + link: 'historicaldocuments/frus-history', + title: '', + level: 'h1' + }, + { + name: 'p5', + link: 'historicaldocuments/ebooks', + title: 'Ebooks', + level: 'h2' + }, + { + name: 'p6', + link: 'historicaldocuments/quarterly-releases', + title: 'Quarterly Releases', + level: 'h2' + }, + { + name: 'p7', + link: 'historicaldocuments/citing-frus', + title: 'Citing the Foreign Relations series', + level: 'h1' + } +] + +describe('FRUS pages: ', function () { + before(function () { + cy.openPage('historicaldocuments') + }) + + // Dropdown check + describe('Checking the dropdown menu: Clicking the first dropdown item', function () { + before(function () { + cy.get('ul.nav.navbar-nav li:nth-child(2) > a').click() + cy.get('ul.dropdown-menu li:nth-child(2)').should('be.visible') + cy.get('ul.dropdown-menu li:nth-child(1) a').click() + }) + + it('should open the FRUS landing page with headline', function () { + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(mainpage.title) + }) + }) + }) + + // Subpage titles check + describe('Each FRUS subpage should be displayed and subsequently', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.get('#content-inner ' + page.level).invoke('text').then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/prod_frus_toc.cy.js b/tests/cypress/e2e/historical-documents/prod_frus_toc.cy.js new file mode 100644 index 00000000..5ca1b8f8 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/prod_frus_toc.cy.js @@ -0,0 +1,16 @@ +/** + * Checks the cover image of a volume landing page + */ + +describe('The TOC of a volume', () => { + before(() => { + cy.openPage('historicaldocuments/frus1947v03/comp1') + }) + + it('should highlight the current chapter', () => { + cy.getCssProperty('a.hsg-current[href*="historicaldocuments/frus1947v03/comp1"]', 'color').then((currentLink) => { + const color = currentLink.parsed.hex + expect(color).to.equal('#205493') + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/uat_frus-all-volumes.cy.js b/tests/cypress/e2e/historical-documents/uat_frus-all-volumes.cy.js new file mode 100644 index 00000000..b7e46f00 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/uat_frus-all-volumes.cy.js @@ -0,0 +1,92 @@ +/** + * Checks all frus all volumes + */ + +const s3_UAT = 'https://static.test.history.state.gov' + +const images = [ + s3_UAT + '/frus/frus1861/covers/frus1861.jpg', + s3_UAT + '/frus/frus1861-99Index/covers/frus1861-99Index.jpg', + s3_UAT + '/frus/frus1862/covers/frus1862.jpg' +] + +const titles = [ + 'Message of the President of the United States to the Two Houses of Congress, at the Commencement of the Second Session of the Thirty-seventh Congress', + 'General Index to the Published Volumes of the Diplomatic Correspondence and Foreign Relations of the United States, 1861–1899', + 'Papers Relating to Foreign Affairs, Accompanying the Annual Message of the President to the Third Session Thirty-seventh Congress' +] + +const links = [ + 'historicaldocuments/frus1861', + '/historicaldocuments/frus1861-99Index', + 'historicaldocuments/frus1862' +] + +const publishedDates = [ + 'Published on May 24, 2021' +] + +describe('FRUS "All Volumes" page', () => { + before(() => { + cy.openPage('historicaldocuments/volume-titles') + cy.wait(500) + }) + + it('should display a title', () => { + cy.getElementText('h1').then((title) => { + expect(title).to.equal('All Titles in the Series') + }) + }) + + it('should display a sidebar with citation option', () => { + cy.get('hsg-cite__button--sidebar').should('exist') + }) + + it('should display a list containing a thumbnail', () => { + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(1) img', 'src').then((t_0) => { + expect(t_0).to.include(images[0]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(2) img', 'src').then((t_1) => { + expect(t_1).to.include(images[1]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(3) img', 'src').then((t_2) => { + expect(t_2).to.include(images[2]) + }) + }) + + it('should display a list containing a title', () => { + cy.getElementText('ul.hsg-list__volumes li:nth-child(1) h3 a').then((title_0) => { + expect(title_0).to.equal(titles[0]) + }) + cy.getElementText('ul.hsg-list__volumes li:nth-child(2) h3 a').then((title_1) => { + expect(title_1).to.equal(titles[1]) + }) + cy.getElementText('ul.hsg-list__volumes li:nth-child(3) h3 a').then((title_2) => { + expect(title_2).to.equal(titles[2]) + }) + }) + + it('should display a list containing a link to the volume', () => { + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(1) h3 a', 'href').then((link_0) => { + expect(link_0).to.include(links[0]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(2) h3 a', 'href').then((link_1) => { + expect(link_1).to.include(links[1]) + }) + cy.getElementAttribute('ul.hsg-list__volumes li:nth-child(3) h3 a', 'href').then((link_2) => { + expect(link_2).to.include(links[2]) + }) + }) + + it('should display a list containing a published status and date, if available', () => { + cy.getElementText('ul.hsg-list__volumes li:nth-child(1) dl dd:nth-of-type(1)').then((publishedDate_0) => { + expect(publishedDate_0).to.include(publishedDates[0]) + }) + }) + + it('should display a list containing download buttons, if available', () => { + cy.getElementText('ul.hsg-list__volumes li:nth-child(1) ul.hsg-list__media__download > li > button span').then((dl) => { + expect(dl).to.exist + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/uat_frus-volume-landing.cy.js b/tests/cypress/e2e/historical-documents/uat_frus-volume-landing.cy.js new file mode 100644 index 00000000..7e15019c --- /dev/null +++ b/tests/cypress/e2e/historical-documents/uat_frus-volume-landing.cy.js @@ -0,0 +1,57 @@ +/** + * Checks the cover image of a volume landing page + */ + +const s3_UAT = 'https://static.test.history.state.gov' + +describe('Volume landing page frus1951-54IranEd2 with a cover image', () => { + before(() => { + cy.openPage('historicaldocuments/frus1951-54IranEd2') + }) + + it('should display an cover image loaded from S3 test bucket', () => { + cy.getElementAttribute('#volume #content-inner > img', 'src').then((src) => { + expect(src).to.equal(s3_UAT + '/frus/frus1951-54IranEd2/covers/frus1951-54IranEd2.jpg') + }) + }) + + it('should display an cover image with an alt text attribute', () => { + cy.getElementAttribute('#volume img', 'alt').then((alt) => { + expect(alt).to.equal('Book Cover of Foreign Relations of the United States, 1952-1954, Iran, 1951–1954, Second Edition') + }) + }) + + it('should display a h1 heading before the image', () => { + cy.getElementText('#volume #content-inner > h1').then((title) => { + expect(title).to.equal('Foreign Relations of the United States, 1952-1954, Iran, 1951–1954, Second Edition', 'No h1 rendered') + }) + }) + + it('should NOT display a h1 heading generated from TEI', () => { + cy.getCssProperty('#volume .content h1', 'display').then((teiHeading) => { + expect(teiHeading.value).to.equal('none', 'TEI heading is displayed') + }) + }) +}) + +describe('Volume landing page "frus1861-99Index" without a cover image', () => { + before(() => { + cy.openPage('historicaldocuments/frus1861-99Index') + }) + + it('should NOT display an cover image', () => { + cy.get('#volume #content-inner > img').should('not.exist') + }) + + it('should display a h1 heading before the image', () => { + cy.getElementText('#volume #content-inner > h1').then((title) => { + expect(title).to.equal('General Index to the Published Volumes of the Diplomatic Correspondence and Foreign Relations of the United States, 1861–1899', 'No h1 rendered') + }) + }) + + it('should NOT display a h1 heading generated from TEI', () => { + cy.getCssProperty('#volume .content h1', 'display').then((teiHeading) => { + expect(teiHeading.value).to.equal('none', 'TEI heading is displayed') + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/uat_frus_landing.cy.js b/tests/cypress/e2e/historical-documents/uat_frus_landing.cy.js new file mode 100644 index 00000000..445c8f38 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/uat_frus_landing.cy.js @@ -0,0 +1,30 @@ +/** + * Checks all frus subpage titles + * and the functionality of the dropdown menu + */ + +const s3_UAT = 'https://static.test.history.state.gov' + +const images = [ + s3_UAT + '/images/alincoln.jpg', + s3_UAT + '/images/ajohnson.jpg', + s3_UAT + '/images/usgrant.jpg' +] + +describe('FRUS landing page: The first 3 tiles', function () { + before(function () { + cy.openPage('historicaldocuments') + }) + + it('should each contain an image', function () { + cy.getElementAttribute('#content-inner div article:nth-child(1) a img', 'src').then((tile0) => { + expect(tile0).to.include(images[0]) + }) + cy.getElementAttribute('#content-inner div article:nth-child(2) a img', 'src').then((tile1) => { + expect(tile1).to.include(images[1]) + }) + cy.getElementAttribute('#content-inner div article:nth-child(3) a img', 'src').then((tile2) => { + expect(tile2).to.include(images[2]) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/historical-documents/uat_frus_titles.cy.js b/tests/cypress/e2e/historical-documents/uat_frus_titles.cy.js new file mode 100644 index 00000000..49336f62 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/uat_frus_titles.cy.js @@ -0,0 +1,99 @@ +/** + * Checks all frus subpage titles + * and the functionality of the dropdown menu + */ + +const subpages = { + titles: { + p1: 'Historical Documents', + p2: 'About the Foreign Relations of the United States Series', + p3: 'Status of the Foreign Relations of the United States Series', + p4: '', // h1 currently is empty - only a subtitle h2 is present + p5: 'Ebooks', + p6: 'Quarterly Releases', + p7: 'Citing the Foreign Relations series' // pagelink is hidden in sidebar! + }, + links: { + p1: 'historicaldocuments', + p2: 'historicaldocuments/about-frus', + p3: 'historicaldocuments/status-of-the-series', + p4: 'historicaldocuments/frus-history', + p5: 'historicaldocuments/ebooks', + p6: 'historicaldocuments/quarterly-releases', + p7: 'historicaldocuments/citing-frus' // pagelink is hidden in sidebar! + } +} + +describe('FRUS pages: ', function () { + before(function () { + cy.openPage('historicaldocuments') + }) + + // Dropdown check + describe('Checking the dropdown menu: Clicking the first dropdown item', function () { + before(function () { + cy.get('ul.nav.navbar-nav li:nth-child(2) > a').click() + cy.waitForVisible('ul.dropdown-menu li:nth-child(2)', 300) + cy.get('ul.dropdown-menu li:nth-child(1) a').click() + }) + + it('should open the FRUS landing page with headline "' + subpages.titles.p1 + '" ', function () { + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + }) + + // Subpage titles check + describe('Each FRUS subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" (h1 is currently empty) ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p4) + }) + }) + + it('should display the headline "' + subpages.titles.p5 + '" ', function () { + cy.openPage(subpages.links.p5) + cy.getHeadlineH2().then((title) => { + expect(title).to.equal(subpages.titles.p5) + }) + }) + + it('should display the headline "' + subpages.titles.p6 + '" ', function () { + cy.openPage(subpages.links.p6) + cy.getHeadlineH2().then((title) => { + expect(title).to.equal(subpages.titles.p6) + }) + }) + + // pagelink is hidden in sidebar! + it('should display the headline "' + subpages.titles.p7 + '" ', function () { + cy.openPage(subpages.links.p7) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p7) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/iiif-images/prod_iiif-viewer.cy.js b/tests/cypress/e2e/iiif-images/prod_iiif-viewer.cy.js new file mode 100644 index 00000000..86616ac0 --- /dev/null +++ b/tests/cypress/e2e/iiif-images/prod_iiif-viewer.cy.js @@ -0,0 +1,27 @@ +/** + * Checks "IIIF image viewer" + * Current implementation: https://openseadragon.github.io + * Needs a running local IIIF image server! + * + */ + +const p1 = 'historicaldocuments/frus1902app1/pg_11' +const p2 = 'historicaldocuments/frus1902app1/pg_12' +const p3 = 'historicaldocuments/frus1902app1/pg_13' +const i1 = 'iiif/3/frus1902app1%2Ftiff%2F0021.tif' +const i2 = 'iiif/3/frus1902app1%2Ftiff%2F0021.tif' +const i3 = 'iiif/3/frus1902app1%2Ftiff%2F0021.tif' + +// TODO: Catch Cantaloupe server response for requesting tif files +// TODO: Catch server response when browsing with side navigation, if correct images are served + +describe('Requesting images from an external source (S3) via a IIIF server', () => { + before(() => { + cy.openPage(p1) + cy.wait(500) + }) + + it('should be displayed in a IIIF viewer', () => { + cy.get('.openseadragon-canvas > canvas').should('exist') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/landing/prod_landing_title.cy.js b/tests/cypress/e2e/landing/prod_landing_title.cy.js new file mode 100644 index 00000000..fa4b87d5 --- /dev/null +++ b/tests/cypress/e2e/landing/prod_landing_title.cy.js @@ -0,0 +1,10 @@ +/** + * Checks if landing page has the correct title + */ + +describe('HSG landing page', function () { + it('should have the correct title', function () { + cy.openPage() + cy.title().should('include', 'Office of the Historian') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/landing/prod_landing_twitter.cy.js b/tests/cypress/e2e/landing/prod_landing_twitter.cy.js new file mode 100644 index 00000000..4351f890 --- /dev/null +++ b/tests/cypress/e2e/landing/prod_landing_twitter.cy.js @@ -0,0 +1,10 @@ +/** + * Checks if twitter module is displaying tweets on landing page + */ + +describe('The twitter section on the landing page', function () { + it('should display at least one twitter post', function () { + cy.openPage() + cy.get('post-list .post:last-child p').should('exist') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/landing/uat_landing_title.cy.js b/tests/cypress/e2e/landing/uat_landing_title.cy.js new file mode 100644 index 00000000..92901763 --- /dev/null +++ b/tests/cypress/e2e/landing/uat_landing_title.cy.js @@ -0,0 +1,10 @@ +/** + * Checks if landing page has the correct title + */ + +describe('HSG landing page', function () { + it('should have the correct title', function () { + cy.openPage() + cy.title().should('include', 'Latest News - Office of the Historian') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/landing/uat_landing_twitter.cy.js b/tests/cypress/e2e/landing/uat_landing_twitter.cy.js new file mode 100644 index 00000000..4351f890 --- /dev/null +++ b/tests/cypress/e2e/landing/uat_landing_twitter.cy.js @@ -0,0 +1,10 @@ +/** + * Checks if twitter module is displaying tweets on landing page + */ + +describe('The twitter section on the landing page', function () { + it('should display at least one twitter post', function () { + cy.openPage() + cy.get('post-list .post:last-child p').should('exist') + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/milestones/prod_milestones_chapter.cy.js b/tests/cypress/e2e/milestones/prod_milestones_chapter.cy.js new file mode 100644 index 00000000..55cb0fff --- /dev/null +++ b/tests/cypress/e2e/milestones/prod_milestones_chapter.cy.js @@ -0,0 +1,15 @@ +/** + * Checks milestones chapter pages + */ + +const red = 'rgba(169,68,66,1)' + +describe('Milestones chapter- and their sub pages: ', function () { + it('should display a red alert note to readers', function () { + cy.openPage('milestones/1750-1775/parliamentary-taxation') + cy.get('#content-inner div.alert.alert-danger').should('exist') + cy.getCssProperty('#content-inner div.alert.alert-danger', 'color').then((textColor) => { + expect(textColor.value).to.equal(red) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/milestones/prod_milestones_titles.cy.js b/tests/cypress/e2e/milestones/prod_milestones_titles.cy.js new file mode 100644 index 00000000..da1bd242 --- /dev/null +++ b/tests/cypress/e2e/milestones/prod_milestones_titles.cy.js @@ -0,0 +1,44 @@ +/** + * Checks milestones pages + */ + +const mainpage = { + name: 'p1', + link: 'milestones', + title: 'Milestones in the History of U.S. Foreign Relations' +} + +const subpages = [ + { name: 'p2', link: 'milestones/all', title: 'All Milestones' }, + { + name: 'p3', + link: 'milestones/1750-1775', + title: 'Milestones in the History of U.S. Foreign Relations' + }, + { + name: 'p4', + link: 'milestones/1750-1775/foreword', + title: '1750–1775: Diplomatic Struggles in the Colonial Period' + } +] + +describe('on the Milestone page', function () { + it('should display the headline', function () { + cy.openPage(mainpage.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(mainpage.title) + }) + }) + + // Subpage titles check + describe('Each "Milestones" subpage', function () { + subpages.forEach(page => { + it('should display the headline (' + page.name + ')', function () { + cy.openPage(page.link) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(page.title) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/milestones/uat_milestones_chapter.cy.js b/tests/cypress/e2e/milestones/uat_milestones_chapter.cy.js new file mode 100644 index 00000000..ea31330d --- /dev/null +++ b/tests/cypress/e2e/milestones/uat_milestones_chapter.cy.js @@ -0,0 +1,15 @@ +/** + * Checks milestones chapter pages + */ + +const isRed = 'rgba(169,68,66,1)' + +describe('Milestones chapter- and their sub pages: ', function () { + it('should display a red alert note to readers', function () { + cy.openPage('milestones/1750-1775/parliamentary-taxation') + cy.get('#content-inner div.alert.alert-danger').should('exist') + cy.getCssProperty('#content-inner div.alert.alert-danger', 'color').then((textColor) => { + expect(textColor.value).to.equal(isRed) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/milestones/uat_milestones_titles.cy.js b/tests/cypress/e2e/milestones/uat_milestones_titles.cy.js new file mode 100644 index 00000000..085bcdb2 --- /dev/null +++ b/tests/cypress/e2e/milestones/uat_milestones_titles.cy.js @@ -0,0 +1,51 @@ +/** + * Checks milestones pages + */ + +const subpages = { + links: { + p1: 'milestones', // landing + p2: 'milestones/all', // landing subpage containing TOC + p3: 'milestones/1750-1775', // milestone subpage 2nd level + p4: 'milestones/1750-1775/foreword' // milestone subpage 3rd level + }, + titles: { + p1: 'Milestones in the History of U.S. Foreign Relations', // h1 + p2: 'All Milestones', + p3: 'Milestones in the History of U.S. Foreign Relations', + p4: '1750–1775: Diplomatic Struggles in the Colonial Period' + } +} + +describe('Milestones pages: ', function () { + // Subpage titles check + describe('Each "Milestones" subpage should be displayed and subsequently', function () { + it('should display the headline "' + subpages.titles.p1 + '" ', function () { + cy.openPage(subpages.links.p1) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p1) + }) + }) + + it('should display the headline "' + subpages.titles.p2 + '" ', function () { + cy.openPage(subpages.links.p2) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p2) + }) + }) + + it('should display the headline "' + subpages.titles.p3 + '" ', function () { + cy.openPage(subpages.links.p3) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p3) + }) + }) + + it('should display the headline "' + subpages.titles.p4 + '" ', function () { + cy.openPage(subpages.links.p4) + cy.getHeadlineH1().then((title) => { + expect(title).to.equal(subpages.titles.p4) + }) + }) + }) +}) \ No newline at end of file diff --git a/tests/cypress/e2e/news/prod_news-article.cy.js b/tests/cypress/e2e/news/prod_news-article.cy.js new file mode 100644 index 00000000..b69610c2 --- /dev/null +++ b/tests/cypress/e2e/news/prod_news-article.cy.js @@ -0,0 +1,103 @@ +/** + * Checks news article page, displaying one news entry + */ + +const newsArticles = [ + { + type: 'twitter', + color: '#1d9bff', + id: 'twitter-998588428919984129', + title: 'In #FRUS our recently digitized…', + dateTime: '2018-05-21', + date: 'May 05, 2018', + furtherLink: 'https://twitter.com/HistoryAtState/status/998588428919984129', + furtherLinkLabel: 'View Twitter Post' + }, + { + type: 'press', + color: '#22711b', + id: 'press-release-frus1977-80v09Ed2', + title: 'Press Release', + dateTime: '2018-05-31', + date: 'May 31, 2018', + thumbnail: 'https://static.history.state.gov/frus/frus1977-80v09Ed2/covers/frus1977-80v09Ed2.jpg', + altText: 'Cover image of frus1977-80v09Ed2', + furtherLink: 'historicaldocuments/frus1977-80v09Ed2', + furtherLinkLabel: 'Visit Resource' + }, + { + type: 'carousel', + color: '#c05600', + id: 'carousel-113', + title: 'Now Available: Foreign Relations of the United States, 1981–1988, Volume XI, START I', + dateTime: '2021-04-22', + date: 'Apr 22, 2021', + thumbnail: 'https://static.history.state.gov/carousel/frus1981-88v11.jpg', + altText: 'Book Cover of Foreign Relations of the United States, 1981–1988, Volume XI, START I', + furtherLink: 'historicaldocuments/frus1981-88v11', + furtherLinkLabel: 'Visit Resource' + }, + { + type: 'tumblr', + color: '#3b627e', + id: 'tumblr-136892724523', + title: 'Remembering Ambassador Stephen W. Bosworth', + dateTime: '2016-01-08', + date: 'Jan 08, 2016', + furtherLink: 'https://historyatstate.tumblr.com/post/136892724523', + furtherLinkLabel: 'View Tumblr Post' + } +] + +newsArticles.forEach((article) => { + describe('The news article with ID ' + article.id, () => { + before(() => { + cy.openPage('news/' + article.id) + cy.wait(500) + }) + + // Check if types of date badges will get the correct color + it('should have a date badge with the correct background-color "' + article.color + '"', () => { + cy.getCssProperty('time.hsg-badge--' + article.type, 'background-color').then((dc) => { + expect(dc.parsed.hex).to.equal(article.color) + }) + }) + + // Check if date is formatted correctly + it('should display the date formatted in [MNn,*-3] [D01],[YYYY]', () => { + expect(article.date).to.match(/^\w{3}\s\d{2},\s\d{4}$/) + }) + + it('should contain a "