diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml new file mode 100644 index 00000000..6705ca91 --- /dev/null +++ b/.github/workflows/cypress.yml @@ -0,0 +1,89 @@ +# 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 + img-version: [latest] + java-version: [11] + + + steps: + # Checkout code + - uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # 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 + + # TODO(DP): cache image + - name: Pull Dev Image + run: docker pull joewiz/hsg-project:${{ matrix.img-version }} + + # Install and start eXist-db + - name: Start exist-ci containers + timeout-minutes: 20 + run: | + docker run -dit -p 8080:8080 -v ${{ github.workspace }}/build:/exist/autodeploy \ + --name exist --rm --health-interval=2s --health-start-period=4s \ + joewiz/hsg-project:${{ matrix.img-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 + + + # Upload test results + - name: Upload Cypress screenshots + uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots-${{ matrix.img-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.img-version }}-${{ matrix.java-version }} + path: tests/cypress/videos + retention-days: 7 diff --git a/.gitignore b/.gitignore index fec8a4f6..57d3e92f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,14 @@ resources/scripts/app.min.js tests/reports/errorShots/* tests/reports/junit-reports/* +tests/cypress/screenshots/ +tests/cypress/videos/ +tests/cypress/downloads/ + +.DS_Store + +plans/ + # local properties local.node-exist.json diff --git a/README.md b/README.md index e3cf4ef3..e2803e6d 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ A new `package-lock.json` file will be created, which should be added to version ### Check currently installed versions -1. node: `node -v` => Should output `v18.18.2` +1. node: `node -v` => Should satisfy `package.json` engines (e.g. `>=18.0.0`; the asdf example uses 18.18.2). 2. npm: `npm -v` => Should output at least `v9.8.1` 3. gulp: `npx gulp -v` => Should output at least `CLI version: 2.3.0, Local version: 4.0.2` @@ -136,110 +136,67 @@ To deploy a full XAR file make sure you build the latest version by callling `an ## 4. Web Tests -Verify you have a local hsg-project running at localhost:8080/exist/apps/hsg-shell. See the Docker section for easy installation. +Verify you have a local hsg-project running at `http://localhost:8080/exist/apps/hsg-shell`. See the Docker section for easy installation. ### 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 is included in 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 `http://localhost:8080/exist/apps/hsg-shell`. All specs under `tests/cypress/e2e/**/*.cy.js` are run (see `specPattern` in the config). Legacy monolithic specs named `prod_*.cy.js` are kept for reference alongside the refactored per-page specs. -It might be helpful to run +#### 3. Run the 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 - -Basic syntax of starting an entire test suite is +**Open Cypress Test Runner (interactive):** ```bash -npm test +npm run cy:open ``` -Use `npx` to execute different test suites - +**Run all tests (headless):** ```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 a specific file or folder:** ```bash -npx wdio wdio.conf.js --suite test-prod +npx cypress run --spec "tests/cypress/e2e/landing/title.cy.js" +npx cypress run --spec "tests/cypress/e2e/conferences/**/*.cy.js" ``` -and for a single test it is -```bash -npx wdio wdio.conf.js --spec path-to-the-testspec -``` -for example: -```bash -npx wdio wdio.conf.js --spec tests/specs/error/prod_404.spec.js -``` +#### 4. Test structure -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 -``` +Specs live under `tests/cypress/e2e/` by feature; many areas use subfolders (e.g. conferences by year, countries/archives, departmenthistory/buildings) so each spec can run in parallel: -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`: +- `conferences/` – main page and year subfolders (2006–2012) +- `countries/` – landing, main, `archives/` +- `departmenthistory/` – index, `buildings/`, `people/`, `travels/`, `short-history/`, etc. +- `developer/` – main, catalog +- `education/` – main, modules, `modules/*-intro` +- `error/` – 404 +- `historical-documents/` – landing, FRUS subpages, `volume/` +- `iiif-images/` – IIIF viewer +- `landing/` – title, twitter +- `milestones/` – main, all, `1750-1775/`, `chapter/` +- `open/` – main, frus-metadata, frus-latest +- `search/` – search-form, search-results, filter-results, new-indexes +- `tags/` – main and tag subpages +- `ui-components/` – breadcrumb -``` -chromeOptions: { - args: [ - //'headless', - 'disable-gpu', - '--window-size=1280,1024', - 'ignore-certificate-errors', - 'ignore-urlfetcher-cert-requests' - ], - binary: process.env.WDIO_CHROME_BINARY -}, -``` +Custom Cypress commands (e.g. `normalizeHeadlineText` for headline assertions) are in `tests/cypress/support/commands.js`. -#### 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. +The suite uses Cypress with Mocha and Chai. The `assert` global is available for compatibility. -Have a look at the documentation: +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..cb28cd50 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..dd6a2d63 --- /dev/null +++ b/cypress.config.cjs @@ -0,0 +1,31 @@ +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', + ], + 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..02b6b367 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,8 @@ "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", "update": "npm update && gulp", "start": "npm install --quiet && gulp" }, diff --git a/tests/cypress/e2e/conferences/2006/china.cy.js b/tests/cypress/e2e/conferences/2006/china.cy.js new file mode 100644 index 00000000..05dd4a1d --- /dev/null +++ b/tests/cypress/e2e/conferences/2006/china.cy.js @@ -0,0 +1,13 @@ +/** + * China Cold War conference landing headline + */ + +describe('2006 China', function () { + beforeEach(function () { + cy.visit('conferences/2006-china-cold-war') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('"Transforming the Cold War: The United States and China, 1969-1980"') + }) +}) diff --git a/tests/cypress/e2e/conferences/2006/susser.cy.js b/tests/cypress/e2e/conferences/2006/susser.cy.js new file mode 100644 index 00000000..e83e0537 --- /dev/null +++ b/tests/cypress/e2e/conferences/2006/susser.cy.js @@ -0,0 +1,13 @@ +/** + * China Cold War – Susser Introductions headline + */ + +describe('2006 Susser', function () { + beforeEach(function () { + cy.visit('conferences/2006-china-cold-war/susser') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Introductions') + }) +}) diff --git a/tests/cypress/e2e/conferences/2007/detente.cy.js b/tests/cypress/e2e/conferences/2007/detente.cy.js new file mode 100644 index 00000000..c29bd18b --- /dev/null +++ b/tests/cypress/e2e/conferences/2007/detente.cy.js @@ -0,0 +1,13 @@ +/** + * Detente conference – Schedule headline + */ + +describe('2007 Detente', function () { + beforeEach(function () { + cy.visit('conferences/2007-detente') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Schedule') + }) +}) diff --git a/tests/cypress/e2e/conferences/2007/roundtable.cy.js b/tests/cypress/e2e/conferences/2007/roundtable.cy.js new file mode 100644 index 00000000..005efb53 --- /dev/null +++ b/tests/cypress/e2e/conferences/2007/roundtable.cy.js @@ -0,0 +1,13 @@ +/** + * Detente – Roundtable introduction headline + */ + +describe('2007 Roundtable', function () { + beforeEach(function () { + cy.visit('conferences/2007-detente/roundtable1') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Introduction to Roundtable Discussion of Former Government Officials') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/background.cy.js b/tests/cypress/e2e/conferences/2010/background.cy.js new file mode 100644 index 00000000..318df471 --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/background.cy.js @@ -0,0 +1,13 @@ +/** + * Southeast Asia – Background Materials headline + */ + +describe('2010 Background', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia/background-materials') + }) + + it('should display the headline', function () { + cy.get('#content-inner h3').first().normalizeHeadlineText('Background Materials') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/clinton.cy.js b/tests/cypress/e2e/conferences/2010/clinton.cy.js new file mode 100644 index 00000000..1219b04b --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/clinton.cy.js @@ -0,0 +1,13 @@ +/** + * Secretary Clinton opening address headline + */ + +describe('2010 Clinton', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia/secretary-clinton') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Opening Address by Secretary of State Hillary Rodham Clinton') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/maps.cy.js b/tests/cypress/e2e/conferences/2010/maps.cy.js new file mode 100644 index 00000000..19e2ed05 --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/maps.cy.js @@ -0,0 +1,13 @@ +/** + * Southeast Asia – Maps headline + */ + +describe('2010 Maps', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia/maps') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Maps') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/photos.cy.js b/tests/cypress/e2e/conferences/2010/photos.cy.js new file mode 100644 index 00000000..4a3a3342 --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/photos.cy.js @@ -0,0 +1,13 @@ +/** + * Southeast Asia – Vietnam Photo Gallery headline + */ + +describe('2010 Photos', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia/photos') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Vietnam Photo Gallery') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/se_asia.cy.js b/tests/cypress/e2e/conferences/2010/se_asia.cy.js new file mode 100644 index 00000000..821777d4 --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/se_asia.cy.js @@ -0,0 +1,13 @@ +/** + * Southeast Asia conference – Program headline + */ + +describe('2010 SE Asia', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Program') + }) +}) diff --git a/tests/cypress/e2e/conferences/2010/videos.cy.js b/tests/cypress/e2e/conferences/2010/videos.cy.js new file mode 100644 index 00000000..421d1ec7 --- /dev/null +++ b/tests/cypress/e2e/conferences/2010/videos.cy.js @@ -0,0 +1,13 @@ +/** + * Southeast Asia – Videos and Transcripts headline + */ + +describe('2010 Videos', function () { + beforeEach(function () { + cy.visit('conferences/2010-southeast-asia/videos-transcripts') + }) + + it('should display the headline', function () { + cy.get('#content-inner h3').first().normalizeHeadlineText('Videos and Transcripts') + }) +}) diff --git a/tests/cypress/e2e/conferences/2011/audio.cy.js b/tests/cypress/e2e/conferences/2011/audio.cy.js new file mode 100644 index 00000000..10478fa8 --- /dev/null +++ b/tests/cypress/e2e/conferences/2011/audio.cy.js @@ -0,0 +1,13 @@ +/** + * Foreign Economic Policy – Audio and Transcripts headline + */ + +describe('2011 Audio', function () { + beforeEach(function () { + cy.visit('conferences/2011-foreign-economic-policy/audio-transcripts') + }) + + it('should display the headline', function () { + cy.get('#content-inner h3').first().normalizeHeadlineText('Audio and Transcripts') + }) +}) diff --git a/tests/cypress/e2e/conferences/2011/foreign_econ.cy.js b/tests/cypress/e2e/conferences/2011/foreign_econ.cy.js new file mode 100644 index 00000000..1f506a81 --- /dev/null +++ b/tests/cypress/e2e/conferences/2011/foreign_econ.cy.js @@ -0,0 +1,13 @@ +/** + * Foreign Economic Policy conference landing headline + */ + +describe('2011 Foreign Econ', function () { + beforeEach(function () { + cy.visit('conferences/2011-foreign-economic-policy') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('"Foreign Economic Policy, 1973-1976"') + }) +}) diff --git a/tests/cypress/e2e/conferences/2011/opening.cy.js b/tests/cypress/e2e/conferences/2011/opening.cy.js new file mode 100644 index 00000000..04bb69cf --- /dev/null +++ b/tests/cypress/e2e/conferences/2011/opening.cy.js @@ -0,0 +1,13 @@ +/** + * Opening Remarks and Editor's Talk headline + */ + +describe('2011 Opening Remarks', function () { + beforeEach(function () { + cy.visit('conferences/2011-foreign-economic-policy/opening-remarks-and-editors-talk') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText("Opening Remarks and Editor's Talk on Foreign Economic Policy, 1973-1976") + }) +}) diff --git a/tests/cypress/e2e/conferences/2011/panel.cy.js b/tests/cypress/e2e/conferences/2011/panel.cy.js new file mode 100644 index 00000000..3403f82c --- /dev/null +++ b/tests/cypress/e2e/conferences/2011/panel.cy.js @@ -0,0 +1,13 @@ +/** + * Panel Discussion headline + */ + +describe('2011 Panel', function () { + beforeEach(function () { + cy.visit('conferences/2011-foreign-economic-policy/panel') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Panel Discussion') + }) +}) diff --git a/tests/cypress/e2e/conferences/2012/salt.cy.js b/tests/cypress/e2e/conferences/2012/salt.cy.js new file mode 100644 index 00000000..afa94ae3 --- /dev/null +++ b/tests/cypress/e2e/conferences/2012/salt.cy.js @@ -0,0 +1,13 @@ +/** + * SALT conference landing headline + */ + +describe('2012 SALT', function () { + beforeEach(function () { + cy.visit('conferences/2012-national-security-policy-salt') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('"National Security Policy and SALT I, 1969-1972"') + }) +}) diff --git a/tests/cypress/e2e/conferences/conferences.cy.js b/tests/cypress/e2e/conferences/conferences.cy.js new file mode 100644 index 00000000..a2e071bb --- /dev/null +++ b/tests/cypress/e2e/conferences/conferences.cy.js @@ -0,0 +1,13 @@ +/** + * Conference main page headline + */ + +describe('Conferences', function () { + beforeEach(function () { + cy.visit('conferences') + }) + + it('should display the headline', function () { + cy.contains('#content-inner h1', 'Conferences') + }) +}) diff --git a/tests/cypress/e2e/countries/archives/afghanistan.cy.js b/tests/cypress/e2e/countries/archives/afghanistan.cy.js new file mode 100644 index 00000000..644f4579 --- /dev/null +++ b/tests/cypress/e2e/countries/archives/afghanistan.cy.js @@ -0,0 +1,13 @@ +/** + * Archives: Afghanistan headline + */ + +describe('Archives Afghanistan', function () { + beforeEach(function () { + cy.visit('countries/archives/afghanistan') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('World Wide Diplomatic Archives Index: Afghanistan') + }) +}) diff --git a/tests/cypress/e2e/countries/archives/all.cy.js b/tests/cypress/e2e/countries/archives/all.cy.js new file mode 100644 index 00000000..08317a26 --- /dev/null +++ b/tests/cypress/e2e/countries/archives/all.cy.js @@ -0,0 +1,13 @@ +/** + * All Countries headline + */ + +describe('All countries', function () { + beforeEach(function () { + cy.visit('countries/archives/all') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('All Countries') + }) +}) diff --git a/tests/cypress/e2e/countries/archives/archives.cy.js b/tests/cypress/e2e/countries/archives/archives.cy.js new file mode 100644 index 00000000..a415dae9 --- /dev/null +++ b/tests/cypress/e2e/countries/archives/archives.cy.js @@ -0,0 +1,13 @@ +/** + * World Wide Diplomatic Archives Index headline + */ + +describe('Archives index', function () { + beforeEach(function () { + cy.visit('countries/archives') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('World Wide Diplomatic Archives Index') + }) +}) diff --git a/tests/cypress/e2e/countries/archives/bahamas.cy.js b/tests/cypress/e2e/countries/archives/bahamas.cy.js new file mode 100644 index 00000000..f9779602 --- /dev/null +++ b/tests/cypress/e2e/countries/archives/bahamas.cy.js @@ -0,0 +1,13 @@ +/** + * Archives: Bahamas headline + */ + +describe('Archives Bahamas', function () { + beforeEach(function () { + cy.visit('countries/archives/bahamas') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('World Wide Diplomatic Archives Index: Bahamas') + }) +}) diff --git a/tests/cypress/e2e/countries/archives/zimbabwe.cy.js b/tests/cypress/e2e/countries/archives/zimbabwe.cy.js new file mode 100644 index 00000000..57d34120 --- /dev/null +++ b/tests/cypress/e2e/countries/archives/zimbabwe.cy.js @@ -0,0 +1,13 @@ +/** + * Archives: Zimbabwe headline + */ + +describe('Archives Zimbabwe', function () { + beforeEach(function () { + cy.visit('countries/archives/zimbabwe') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('World Wide Diplomatic Archives Index: Zimbabwe') + }) +}) diff --git a/tests/cypress/e2e/countries/countries.cy.js b/tests/cypress/e2e/countries/countries.cy.js new file mode 100644 index 00000000..3867fd49 --- /dev/null +++ b/tests/cypress/e2e/countries/countries.cy.js @@ -0,0 +1,13 @@ +/** + * Countries main page headline + */ + +describe('Countries', function () { + beforeEach(function () { + cy.visit('countries') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Countries') + }) +}) diff --git a/tests/cypress/e2e/countries/landing.cy.js b/tests/cypress/e2e/countries/landing.cy.js new file mode 100644 index 00000000..3d255b9d --- /dev/null +++ b/tests/cypress/e2e/countries/landing.cy.js @@ -0,0 +1,13 @@ +/** + * Countries landing – select input + */ + +describe('Countries landing', function () { + beforeEach(function () { + cy.visit('countries') + }) + + it('should display a select input for choosing countries', function () { + cy.get('#content-inner select, select[data-template="countries:load-countries"]', { timeout: 10000 }).should('exist') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/buildings.cy.js b/tests/cypress/e2e/departmenthistory/buildings/buildings.cy.js new file mode 100644 index 00000000..1f664b1e --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/buildings.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings of the Department of State – main headline + */ + +describe('Buildings', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Buildings of the Department of State') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/foreword.cy.js b/tests/cypress/e2e/departmenthistory/buildings/foreword.cy.js new file mode 100644 index 00000000..ac0bbfc5 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/foreword.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings – Original Foreword headline + */ + +describe('Buildings Foreword', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings/foreword') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Original Foreword') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/intro.cy.js b/tests/cypress/e2e/departmenthistory/buildings/intro.cy.js new file mode 100644 index 00000000..e17cd750 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/intro.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings – Introduction headline + */ + +describe('Buildings Intro', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings/intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Introduction') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/section1.cy.js b/tests/cypress/e2e/departmenthistory/buildings/section1.cy.js new file mode 100644 index 00000000..e71f22f3 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/section1.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings – Section 1 headline + */ + +describe('Buildings Section 1', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings/section1') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('The Period of the Continental Congress') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/section2.cy.js b/tests/cypress/e2e/departmenthistory/buildings/section2.cy.js new file mode 100644 index 00000000..54d6bb2a --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/section2.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings – Section 2 headline (Carpenters' Hall) + */ + +describe('Buildings Section 2', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings/section2') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText("Carpenters' Hall, Philadelphia\nSept. 5, 1774—Oct. 26, 1774") + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/buildings/section3.cy.js b/tests/cypress/e2e/departmenthistory/buildings/section3.cy.js new file mode 100644 index 00000000..0c79e72b --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/buildings/section3.cy.js @@ -0,0 +1,13 @@ +/** + * Buildings – Section 3 headline (Pennsylvania State House) + */ + +describe('Buildings Section 3', function () { + beforeEach(function () { + cy.visit('departmenthistory/buildings/section3') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Pennsylvania State House (Independence Hall), Philadelphia\nIntermittingly from May 10, 1775 to March 1, 1781') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/departmenthistory.cy.js b/tests/cypress/e2e/departmenthistory/departmenthistory.cy.js new file mode 100644 index 00000000..312da077 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/departmenthistory.cy.js @@ -0,0 +1,13 @@ +/** + * Department History index headline + */ + +describe('Department History', function () { + beforeEach(function () { + cy.visit('departmenthistory') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Department History') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/diplomatic-couriers.cy.js b/tests/cypress/e2e/departmenthistory/diplomatic-couriers.cy.js new file mode 100644 index 00000000..3cbbdb78 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/diplomatic-couriers.cy.js @@ -0,0 +1,13 @@ +/** + * U.S. Diplomatic Couriers headline + */ + +describe('Diplomatic Couriers', function () { + beforeEach(function () { + cy.visit('departmenthistory/diplomatic-couriers') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('U.S. Diplomatic Couriers') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/people/principals-chiefs.cy.js b/tests/cypress/e2e/departmenthistory/people/principals-chiefs.cy.js new file mode 100644 index 00000000..0d212e05 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/people/principals-chiefs.cy.js @@ -0,0 +1,13 @@ +/** + * Principal Officers and Chiefs of Mission headline + */ + +describe('Principals and Chiefs', function () { + beforeEach(function () { + cy.visit('departmenthistory/people/principals-chiefs') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Principal Officers and Chiefs of Mission') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/people/secretaries.cy.js b/tests/cypress/e2e/departmenthistory/people/secretaries.cy.js new file mode 100644 index 00000000..f7d43bf7 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/people/secretaries.cy.js @@ -0,0 +1,13 @@ +/** + * Biographies of the Secretaries of State headline + */ + +describe('Secretaries of State', function () { + beforeEach(function () { + cy.visit('departmenthistory/people/secretaries') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Biographies of the Secretaries of State') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/short-history/foundations.cy.js b/tests/cypress/e2e/departmenthistory/short-history/foundations.cy.js new file mode 100644 index 00000000..b6568f7d --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/short-history/foundations.cy.js @@ -0,0 +1,13 @@ +/** + * Short History – Foundations headline + */ + +describe('Short History Foundations', function () { + beforeEach(function () { + cy.visit('departmenthistory/short-history/foundations') + }) + + it('should display the headline', function () { + cy.get('#content-inner h3').first().normalizeHeadlineText('Foundations of Foreign Affairs, 1775-1823') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/short-history/origins.cy.js b/tests/cypress/e2e/departmenthistory/short-history/origins.cy.js new file mode 100644 index 00000000..b9acb69a --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/short-history/origins.cy.js @@ -0,0 +1,13 @@ +/** + * Short History – Origins headline + */ + +describe('Short History Origins', function () { + beforeEach(function () { + cy.visit('departmenthistory/short-history/origins') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Origins of a Diplomatic Tradition') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/short-history/short-history.cy.js b/tests/cypress/e2e/departmenthistory/short-history/short-history.cy.js new file mode 100644 index 00000000..67ab4d03 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/short-history/short-history.cy.js @@ -0,0 +1,13 @@ +/** + * Short History main headline + */ + +describe('Short History', function () { + beforeEach(function () { + cy.visit('departmenthistory/short-history') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('A Short History of the Department of State') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/travels/president.cy.js b/tests/cypress/e2e/departmenthistory/travels/president.cy.js new file mode 100644 index 00000000..218fe046 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/travels/president.cy.js @@ -0,0 +1,13 @@ +/** + * Travels Abroad of the President headline + */ + +describe('President travels', function () { + beforeEach(function () { + cy.visit('departmenthistory/travels/president') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Travels Abroad of the President') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/travels/secretary.cy.js b/tests/cypress/e2e/departmenthistory/travels/secretary.cy.js new file mode 100644 index 00000000..9c7ab02a --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/travels/secretary.cy.js @@ -0,0 +1,13 @@ +/** + * Travels Abroad of the Secretary of State headline + */ + +describe('Secretary travels', function () { + beforeEach(function () { + cy.visit('departmenthistory/travels/secretary') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Travels Abroad of the Secretary of State') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/visits.cy.js b/tests/cypress/e2e/departmenthistory/visits.cy.js new file mode 100644 index 00000000..53dd25b9 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/visits.cy.js @@ -0,0 +1,13 @@ +/** + * Visits by Foreign Leaders headline + */ + +describe('Visits by Foreign Leaders', function () { + beforeEach(function () { + cy.visit('departmenthistory/visits') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Visits by Foreign Leaders') + }) +}) diff --git a/tests/cypress/e2e/departmenthistory/wwi.cy.js b/tests/cypress/e2e/departmenthistory/wwi.cy.js new file mode 100644 index 00000000..320a0910 --- /dev/null +++ b/tests/cypress/e2e/departmenthistory/wwi.cy.js @@ -0,0 +1,13 @@ +/** + * World War I and the Department headline + */ + +describe('WWI and the Department', function () { + beforeEach(function () { + cy.visit('departmenthistory/wwi') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('World War I and the Department') + }) +}) diff --git a/tests/cypress/e2e/developer/catalog.cy.js b/tests/cypress/e2e/developer/catalog.cy.js new file mode 100644 index 00000000..78269cf3 --- /dev/null +++ b/tests/cypress/e2e/developer/catalog.cy.js @@ -0,0 +1,13 @@ +/** + * Ebook Catalog API headline + */ + +describe('Developer Catalog', function () { + beforeEach(function () { + cy.visit('developer/catalog') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Office of the Historian Ebook Catalog API') + }) +}) diff --git a/tests/cypress/e2e/developer/developer.cy.js b/tests/cypress/e2e/developer/developer.cy.js new file mode 100644 index 00000000..f4e385ed --- /dev/null +++ b/tests/cypress/e2e/developer/developer.cy.js @@ -0,0 +1,13 @@ +/** + * Developer Resources headline + */ + +describe('Developer', function () { + beforeEach(function () { + cy.visit('developer') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Developer Resources') + }) +}) diff --git a/tests/cypress/e2e/education/education.cy.js b/tests/cypress/e2e/education/education.cy.js new file mode 100644 index 00000000..1b2f8535 --- /dev/null +++ b/tests/cypress/e2e/education/education.cy.js @@ -0,0 +1,13 @@ +/** + * Education main headline + */ + +describe('Education', function () { + beforeEach(function () { + cy.visit('education') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Education') + }) +}) diff --git a/tests/cypress/e2e/education/modules.cy.js b/tests/cypress/e2e/education/modules.cy.js new file mode 100644 index 00000000..11191a4c --- /dev/null +++ b/tests/cypress/e2e/education/modules.cy.js @@ -0,0 +1,13 @@ +/** + * Curriculum Modules headline + */ + +describe('Curriculum Modules', function () { + beforeEach(function () { + cy.visit('education/modules') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Curriculum Modules') + }) +}) diff --git a/tests/cypress/e2e/education/modules/border-vanishes-intro.cy.js b/tests/cypress/e2e/education/modules/border-vanishes-intro.cy.js new file mode 100644 index 00000000..ce460a6b --- /dev/null +++ b/tests/cypress/e2e/education/modules/border-vanishes-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Border Vanishes intro module headline + */ + +describe('Border Vanishes intro', function () { + beforeEach(function () { + cy.visit('education/modules/border-vanishes-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "When the Border Vanishes: Diplomacy and the Threat to our Health and Environment"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/documents-intro.cy.js b/tests/cypress/e2e/education/modules/documents-intro.cy.js new file mode 100644 index 00000000..d93eb75f --- /dev/null +++ b/tests/cypress/e2e/education/modules/documents-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Documents intro module headline + */ + +describe('Documents intro', function () { + beforeEach(function () { + cy.visit('education/modules/documents-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "Documents on Diplomacy: Primary Source Documents and Lessons from the World of Foreign Affairs, 1775-2011"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/history-diplomacy-intro.cy.js b/tests/cypress/e2e/education/modules/history-diplomacy-intro.cy.js new file mode 100644 index 00000000..92df1ee5 --- /dev/null +++ b/tests/cypress/e2e/education/modules/history-diplomacy-intro.cy.js @@ -0,0 +1,13 @@ +/** + * History of Diplomacy intro module headline + */ + +describe('History Diplomacy intro', function () { + beforeEach(function () { + cy.visit('education/modules/history-diplomacy-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "A History of Diplomacy"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/journey-shared-intro.cy.js b/tests/cypress/e2e/education/modules/journey-shared-intro.cy.js new file mode 100644 index 00000000..e24396f0 --- /dev/null +++ b/tests/cypress/e2e/education/modules/journey-shared-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Journey Shared intro module headline + */ + +describe('Journey Shared intro', function () { + beforeEach(function () { + cy.visit('education/modules/journey-shared-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "A Journey Shared: The United States and China"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/media-intro.cy.js b/tests/cypress/e2e/education/modules/media-intro.cy.js new file mode 100644 index 00000000..ce4b7e75 --- /dev/null +++ b/tests/cypress/e2e/education/modules/media-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Media intro module headline + */ + +describe('Media intro', function () { + beforeEach(function () { + cy.visit('education/modules/media-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "Today in Washington: The Media and Diplomacy"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/sports-intro.cy.js b/tests/cypress/e2e/education/modules/sports-intro.cy.js new file mode 100644 index 00000000..27b09b22 --- /dev/null +++ b/tests/cypress/e2e/education/modules/sports-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Sports intro module headline + */ + +describe('Sports intro', function () { + beforeEach(function () { + cy.visit('education/modules/sports-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "Sports and Diplomacy in the Global Arena"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/education/modules/terrorism-intro.cy.js b/tests/cypress/e2e/education/modules/terrorism-intro.cy.js new file mode 100644 index 00000000..eacbfd32 --- /dev/null +++ b/tests/cypress/e2e/education/modules/terrorism-intro.cy.js @@ -0,0 +1,13 @@ +/** + * Terrorism intro module headline + */ + +describe('Terrorism intro', function () { + beforeEach(function () { + cy.visit('education/modules/terrorism-intro') + }) + + it('should display the headline', function () { + cy.get('#content-inner div:nth-child(2) h2', { timeout: 10000 }).first().normalizeHeadlineText('Introduction to Curriculum Packet on "Terrorism: A War Without Borders"', { stripAfter: 'Lesson Plans' }) + }) +}) diff --git a/tests/cypress/e2e/error/404.cy.js b/tests/cypress/e2e/error/404.cy.js new file mode 100644 index 00000000..96d48c73 --- /dev/null +++ b/tests/cypress/e2e/error/404.cy.js @@ -0,0 +1,10 @@ +/** + * 404 error page + */ + +describe('404 error page', function () { + it('should redirect to the 404 error page', function () { + cy.visit('asdfg', { failOnStatusCode: false }) + cy.title().should('include', 'Page not found - Office of the Historian') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/about-frus.cy.js b/tests/cypress/e2e/historical-documents/about-frus.cy.js new file mode 100644 index 00000000..393cc6bd --- /dev/null +++ b/tests/cypress/e2e/historical-documents/about-frus.cy.js @@ -0,0 +1,13 @@ +/** + * About FRUS headline + */ + +describe('About FRUS', function () { + beforeEach(function () { + cy.visit('historicaldocuments/about-frus') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('About the Foreign Relations of the United States Series') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/citing-frus.cy.js b/tests/cypress/e2e/historical-documents/citing-frus.cy.js new file mode 100644 index 00000000..8343da91 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/citing-frus.cy.js @@ -0,0 +1,13 @@ +/** + * Citing the Foreign Relations series headline + */ + +describe('Citing FRUS', function () { + beforeEach(function () { + cy.visit('historicaldocuments/citing-frus') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Citing the Foreign Relations series') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/ebooks.cy.js b/tests/cypress/e2e/historical-documents/ebooks.cy.js new file mode 100644 index 00000000..b743d46f --- /dev/null +++ b/tests/cypress/e2e/historical-documents/ebooks.cy.js @@ -0,0 +1,13 @@ +/** + * Ebooks headline + */ + +describe('FRUS Ebooks', function () { + beforeEach(function () { + cy.visit('historicaldocuments/ebooks') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Ebooks') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/frus-history.cy.js b/tests/cypress/e2e/historical-documents/frus-history.cy.js new file mode 100644 index 00000000..a2e0d610 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/frus-history.cy.js @@ -0,0 +1,13 @@ +/** + * FRUS History page headline (empty h1) + */ + +describe('FRUS History', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus-history') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/frus-toc.cy.js b/tests/cypress/e2e/historical-documents/frus-toc.cy.js new file mode 100644 index 00000000..75c609f0 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/frus-toc.cy.js @@ -0,0 +1,14 @@ +/** + * TOC of a volume – current chapter highlight + */ + +describe('FRUS TOC', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus1947v03/comp1') + }) + + it('should highlight the current chapter', function () { + cy.get('a.hsg-current[href*="historicaldocuments/frus1947v03/comp1"]') + .should('have.css', 'color', 'rgb(32, 84, 147)') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/landing.cy.js b/tests/cypress/e2e/historical-documents/landing.cy.js new file mode 100644 index 00000000..1b1e5b4e --- /dev/null +++ b/tests/cypress/e2e/historical-documents/landing.cy.js @@ -0,0 +1,40 @@ +/** + * FRUS landing – tiles and dropdown headline + */ + +describe('FRUS landing', function () { + beforeEach(function () { + cy.visit('historicaldocuments') + }) + + it('should have at least 3 article tiles', function () { + cy.get('#content-inner article', { timeout: 10000 }).should('have.length.at.least', 3) + }) + + it('should display tile 0 image', function () { + cy.get('#content-inner .hsg-thumbnail-wrapper').eq(0).find('a img').invoke('attr', 'src').then((imgSrc) => { + expect(imgSrc).to.include('https://static.history.state.gov/images/alincoln.jpg') + }) + }) + + it('should display tile 1 image', function () { + cy.get('#content-inner .hsg-thumbnail-wrapper').eq(1).find('a img').invoke('attr', 'src').then((imgSrc) => { + expect(imgSrc).to.include('https://static.history.state.gov/images/ajohnson.jpg') + }) + }) + + it('should display tile 2 image', function () { + cy.get('#content-inner .hsg-thumbnail-wrapper').eq(2).find('a img').invoke('attr', 'src').then((imgSrc) => { + expect(imgSrc).to.include('https://static.history.state.gov/images/usgrant.jpg') + }) + }) + + it('should open FRUS landing with headline after dropdown navigation', function () { + cy.get('ul.nav.navbar-nav li:nth-child(2) > a').first().click() + cy.get('ul.dropdown-menu li:nth-child(2)').should('be.visible') + cy.get('ul.dropdown-menu li:nth-child(1) a').first().click() + cy.get('#content-inner h1').invoke('text').then((title) => { + expect(title).to.equal('Historical Documents') + }) + }) +}) diff --git a/tests/cypress/e2e/historical-documents/quarterly-releases.cy.js b/tests/cypress/e2e/historical-documents/quarterly-releases.cy.js new file mode 100644 index 00000000..fbbcbf89 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/quarterly-releases.cy.js @@ -0,0 +1,13 @@ +/** + * Quarterly Releases headline + */ + +describe('Quarterly Releases', function () { + beforeEach(function () { + cy.visit('historicaldocuments/quarterly-releases') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Quarterly Releases') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/status-of-the-series.cy.js b/tests/cypress/e2e/historical-documents/status-of-the-series.cy.js new file mode 100644 index 00000000..ccc212c5 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/status-of-the-series.cy.js @@ -0,0 +1,13 @@ +/** + * Status of the FRUS Series headline + */ + +describe('Status of the Series', function () { + beforeEach(function () { + cy.visit('historicaldocuments/status-of-the-series') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Status of the Foreign Relations of the United States Series') + }) +}) diff --git a/tests/cypress/e2e/historical-documents/volume/volume-cover.cy.js b/tests/cypress/e2e/historical-documents/volume/volume-cover.cy.js new file mode 100644 index 00000000..9468361b --- /dev/null +++ b/tests/cypress/e2e/historical-documents/volume/volume-cover.cy.js @@ -0,0 +1,37 @@ +/** + * Volume landing with cover image (frus1951-54IranEd2) + */ + +const s3_Prod = 'https://static.history.state.gov' + +describe('Volume with cover', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus1951-54IranEd2') + cy.get('#volume', { timeout: 10000 }).should('exist') + }) + + it('should display a cover image loaded from S3', function () { + cy.get('#volume #content-inner > img').invoke('attr', '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', function () { + cy.get('#volume #content-inner > img').invoke('attr', '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', function () { + cy.get('#volume #content-inner > h1').invoke('text').then((title) => { + expect(title.trim()).to.equal('Foreign Relations of the United States, 1952–1954, Iran, 1951–1954, Second Edition') + }) + }) + + it('should NOT display a h1 heading generated from TEI', function () { + cy.get('#volume .content h1').then(($el) => { + const display = $el.length ? window.getComputedStyle($el[0]).display : 'none' + expect(display).to.equal('none') + }) + }) +}) diff --git a/tests/cypress/e2e/historical-documents/volume/volume-no-cover.cy.js b/tests/cypress/e2e/historical-documents/volume/volume-no-cover.cy.js new file mode 100644 index 00000000..f312bdb4 --- /dev/null +++ b/tests/cypress/e2e/historical-documents/volume/volume-no-cover.cy.js @@ -0,0 +1,28 @@ +/** + * Volume landing without cover image (frus1861-99Index) + */ + +describe('Volume without cover', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus1861-99Index') + cy.get('#content-inner, #volume', { timeout: 10000 }).should('exist') + }) + + it('should NOT display a cover image', function () { + cy.get('#volume #content-inner > img').should('not.exist') + }) + + it('should display a h1 heading', function () { + cy.get('#content-inner > h1, #volume #content-inner > h1').first().invoke('text').then((title) => { + expect(title.trim()).to.equal('General Index to the Published Volumes of the Diplomatic Correspondence and Foreign Relations of the United States, 1861–1899') + }) + }) + + it('should NOT display a h1 heading generated from TEI', function () { + cy.get('body').then(($body) => { + const $tei = $body.find('#volume .content h1, .content h1') + const display = $tei.length ? window.getComputedStyle($tei[0]).display : 'none' + expect(display).to.equal('none') + }) + }) +}) diff --git a/tests/cypress/e2e/iiif-images/iiif-viewer.cy.js b/tests/cypress/e2e/iiif-images/iiif-viewer.cy.js new file mode 100644 index 00000000..6989522a --- /dev/null +++ b/tests/cypress/e2e/iiif-images/iiif-viewer.cy.js @@ -0,0 +1,14 @@ +/** + * IIIF image viewer (OpenSeadragon) + */ + +describe('IIIF viewer', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus1902app1/pg_11') + cy.wait(500) + }) + + it('should be displayed in a IIIF viewer', function () { + cy.get('.openseadragon-canvas > canvas').should('exist') + }) +}) diff --git a/tests/cypress/e2e/landing/title.cy.js b/tests/cypress/e2e/landing/title.cy.js new file mode 100644 index 00000000..305757a8 --- /dev/null +++ b/tests/cypress/e2e/landing/title.cy.js @@ -0,0 +1,13 @@ +/** + * HSG landing page title + */ + +describe('Landing title', function () { + beforeEach(function () { + cy.visit('') + }) + + it('should have the correct title', function () { + cy.title().should('include', 'Office of the Historian') + }) +}) diff --git a/tests/cypress/e2e/landing/twitter.cy.js b/tests/cypress/e2e/landing/twitter.cy.js new file mode 100644 index 00000000..9ece38bd --- /dev/null +++ b/tests/cypress/e2e/landing/twitter.cy.js @@ -0,0 +1,13 @@ +/** + * Twitter section on landing page + */ + +describe('Landing twitter', function () { + beforeEach(function () { + cy.visit('') + }) + + it.skip('should display at least one twitter post (requires .post-list widget)', function () { + cy.get('.post-list .post p', { timeout: 10000 }).should('have.length.at.least', 1) + }) +}) diff --git a/tests/cypress/e2e/milestones/1750-1775/era.cy.js b/tests/cypress/e2e/milestones/1750-1775/era.cy.js new file mode 100644 index 00000000..8cd45a5b --- /dev/null +++ b/tests/cypress/e2e/milestones/1750-1775/era.cy.js @@ -0,0 +1,13 @@ +/** + * Milestones era 1750-1775 headline + */ + +describe('Milestones 1750-1775', function () { + beforeEach(function () { + cy.visit('milestones/1750-1775') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Milestones in the History of U.S. Foreign Relations') + }) +}) diff --git a/tests/cypress/e2e/milestones/1750-1775/foreword.cy.js b/tests/cypress/e2e/milestones/1750-1775/foreword.cy.js new file mode 100644 index 00000000..b637a4fa --- /dev/null +++ b/tests/cypress/e2e/milestones/1750-1775/foreword.cy.js @@ -0,0 +1,13 @@ +/** + * Milestones 1750-1775 foreword headline + */ + +describe('Milestones Foreword', function () { + beforeEach(function () { + cy.visit('milestones/1750-1775/foreword') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('1750–1775: Diplomatic Struggles in the Colonial Period') + }) +}) diff --git a/tests/cypress/e2e/milestones/all.cy.js b/tests/cypress/e2e/milestones/all.cy.js new file mode 100644 index 00000000..55073b70 --- /dev/null +++ b/tests/cypress/e2e/milestones/all.cy.js @@ -0,0 +1,13 @@ +/** + * All Milestones headline + */ + +describe('All Milestones', function () { + beforeEach(function () { + cy.visit('milestones/all') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('All Milestones') + }) +}) diff --git a/tests/cypress/e2e/milestones/chapter/parliamentary-taxation.cy.js b/tests/cypress/e2e/milestones/chapter/parliamentary-taxation.cy.js new file mode 100644 index 00000000..2cba56d0 --- /dev/null +++ b/tests/cypress/e2e/milestones/chapter/parliamentary-taxation.cy.js @@ -0,0 +1,23 @@ +/** + * Milestones chapter – red alert note + */ + +const red = 'rgba(169,68,66,1)' + +describe('Milestones chapter alert', function () { + beforeEach(function () { + cy.visit('milestones/1750-1775/parliamentary-taxation') + }) + + it('should display a red alert note to readers', function () { + cy.get('#content-inner div.alert.alert-danger') + .should('exist') + .should('have.css', 'color') + .then((value) => { + const normalized = value.replace(/\s+/g, '') + const expectedRgb = 'rgb(169,68,66)'.replace(/\s+/g, '') + const expectedRgba = red.replace(/\s+/g, '') + expect([expectedRgb, expectedRgba]).to.include(normalized) + }) + }) +}) diff --git a/tests/cypress/e2e/milestones/milestones.cy.js b/tests/cypress/e2e/milestones/milestones.cy.js new file mode 100644 index 00000000..64ba777f --- /dev/null +++ b/tests/cypress/e2e/milestones/milestones.cy.js @@ -0,0 +1,13 @@ +/** + * Milestones main headline + */ + +describe('Milestones', function () { + beforeEach(function () { + cy.visit('milestones') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Milestones in the History of U.S. Foreign Relations') + }) +}) diff --git a/tests/cypress/e2e/open/frus-latest.cy.js b/tests/cypress/e2e/open/frus-latest.cy.js new file mode 100644 index 00000000..baa8fc44 --- /dev/null +++ b/tests/cypress/e2e/open/frus-latest.cy.js @@ -0,0 +1,13 @@ +/** + * FRUS Latest volumes headline + */ + +describe('FRUS Latest', function () { + beforeEach(function () { + cy.visit('open/frus-latest') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Latest Volumes of Foreign Relations of the United States Series') + }) +}) diff --git a/tests/cypress/e2e/open/frus-metadata.cy.js b/tests/cypress/e2e/open/frus-metadata.cy.js new file mode 100644 index 00000000..e7f26cbe --- /dev/null +++ b/tests/cypress/e2e/open/frus-metadata.cy.js @@ -0,0 +1,13 @@ +/** + * FRUS Metadata headline + */ + +describe('FRUS Metadata', function () { + beforeEach(function () { + cy.visit('open/frus-metadata') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Bibliographic Metadata of the Foreign Relations of the United States Series') + }) +}) diff --git a/tests/cypress/e2e/open/open.cy.js b/tests/cypress/e2e/open/open.cy.js new file mode 100644 index 00000000..9f1d2bc5 --- /dev/null +++ b/tests/cypress/e2e/open/open.cy.js @@ -0,0 +1,13 @@ +/** + * Open Government Initiative headline + */ + +describe('Open Government', function () { + beforeEach(function () { + cy.visit('open') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Open Government Initiative') + }) +}) diff --git a/tests/cypress/e2e/search/filter-results.cy.js b/tests/cypress/e2e/search/filter-results.cy.js new file mode 100644 index 00000000..e8899068 --- /dev/null +++ b/tests/cypress/e2e/search/filter-results.cy.js @@ -0,0 +1,64 @@ +/** + * Search filter and sort options (parameterized) + */ + +const basePath = 'search' +const baseQuery = { q: 'china' } +const sortingOptions = [ + { label: 'relevance', qs: { 'sort-by': 'relevance' } }, + { label: 'date-asc', qs: { 'sort-by': 'date-asc' } } +] + +const validFilterOptions = [ + { label: 'entire-site', qs: { within: 'entire-site' } }, + { label: 'department', qs: { within: 'department' } }, + { label: 'documents', qs: { within: 'documents' } }, + { label: 'documents+dates', qs: { within: 'documents', 'start-date': '1946-02-01', 'end-date': '1946-03-31' } }, + { label: 'documents+year', qs: { within: 'documents', 'start-date': '1946', 'end-date': '1946-03-31' } }, + { label: 'documents+month', qs: { within: 'documents', 'start-date': '1946-02', 'end-date': '1946-03-31' } }, + { label: 'documents+end', qs: { within: 'documents', 'end-date': '1946-01-31' } }, + { label: 'documents+range', qs: { within: 'documents', 'start-date': '1946-02-01', 'end-date': '1946' } }, + { label: 'documents+range-month', qs: { within: 'documents', 'start-date': '1946-02-01', 'end-date': '1946-03' } }, + { label: 'documents+start-only', qs: { within: 'documents', 'start-date': '1946-01-02' } } +] + +const invalidFilterOptions = [ + { label: 'start-gt-end', qs: { within: 'documents', 'start-date': '1946-01-02', 'end-date': '1945-01-01' } }, + { label: 'dates-out-of-scope', qs: { within: 'documents', 'start-date': '1000-01-02', 'end-date': '1000-01-01' } } +] + +const firstResultItem = '.hsg-search-result > h3 > a' + +validFilterOptions.forEach(function (filter) { + sortingOptions.forEach(function (sort) { + describe('Filter ' + filter.label + ' sort ' + sort.label, function () { + beforeEach(function () { + cy.visit(basePath, { qs: { ...baseQuery, ...filter.qs, ...sort.qs } }) + }) + + it('should return search results', function () { + cy.get(firstResultItem).invoke('text').then((searchResult) => { + expect(searchResult).to.exist + }) + }) + }) + }) +}) + +invalidFilterOptions.forEach(function (filter) { + describe('Invalid filter ' + filter.label, function () { + beforeEach(function () { + cy.visit(basePath, { qs: { ...baseQuery, ...filter.qs, 'sort-by': 'relevance' } }) + }) + + it('should display the search page', function () { + cy.get('.hsg-search-section').should('exist') + }) + + it('should not return any search results', function () { + cy.get('.hsg-search-section').within(function () { + cy.contains('p', 'No results were found.').should('be.visible') + }) + }) + }) +}) diff --git a/tests/cypress/e2e/search/new-indexes.cy.js b/tests/cypress/e2e/search/new-indexes.cy.js new file mode 100644 index 00000000..257e7b09 --- /dev/null +++ b/tests/cypress/e2e/search/new-indexes.cy.js @@ -0,0 +1,72 @@ +/** + * Search count and duration (expected indexes) + */ + +const searchCount = '.hsg-search-section .search-count' +const searchDuration = '.hsg-search-section .search-duration' + +const baseQs = { within: 'documents', 'start-date': '1940', 'end-date': '1960' } + +describe('Search Indochina', function () { + it('should display expected number of results', function () { + cy.visit('search', { qs: { q: 'Indochina', ...baseQs, 'sort-by': 'date-asc' } }) + cy.get(searchCount).invoke('text').then((count) => { + expect(count.replace(/,/, '')).to.equal('4512') + }) + }) + + it('should be performed within expected duration', function () { + cy.visit('search', { qs: { q: 'Indochina', ...baseQs } }) + cy.get(searchDuration).invoke('text').then((duration) => { + expect(parseFloat(duration)).to.be.below(1.000) + }) + }) +}) + +describe('Search Sudan', function () { + it('should display expected number of results', function () { + cy.visit('search', { qs: { q: 'Sudan', ...baseQs, 'sort-by': 'date-asc' } }) + cy.get(searchCount).invoke('text').then((count) => { + expect(count.replace(/,/, '')).to.equal('723') + }) + }) + + it('should be performed within expected duration', function () { + cy.visit('search', { qs: { q: 'Sudan', ...baseQs } }) + cy.get(searchDuration).invoke('text').then((duration) => { + expect(parseFloat(duration)).to.be.below(1.000) + }) + }) +}) + +describe('Search China', function () { + it('should display expected number of results', function () { + cy.visit('search', { qs: { q: 'China', ...baseQs, 'sort-by': 'date-asc' } }) + cy.get(searchCount).invoke('text').then((count) => { + expect(count.replace(/,/, '')).to.equal('20712') + }) + }) + + it('should be performed within expected duration', function () { + cy.visit('search', { qs: { q: 'China', ...baseQs } }) + cy.get(searchDuration).invoke('text').then((duration) => { + expect(parseFloat(duration)).to.be.below(1.000) + }) + }) +}) + +describe('Search Tokyo', function () { + it('should display expected number of results', function () { + cy.visit('search', { qs: { q: 'Tokyo', ...baseQs, 'sort-by': 'date-asc' } }) + cy.get(searchCount).invoke('text').then((count) => { + expect(count.replace(/,/, '')).to.equal('5090') + }) + }) + + it('should be performed within expected duration', function () { + cy.visit('search', { qs: { q: 'Tokyo', ...baseQs } }) + cy.get(searchDuration).invoke('text').then((duration) => { + expect(parseFloat(duration)).to.be.below(1.000) + }) + }) +}) diff --git a/tests/cypress/e2e/search/search-form.cy.js b/tests/cypress/e2e/search/search-form.cy.js new file mode 100644 index 00000000..d2d13f9c --- /dev/null +++ b/tests/cypress/e2e/search/search-form.cy.js @@ -0,0 +1,12 @@ +/** + * Search form – submit and results + */ + +describe('Search form', function () { + it('should have results after searching', function () { + cy.visit('/') + cy.get('form input#search-box').type('Washington') + cy.get('button[type="submit"]').click() + cy.get('.hsg-search-result > h3 > a').should('exist').and('not.be.empty') + }) +}) diff --git a/tests/cypress/e2e/search/search-results.cy.js b/tests/cypress/e2e/search/search-results.cy.js new file mode 100644 index 00000000..940c1bed --- /dev/null +++ b/tests/cypress/e2e/search/search-results.cy.js @@ -0,0 +1,17 @@ +/** + * Search results by phrase + */ + +const searchPhrases = ['Washington', 'United Nations'] + +searchPhrases.forEach(function (phrase) { + describe('Search results: ' + phrase, function () { + beforeEach(function () { + cy.visit('search', { qs: { q: phrase } }) + }) + + it('should have results', function () { + cy.get('.hsg-search-result > h3 > a').should('exist').and('not.be.empty') + }) + }) +}) diff --git a/tests/cypress/e2e/tags/all.cy.js b/tests/cypress/e2e/tags/all.cy.js new file mode 100644 index 00000000..b7dcd6a3 --- /dev/null +++ b/tests/cypress/e2e/tags/all.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – All Tags headline + */ + +describe('All Tags', function () { + beforeEach(function () { + cy.visit('tags/all') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('All Tags') + }) +}) diff --git a/tests/cypress/e2e/tags/buchanan.cy.js b/tests/cypress/e2e/tags/buchanan.cy.js new file mode 100644 index 00000000..80c22dd3 --- /dev/null +++ b/tests/cypress/e2e/tags/buchanan.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Buchanan person headline + */ + +describe('Tags Buchanan', function () { + beforeEach(function () { + cy.visit('tags/buchanan-james-p') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Buchanan, James (P)') + }) +}) diff --git a/tests/cypress/e2e/tags/jefferson.cy.js b/tests/cypress/e2e/tags/jefferson.cy.js new file mode 100644 index 00000000..9f3072db --- /dev/null +++ b/tests/cypress/e2e/tags/jefferson.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Jefferson person headline + */ + +describe('Tags Jefferson', function () { + beforeEach(function () { + cy.visit('tags/jefferson-thomas-s') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Jefferson, Thomas (S)') + }) +}) diff --git a/tests/cypress/e2e/tags/people.cy.js b/tests/cypress/e2e/tags/people.cy.js new file mode 100644 index 00000000..ba963e9b --- /dev/null +++ b/tests/cypress/e2e/tags/people.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – People headline + */ + +describe('Tags People', function () { + beforeEach(function () { + cy.visit('tags/people') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('People') + }) +}) diff --git a/tests/cypress/e2e/tags/places.cy.js b/tests/cypress/e2e/tags/places.cy.js new file mode 100644 index 00000000..a460cafc --- /dev/null +++ b/tests/cypress/e2e/tags/places.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Places headline + */ + +describe('Tags Places', function () { + beforeEach(function () { + cy.visit('tags/places') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Places') + }) +}) diff --git a/tests/cypress/e2e/tags/presidents.cy.js b/tests/cypress/e2e/tags/presidents.cy.js new file mode 100644 index 00000000..672e1588 --- /dev/null +++ b/tests/cypress/e2e/tags/presidents.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Presidents headline + */ + +describe('Tags Presidents', function () { + beforeEach(function () { + cy.visit('tags/presidents') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Presidents') + }) +}) diff --git a/tests/cypress/e2e/tags/secretaries-of-state.cy.js b/tests/cypress/e2e/tags/secretaries-of-state.cy.js new file mode 100644 index 00000000..db4d5db0 --- /dev/null +++ b/tests/cypress/e2e/tags/secretaries-of-state.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Secretaries of State headline + */ + +describe('Tags Secretaries', function () { + beforeEach(function () { + cy.visit('tags/secretaries-of-state') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Secretaries of State') + }) +}) diff --git a/tests/cypress/e2e/tags/tags.cy.js b/tests/cypress/e2e/tags/tags.cy.js new file mode 100644 index 00000000..3973da28 --- /dev/null +++ b/tests/cypress/e2e/tags/tags.cy.js @@ -0,0 +1,13 @@ +/** + * Tags main headline + */ + +describe('Tags', function () { + beforeEach(function () { + cy.visit('tags') + }) + + it('should display the headline', function () { + cy.get('#content-inner h1').first().normalizeHeadlineText('Tags') + }) +}) diff --git a/tests/cypress/e2e/tags/topics.cy.js b/tests/cypress/e2e/tags/topics.cy.js new file mode 100644 index 00000000..e1673839 --- /dev/null +++ b/tests/cypress/e2e/tags/topics.cy.js @@ -0,0 +1,13 @@ +/** + * Tags – Topics headline + */ + +describe('Tags Topics', function () { + beforeEach(function () { + cy.visit('tags/topics') + }) + + it('should display the headline', function () { + cy.get('#content-inner h2').first().normalizeHeadlineText('Topics') + }) +}) diff --git a/tests/cypress/e2e/ui-components/breadcrumb.cy.js b/tests/cypress/e2e/ui-components/breadcrumb.cy.js new file mode 100644 index 00000000..77b8bba5 --- /dev/null +++ b/tests/cypress/e2e/ui-components/breadcrumb.cy.js @@ -0,0 +1,66 @@ +/** + * Breadcrumb UI component (rdf, aria, styling) + */ + +describe('Breadcrumb', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus-history/chapter-4') + }) + + it('should contain a list with rdf metadata', function () { + cy.get('nav.hsg-breadcrumb ol') + .should('have.attr', 'typeof', 'BreadcrumbList') + .and('have.attr', 'vocab', 'http://schema.org/') + }) + + it('should contain list-items with rdf metadata', function () { + cy.get('nav.hsg-breadcrumb ol li') + .first() + .should('have.attr', 'typeof', 'ListItem') + .and('have.attr', 'property', 'itemListElement') + }) + + it('should contain links with rdf metadata', function () { + cy.get('nav.hsg-breadcrumb ol li a') + .first() + .should('have.attr', 'typeof', 'WebPage') + .and('have.attr', 'property', 'item') + }) + + it('should contain an aria-label in the nav element', function () { + cy.get('nav.hsg-breadcrumb').should('have.attr', 'aria-label', 'breadcrumbs') + }) + + it('should contain an aria-current attribute in current breadcrumb', function () { + cy.get('nav.hsg-breadcrumb a[aria-current="page"]').should('exist') + }) + + it('should highlight current breadcrumb in normal text color', function () { + cy.get('nav.hsg-breadcrumb a[aria-current="page"] span') + .should('have.css', 'color', 'rgb(33, 33, 33)') + }) +}) + +describe.skip('Breadcrumb on small screens', function () { + beforeEach(function () { + cy.visit('historicaldocuments/frus-history/chapter-4') + cy.viewport(480, 800) + cy.get('.hsg-breadcrumb__list-item:nth-last-child(2) .hsg-breadcrumb__link').should('be.visible') + }) + + it('should display the parent chapter breadcrumb', function () { + cy.get('.hsg-breadcrumb__list-item:nth-last-child(2) .hsg-breadcrumb__link span') + .invoke('html') + .then((html) => { + expect(html).to.equal('History of the Foreign Relations Series') + }) + }) + + it('should display a "back" arrow before the parent chapter breadcrumb', function () { + cy.get('.hsg-breadcrumb__list-item:nth-last-child(2) .hsg-breadcrumb__link').then(($el) => { + const style = window.getComputedStyle($el[0], '::before') + const mask = style.getPropertyValue('-webkit-mask') || style.getPropertyValue('mask') + expect(mask).to.contain('arrow_back.svg') + }) + }) +}) diff --git a/tests/cypress/fixtures/example.json b/tests/cypress/fixtures/example.json new file mode 100644 index 00000000..02e42543 --- /dev/null +++ b/tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js new file mode 100644 index 00000000..fc48e92b --- /dev/null +++ b/tests/cypress/support/commands.js @@ -0,0 +1,58 @@ +// *********************************************** +// Custom Cypress commands for hsg-shell +// *********************************************** +// +// NOTE: +// - All migrated specs currently use native Cypress APIs directly +// (cy.visit, cy.get, cy.contains, cy.viewport, etc.). +// - This file is intentionally minimal and kept as a stub so that +// future helpers can be added without changing cypress.config.cjs. +// +// If you add commands here, prefer patterns that do NOT mask what the +// test is doing. For example, avoid thin wrappers around: +// - cy.visit() +// - cy.get().invoke('text') +// - cy.get().should('have.css', ...) +// Instead, use those primitives directly in tests so failures produce +// clear, actionable error messages. + +const TAG_REGEX = /(\<|\/)[a-z]*>/gi + +/** + * Normalize headline text for comparison: strip HTML tags, collapse whitespace, + * trim, and normalize Unicode curly/smart quotes to straight quotes. + * @param {string} str - Raw text (e.g. from textContent) + * @returns {string} Normalized string + */ +function normalizeHeadlineText (str) { + if (str == null || typeof str !== 'string') return '' + let s = str.replace(TAG_REGEX, '').replace(/\s+/g, ' ').trim() + return s + .replace(/[""]/g, '"') + .replace(/['']/g, "'") + .replace(/\u2018|\u2019/g, "'") + .replace(/\u201C|\u201D/g, '"') +} + +/** + * Asserts that the first element in the subject has headline text equal to + * expectedTitle after normalization (strip tags, whitespace, Unicode quotes). + * Chain after cy.get(selector).first() + * + * @param {string} expectedTitle - Expected headline text (will be normalized) + * @param {object} [options] - Optional. stripAfter: string to trim actual text before this substring (e.g. 'Lesson Plans') + * @example + * cy.get('#content-inner h2').first().normalizeHeadlineText('Opening Remarks') + * cy.get('#content-inner div:nth-child(2) h2').first().normalizeHeadlineText('Introduction...', { stripAfter: 'Lesson Plans' }) + */ +Cypress.Commands.add('normalizeHeadlineText', { prevSubject: true }, (subject, expectedTitle, options) => { + const $el = subject.first() + const raw = $el[0].textContent || $el[0].innerText || '' + let normalized = normalizeHeadlineText(raw) + if (options && options.stripAfter && normalized.includes(options.stripAfter)) { + normalized = normalized.split(options.stripAfter)[0].trim() + } + const expected = normalizeHeadlineText(expectedTitle) + expect(normalized).to.equal(expected) +}) + diff --git a/tests/cypress/support/e2e.js b/tests/cypress/support/e2e.js new file mode 100644 index 00000000..6f504c2b --- /dev/null +++ b/tests/cypress/support/e2e.js @@ -0,0 +1,19 @@ +// *********************************************************** +// This example support/e2e.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js +require('./commands') + +// Import chai for assertions (matching wdio setup) +const { expect, assert } = require('chai') + +// Make assert available globally (matching wdio setup) +global.assert = assert \ No newline at end of file