diff --git a/.eslintrc.json b/.eslintrc.json
index 115eb698..6a27cb6a 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -11,8 +11,7 @@
"env": {
"es6": true,
"node": true,
- "browser": true,
- "cypress/globals": true
+ "browser": true
},
"parserOptions": {
"sourceType": "module",
@@ -65,6 +64,7 @@
}
],
"lines-between-class-members": "off",
+ "@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-namespace": "off",
"react/jsx-filename-extension": [0],
"import/extensions": [
@@ -100,16 +100,6 @@
}
]
}
- },
- {
- "files": ["cypress/**"],
- "plugins": ["cypress"],
- "rules": {
- "no-unused-vars": "warn"
- },
- "env": {
- "cypress/globals": true
- }
}
],
"settings": {
diff --git a/.github/workflows/browsers.yml b/.github/workflows/browsers.yml
deleted file mode 100644
index 4b2fe776..00000000
--- a/.github/workflows/browsers.yml
+++ /dev/null
@@ -1,131 +0,0 @@
-name: Browsers
-
-on:
- pull_request:
- paths:
- - 'src/**'
- - 'package-lock.json'
- - '.browserslistrc'
- - '.babelrc'
- - 'webpack.config.*'
- - 'public/index.html'
- - '.github/actions-scripts/__snapshots__/**'
- - '.github/workflows/browsers.yml'
-
-jobs:
- selenium:
- strategy:
- fail-fast: false
- matrix:
- os: [windows-latest, macos-latest]
- browser: [edge, firefox, safari, chrome]
- exclude:
- - os: windows-latest
- browser: safari
- - os: macos-latest
- browser: edge
- - os: macos-latest
- browser: chrome
- # Safari workaround is not working in Catalina
- - browser: safari
-
- runs-on: ${{ matrix.os }}
- steps:
- - name: Dump GitHub context
- env:
- GITHUB_CONTEXT: ${{ toJson(github) }}
- run: echo "$GITHUB_CONTEXT"
-
- - uses: actions/checkout@v4
- with:
- fetch-depth: 1
- - uses: actions/setup-node@v4
- with:
- node-version: 20
-
- - name: Cache node modules
- uses: actions/cache@v4
- with:
- path: ~/.npm
- key: ${{ runner.OS }}-build-${{ matrix.browser }}
- restore-keys: |
- ${{ runner.OS }}-build-${{ env.cache-name }}-
- ${{ runner.OS }}-build-
- ${{ runner.OS }}-
-
- - run: |
- npm ci --no-audit
- npm run build
- env:
- CYPRESS_INSTALL_BINARY: 0
- HUSKY_SKIP_INSTALL: true
-
- # install drivers
- - name: Enable Safari Driver
- run: |
- # Workaround for `sudo safardriver --enable` not working:
- # https://github.com/web-platform-tests/wpt/issues/19845
- # https://github.com/web-platform-tests/wpt/blob/master/tools/ci/azure/install_safari.yml
- mkdir -p ~/Library/WebDriver/
- curl https://raw.githubusercontent.com/web-platform-tests/wpt/master/tools/ci/azure/com.apple.Safari.plist -o ~/Library/WebDriver/com.apple.Safari.plist
- defaults write com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically 1
- # sudo safaridriver --enable
- if: matrix.browser == 'safari'
-
- - run: |
- brew install --cask firefox
- brew install geckodriver
- if: matrix.browser == 'firefox' && matrix.os == 'macos-latest'
-
- - run: echo "$env:GeckoWebDriver" >> $GITHUB_PATH
- if: matrix.browser == 'firefox' && matrix.os == 'windows-latest'
-
- - run: echo "$env:EdgeWebDriver" >> $GITHUB_PATH
- if: matrix.browser == 'edge' && matrix.os == 'windows-latest'
-
- - run: echo "$env:ChromeWebDriver" >> $GITHUB_PATH
- if: matrix.browser == 'chrome' && matrix.os == 'windows-latest'
-
- - run: npm i --no-optional --no-audit selenium-webdriver pixelmatch@5.3.0 pngjs
- - run: node .github/actions-scripts/selenium.cjs
- env:
- BROWSER: ${{ matrix.browser }}
- PORT: 0
- NODE_ENV: production # prevent watching
-
- - uses: actions/upload-artifact@v4
- if: failure()
- with:
- name: screenshot-${{ matrix.browser }}-${{ matrix.os }}
- path: screenshot
-
- puppeteer:
- runs-on: macos-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 1
- - name: Cache node modules
- uses: actions/cache@v4
- with:
- path: ~/.npm
- key: ${{ runner.OS }}-build-puppeteer
- restore-keys: |
- ${{ runner.OS }}-build-puppeteer
- - run: |
- npm ci --no-audit
- npm run build
- env:
- CYPRESS_INSTALL_BINARY: 0
- HUSKY_SKIP_INSTALL: true
- - run: npm i --no-optional --no-audit puppeteer@23.0.1 pixelmatch@5.3.0 pngjs@6.0.0
- - run: node .github/actions-scripts/puppeteer.cjs
- env:
- PORT: 0
- NODE_ENV: production # prevent watching
-
- - uses: actions/upload-artifact@v4
- if: failure()
- with:
- name: screenshot-puppeteer-darwin
- path: screenshot
diff --git a/.github/workflows/bundlesize.yml b/.github/workflows/bundlesize.yml
index d718931b..e5d901af 100644
--- a/.github/workflows/bundlesize.yml
+++ b/.github/workflows/bundlesize.yml
@@ -25,7 +25,6 @@ jobs:
npm ci
npm run build
env:
- CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
# we don't need to build here, as even minized assets expected to be commited
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
index 455b534f..c69e71b6 100644
--- a/.github/workflows/deploy-pages.yml
+++ b/.github/workflows/deploy-pages.yml
@@ -3,8 +3,8 @@ name: Deploy Pages
on:
release:
types: [published]
- workflow_dispatch:
-
+ workflow_dispatch:
+
jobs:
deploy-gh-pages:
runs-on: ubuntu-latest
@@ -22,7 +22,6 @@ jobs:
npm run build
rm -rf public/test
env:
- CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml
index bec38f47..18ee93fc 100644
--- a/.github/workflows/deployment.yml
+++ b/.github/workflows/deployment.yml
@@ -17,7 +17,6 @@ jobs:
registry-url: https://registry.npmjs.org/
- run: npm ci
env:
- CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
- run: npm publish
env:
diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
deleted file mode 100644
index 1da01bce..00000000
--- a/.github/workflows/e2e-tests.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-name: End-to-end tests
-
-on:
- pull_request:
- paths:
- - 'src/**'
- - 'package-lock.json'
- - '.browserslistrc'
- - '.babelrc'
- - 'webpack.config.*'
- - 'public/test/**'
- - 'cypress/**'
- - '.github/workflows/e2e-tests.yml'
-
-jobs:
- test-e2e:
- runs-on: ubuntu-latest
- env:
- CI: true
- TERM: xterm-256color
-
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 1
-
- - uses: actions/setup-node@v4
- with:
- node-version: 20
-
- - name: Cache node modules
- uses: actions/cache@v2
- with:
- path: ~/.npm
- key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.OS }}-build-${{ env.cache-name }}-
- ${{ runner.OS }}-build-
- ${{ runner.OS }}-
-
- - name: Get Cypress info
- id: cypress-info
- run: |
- echo ::set-output name=version::$(jq -r .devDependencies.cypress ./package.json)
- echo ::set-output name=cache::$(npm exec cypress cache path)
- env:
- CYPRESS_INSTALL_BINARY: 0
- - name: Cache Cypress cache
- uses: actions/cache@v2
- with:
- path: ${{ steps.cypress-info.outputs.cache }}
- key: ${{ runner.OS }}-cypress-${{ steps.cypress-info.outputs.version }}
- restore-keys: |
- ${{ runner.OS }}-cypress-${{ steps.cypress-info.outputs.version }}
-
- - name: Install dependencies
- run: npm ci --no-audit
- env:
- HUSKY_SKIP_INSTALL: true
-
- - name: run Cypress (with or without recording)
- # if we have ran out of free Cypress recordings, run Cypress with recording switched off
- run: npm exec -- run-p --race start cypress:ci || npm exec -- run-p --race start cypress:run
- env:
- NODE_ENV: production # prevent watching
- CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
- DEBUG: commit-info,cypress:server:record
- # https://docs.cypress.io/guides/guides/continuous-integration.html#Environment-variables
- COMMIT_INFO_BRANCH: ${{ github.head_ref }}
- COMMIT_INFO_AUTHOR: ${{ github.event.sender.login }}
- COMMIT_INFO_SHA: ${{ github.event.after }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index cd4d4d8f..f263e5de 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -23,7 +23,6 @@ jobs:
- name: Install dependencies
run: npm ci
env:
- CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
- name: run eslint
diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml
new file mode 100644
index 00000000..c8589879
--- /dev/null
+++ b/.github/workflows/playwright.yml
@@ -0,0 +1,59 @@
+name: Playwright Tests
+on:
+ push:
+ branches: [ playwright ]
+ pull_request:
+ branches: [ main, master ]
+jobs:
+ test:
+ timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [windows-latest, macos-latest, ubuntu-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: lts/*
+ - name: Cache node modules
+ uses: actions/cache@v4
+ with:
+ path: ~/.npm
+ key: ${{ runner.OS }}-build
+ restore-keys: |
+ ${{ runner.OS }}-build-
+ ${{ runner.OS }}-
+ - name: Install dependencies
+ run: npm ci --no-audit
+
+ - name: Get installed Playwright version
+ id: playwright-version
+ run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package-lock.json').dependencies['@playwright/test'].version)")" >> $GITHUB_ENV
+ - name: Cache playwright binaries
+ uses: actions/cache@v3
+ id: playwright-cache
+ with:
+ path: |
+ ~/.cache/ms-playwright
+ key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
+ - name: Install Playwright Browsers
+ run: npx playwright install --with-deps
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
+ - run: npx playwright install-deps
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
+
+ - name: Run Playwright tests
+ run: npx playwright test
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: screenshot-${{ matrix.os }}
+ path: screenshot
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 013d2c07..7b57f2b4 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -22,7 +22,6 @@ jobs:
- name: Install dependencies
run: npm ci --no-audit
env:
- CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
- run: npm run build
diff --git a/.gitignore b/.gitignore
index 7ae0f10e..91d3a6aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,5 +11,7 @@ tests/reports
tests/results
.nyc_output
coverage
-cypress/videos
-cypress/screenshots
+/test-results/
+/playwright-report/
+/blob-report/
+/playwright/.cache/
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6dba3119..7592f253 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,35 +12,5 @@
"webpack://Choices/*": "${workspaceFolder}/*"
}
},
- {
- "type": "node",
- "request": "launch",
- "name": "Cypress Current File",
- "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/cypress",
- "windows": {
- "runtimeExecutable": "${workspaceFolder}\\node_modules\\.bin\\cypress.cmd"
- },
- "runtimeArgs": [
- "run",
- "--headed",
- "--no-exit",
- "--browser=electron",
- "--port",
- "9898",
- "--spec"
- ],
- "protocol": "legacy",
- "port": 9898,
- "program": "${file}",
- "console": "integratedTerminal",
- "preLaunchTask": "buildAndWatch",
- "internalConsoleOptions": "openOnSessionStart",
- "timeout": 999999999999999,
- "autoAttachChildProcesses": false,
- "env": {
- "NODE_ENV": "test"
- // "DEBUG": "cypress:*"
- }
- }
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3b7eada7..5a669ecb 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -38,11 +38,6 @@
"npm.fetchOnlinePackageInfo": true,
"eslint.packageManager": "npm",
"json.schemas": [
- // Cypress related settings - https://docs.cypress.io/guides/tooling/intelligent-code-completion.html#Features-1
- {
- "fileMatch": ["cypress.json"],
- "url": "https://on.cypress.io/cypress.schema.json"
- },
// Husky config file
{
"fileMatch": [".huskyrc"],
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 5014b08f..aa3cc208 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -78,10 +78,5 @@
"script": "test:unit",
"group": "test"
},
- {
- "type": "npm",
- "script": "cypress:open",
- "isBackground": true
- }
]
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97833752..fd5b8cfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,9 @@
* Restructure end-to-end tests so html/script blocks are co-located to improve debugability
* Enable `@typescript-eslint/explicit-function-return-type` eslint rule
+### Chore
+* Switch e2e tests from `puppeteer`/`selenium`/`cypress` `playwright`
+
## [11.0.0-rc6] (2024-08-12)
### Features
diff --git a/README.md b/README.md
index 558890e2..c27f2540 100644
--- a/README.md
+++ b/README.md
@@ -1229,17 +1229,27 @@ To setup a local environment: clone this repo, navigate into its directory in a
`npm install`
+### playwright
+
+e2e (End-to-end) tests are implemented using playwright, which requires installing likely with OS support.
+
+`npx playwright install`
+`npx playwright install-deps `
+
+For JetBrain IDE's the `Test automation` plugin is recommended:
+https://www.jetbrains.com/help/phpstorm/playwright.html
+
### NPM tasks
| Task | Usage |
-| ------------------------- | ------------------------------------------------------------ |
+|---------------------------|--------------------------------------------------------------|
| `npm run start` | Fire up local server for development |
| `npm run test:unit` | Run sequence of tests once |
| `npm run test:unit:watch` | Fire up test server and re-test on file change |
| `npm run test:e2e` | Run sequence of e2e tests (with local server) |
| `npm run test` | Run both unit and e2e tests |
-| `npm run cypress:open` | Run Cypress e2e tests (GUI) |
-| `npm run cypress:run` | Run Cypress e2e tests (CLI) |
+| `npm run playwright:gui` | Run Playwright e2e tests (GUI) |
+| `npm run playwright:cli` | Run Playwright e2e tests (CLI) |
| `npm run js:build` | Compile Choices to an uglified JavaScript file |
| `npm run css:watch` | Watch SCSS files for changes. On a change, run build process |
| `npm run css:build` | Compile, minify and prefix SCSS files to CSS |
diff --git a/cypress/cypress.config.ts b/cypress/cypress.config.ts
deleted file mode 100644
index 43bb0078..00000000
--- a/cypress/cypress.config.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineConfig } from 'cypress';
-
-export default defineConfig({
- video: false,
- projectId: 'n7g5qp',
- e2e: {
- baseUrl: 'http://localhost:3001/test',
- specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
- },
-});
diff --git a/cypress/e2e/select-multiple.spec.ts b/cypress/e2e/select-multiple.spec.ts
deleted file mode 100644
index 3f95cac4..00000000
--- a/cypress/e2e/select-multiple.spec.ts
+++ /dev/null
@@ -1,1014 +0,0 @@
-describe('Choices - select multiple', () => {
- beforeEach(() => {
- cy.visit('/select-multiple', {
- onBeforeLoad(win) {
- cy.stub(win.console, 'warn').as('consoleWarn');
- },
- });
- });
-
- describe('scenarios', () => {
- describe('basic setup', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .focus();
- });
-
- describe('focusing on text input', () => {
- it('displays a dropdown of choices', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 4)
- .each(($choice, index) => {
- expect($choice.text().trim()).to.equal(`Choice ${index + 1}`);
- });
- });
-
- describe('pressing escape', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .wait(200) // Otherwise these tests are flaky
- .type('{esc}');
- });
-
- it('closes the dropdown', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('not.be.visible');
- });
-
- describe('typing more into the input', () => {
- it('re-opens the dropdown', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('test');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible');
- });
- });
- });
- });
-
- describe('selecting choices', () => {
- describe('selecting a single choice', () => {
- let selectedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .then(($choice) => {
- selectedChoiceText = $choice.text().trim();
- })
- .click();
- });
-
- it('allows selecting choices from dropdown', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($item) => {
- expect($item).to.contain(selectedChoiceText);
- });
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input[hidden]')
- .should(($select) => {
- expect($select.val()).to.contain(selectedChoiceText);
- });
- });
-
- it('removes selected choice from dropdown list', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .each(($choice) => {
- expect($choice.text().trim()).to.not.equal(selectedChoiceText);
- });
- });
- });
-
- describe('selecting all available choices', () => {
- beforeEach(() => {
- for (let index = 0; index <= 4; index++) {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
- }
- });
-
- it('displays "no choices to choose" prompt', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal('No choices to choose from');
- });
- });
- });
- });
-
- describe('removing choices', () => {
- let removedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .then(($choice) => {
- removedChoiceText = $choice.text().trim();
- })
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('{backspace}');
- });
-
- describe('on backspace', () => {
- it('removes last choice', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--multiple')
- .children()
- .should('have.length', 0);
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input[hidden]')
- .should(($select) => {
- const val = $select.val() || [];
- expect(val).to.not.contain(removedChoiceText);
- });
- });
- });
- });
-
- describe('searching choices', () => {
- describe('on input', () => {
- describe('searching by label', () => {
- it('displays choices filtered by inputted value', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('item 2');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 2');
- });
- });
- });
-
- describe('searching by value', () => {
- it('displays choices filtered by inputted value', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('find me');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 3');
- });
- });
- });
-
- describe('no results found', () => {
- it('displays "no results found" prompt', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('faergge');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal('No results found');
- });
- });
- });
- });
- });
-
- describe('disabling', () => {
- describe('on disable', () => {
- it('disables the search input', () => {
- cy.get('[data-test-hook=basic]')
- .find('button.disable')
- .focus()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
- });
- });
-
- describe('enabling', () => {
- describe('on enable', () => {
- it('enables the search input', () => {
- cy.get('[data-test-hook=basic]')
- .find('button.enable')
- .focus()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .should('not.be.disabled');
- });
- });
- });
- });
-
- describe('remove button', () => {
- /*
- {
- removeItemButton: true,
- };
- */
- beforeEach(() => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .click();
- });
-
- describe('on click', () => {
- it('removes respective choice', () => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .find('.choices__button')
- .focus()
- .click();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple')
- .children()
- .should('have.length', 0);
- });
- });
- });
-
- describe('disabled choice', () => {
- describe('selecting a disabled choice', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__list--dropdown .choices__item--disabled')
- .click();
- });
-
- it('does not select choice', () => {
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__list--multiple .choices__item')
- .should('have.length', 0);
- });
-
- it('keeps choice dropdown open', () => {
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__list--dropdown')
- .should('be.visible');
- });
- });
- });
-
- describe('adding items disabled', () => {
- /*
- {
- addItems: false,
- }
- */
- it('disables the search input', () => {
- cy.get('[data-test-hook=add-items-disabled]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=add-items-disabled]')
- .find('.choices')
- .click()
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('disabled via attribute', () => {
- it('disables the search input', () => {
- cy.get('[data-test-hook=disabled-via-attr]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=disabled-via-attr]')
- .find('.choices')
- .click()
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('selection limit', () => {
- /*
- {
- maxItemCount: 5,
- }
- */
- const selectionLimit = 5;
-
- beforeEach(() => {
- for (let index = 0; index < selectionLimit; index++) {
- cy.get('[data-test-hook=selection-limit]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=selection-limit]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
- }
- });
-
- it('displays "limit reached" prompt', () => {
- cy.get('[data-test-hook=selection-limit]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal(
- `Only ${selectionLimit} values can be added`,
- );
- });
- });
- });
-
- describe('prepend/append', () => {
- /*
- {
- prependValue: 'before-',
- appendValue: '-after',
- }
- */
- let selectedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .then(($choice) => {
- selectedChoiceText = $choice.text().trim();
- })
- .click();
- });
-
- it('prepends and appends value to inputted value', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.data('value')).to.equal(
- `before-${selectedChoiceText}-after`,
- );
- });
- });
-
- it('displays just the inputted value to the user', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text()).to.not.contain(
- `before-${selectedChoiceText}-after`,
- );
- expect($choice.text()).to.contain(selectedChoiceText);
- });
- });
- });
-
- describe('render choice limit', () => {
- /*
- {
- renderChoiceLimit: 1,
- }
- */
- it('only displays given number of choices in the dropdown', () => {
- cy.get('[data-test-hook=render-choice-limit]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 1);
- });
- });
-
- describe('search floor', () => {
- /*
- {
- searchFloor: 10,
- }
- */
- describe('on input', () => {
- describe('search floor not reached', () => {
- it('displays choices not filtered by inputted value', () => {
- const searchTerm = 'item 2';
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__input--cloned')
- .type(searchTerm);
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.not.contain(searchTerm);
- });
- });
- });
-
- describe('search floor reached', () => {
- it('displays choices filtered by inputted value', () => {
- const searchTerm = 'Choice 2';
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__input--cloned')
- .type(searchTerm);
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.contain(searchTerm);
- });
- });
- });
- });
- });
-
- describe('placeholder via empty option value', () => {
- describe('when no value has been inputted', () => {
- it('displays a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__input--cloned')
- .should('have.attr', 'placeholder', 'I am a placeholder');
- });
- });
-
- describe('when a value has been inputted', () => {
- it('does not display a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__input--cloned')
- .type('test')
- .should('not.have.value', 'I am a placeholder');
- });
- });
- });
-
- describe('placeholder via option attribute', () => {
- describe('when no value has been inputted', () => {
- it('displays a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__input--cloned')
- .should('have.attr', 'placeholder', 'I am a placeholder');
- });
- });
-
- describe('when a value has been inputted', () => {
- it('does not display a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__input--cloned')
- .type('test')
- .should('not.have.value', 'I am a placeholder');
- });
- });
- });
-
- describe('remote data', () => {
- beforeEach(() => {
- cy.reload(true);
- });
-
- describe('when loading data', () => {
- it('shows a loading message as a placeholder', () => {
- cy.get('[data-test-hook=remote-data]')
- .find('.choices__input--cloned')
- .should('have.attr', 'placeholder', 'Loading...');
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=remote-data]')
- .find('.choices')
- .click()
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('when data has loaded', () => {
- describe('opening the dropdown', () => {
- it('displays the loaded data', () => {
- cy.wait(1000);
- cy.get('[data-test-hook=remote-data]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 50)
- .each(($choice, index) => {
- expect($choice.text().trim()).to.equal(`Label ${index + 1}`);
- expect($choice.data('value')).to.equal(`Value ${index + 1}`);
- });
- });
- });
- });
- });
-
- describe('dropdown scrolling', () => {
- let choicesCount;
-
- beforeEach(() => {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .then(($choices) => {
- choicesCount = $choices.length;
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .focus();
- });
-
- it('highlights first choice on dropdown open', () => {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
-
- it('scrolls to next choice on down arrow', () => {
- for (let index = 1; index <= choicesCount; index++) {
- cy.wait(100);
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .invoke('text')
- .then((text) => {
- expect(text.trim()).to.equal(`Choice ${index}`);
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{downarrow}');
- }
- });
-
- it('scrolls up to previous choice on up arrow', () => {
- // scroll to last choice
- for (let index = 0; index < choicesCount; index++) {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{downarrow}');
- }
-
- // scroll up to first choice
- for (let index = choicesCount; index > 0; index--) {
- cy.wait(100); // allow for dropdown animation to finish
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .invoke('text')
- .then((text) => {
- expect(text.trim()).to.equal(`Choice ${index}`);
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{uparrow}');
- }
- });
- });
-
- describe('choice groups', () => {
- const choicesInGroup = 3;
- let groupValue;
-
- beforeEach(() => {
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .then(($group) => {
- groupValue = $group.text().trim();
- });
- });
-
- describe('selecting all choices in group', () => {
- it('removes group from dropdown', () => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .first()
- .click();
- }
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .should(($group) => {
- expect($group.text().trim()).to.not.equal(groupValue);
- });
- });
- });
-
- describe('deselecting all choices in group', () => {
- beforeEach(() => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .first()
- .click();
- }
- });
-
- it('shows group in dropdown', () => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus()
- .type('{backspace}');
- }
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .should(($group) => {
- expect($group.text().trim()).to.equal(groupValue);
- });
- });
- });
- });
-
- describe('some options with a group and some without', () => {
- it('Shows all options, whether they are in a group or not', () => {
- cy.get('[data-test-hook=mixed-groups]')
- .find('.choices__input--cloned')
- .focus();
- cy.get('[data-test-hook=mixed-groups]')
- .find('.choices__list--dropdown .choices__item')
- .should(($choices) => {
- expect($choices.length).to.equal(3);
- });
- });
- });
-
- describe('custom properties', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__input--cloned')
- .focus();
- });
-
- describe('on input', () => {
- it('filters choices based on custom property', () => {
- const data = [
- {
- country: 'Germany',
- city: 'Berlin',
- },
- {
- country: 'United Kingdom',
- city: 'London',
- },
- {
- country: 'Portugal',
- city: 'Lisbon',
- },
- ];
-
- data.forEach(({ country, city }) => {
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__input--cloned')
- .type(country);
-
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(city);
- });
-
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
- });
- });
-
- describe('custom properties via HTML', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices')
- .click();
- });
-
- describe('on input', () => {
- it('filters choices based on a string custom property', () => {
- const data = [
- {
- searchText: 'fantastic',
- label: 'Label Three',
- },
- ];
-
- data.forEach(({ searchText, label }) => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type(searchText);
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(label);
- });
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
-
- it('filters choices based on a JSON custom property', () => {
- const data = [
- {
- searchText: 'foo',
- label: 'Label Four',
- },
- ];
-
- data.forEach(({ searchText, label }) => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type(searchText);
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(label);
- });
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
- });
- });
-
- describe('non-string values', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=non-string-values]').find('.choices').click();
- });
-
- it('displays expected amount of choices in dropdown', () => {
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 4);
- });
-
- it('allows selecting choices from dropdown', () => {
- let $selectedChoice;
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .then(($choice) => {
- $selectedChoice = $choice;
- })
- .click();
-
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($item) => {
- expect($item.text().trim()).to.equal($selectedChoice.text().trim());
- });
- });
- });
-
- describe('within form', () => {
- describe('selecting choice', () => {
- describe('on enter key', () => {
- it('selects choice', () => {
- cy.get('[data-test-hook=within-form] form').then(($form) => {
- $form.submit(() => {
- // this will fail the test if the form submits
- throw new Error('Form submitted');
- });
- });
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices__input--cloned')
- .click()
- .type('{enter}');
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($item) => {
- expect($item).to.contain('Choice 1');
- });
- });
- });
- });
- });
-
- describe('dynamically setting choice by value', () => {
- const dynamicallySelectedChoiceValue = 'Choice 2';
-
- it('selects choice', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(
- dynamicallySelectedChoiceValue,
- );
- });
- });
-
- it('removes choice from dropdown list', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .each(($choice) => {
- expect($choice.text().trim()).to.not.equal(
- dynamicallySelectedChoiceValue,
- );
- });
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__input[hidden]')
- .should(($select) => {
- const val = $select.val() || [];
- expect(val).to.contain(dynamicallySelectedChoiceValue);
- });
- });
- });
-
- describe('searching by label only', () => {
- it('gets zero results when searching by value', () => {
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__input--cloned')
- .type('value1');
-
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('No results found');
- });
- });
-
- it('gets a result when searching by label', () => {
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__input--cloned')
- .type('label1');
-
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('label1');
- });
- });
- });
-
- describe('allow html', () => {
- describe('set to true', () => {
- it('does not show as text when selected', () => {
- cy.get('[data-test-hook=allowhtml-true]')
- .find('.choices__list--multiple .choices__item')
-
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
-
- it('does not show html as text in dropdown', () => {
- cy.get('[data-test-hook=allowhtml-true]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 2');
- });
- });
- });
-
- describe('set to false', () => {
- it('shows html as text when selected', () => {
- cy.get('[data-test-hook=allowhtml-false]')
- .find('.choices__list--multiple .choices__item')
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
-
- it('shows html as text', () => {
- cy.get('[data-test-hook=allowhtml-false]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 2');
- });
- });
- });
-
- describe('adding user-created choices', () => {
- it('allows the user to add choices', () => {
- const newChoice = 'New Choice';
-
- cy.get('[data-test-hook=add-choices]')
- .find('.choices__input--cloned')
- .type(newChoice)
- .type('{enter}');
-
- cy.get('[data-test-hook=add-choices]')
- .find('.choices__list--multiple')
- .last()
- .should($el => {
- expect($el).to.contain(newChoice);
- });
- });
- });
- });
- });
-});
diff --git a/cypress/e2e/select-one.spec.ts b/cypress/e2e/select-one.spec.ts
deleted file mode 100644
index dedd20e0..00000000
--- a/cypress/e2e/select-one.spec.ts
+++ /dev/null
@@ -1,1151 +0,0 @@
-describe('Choices - select one', () => {
- beforeEach(() => {
- cy.visit('/select-one', {
- onBeforeLoad(win) {
- cy.stub(win.console, 'warn').as('consoleWarn');
- },
- });
- });
-
- describe('scenarios', () => {
- describe('basic', () => {
- describe('focusing on container', () => {
- describe('pressing enter key', () => {
- it('toggles the dropdown', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices')
- .focus()
- .type('{enter}');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices')
- .focus()
- .type('{enter}');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('not.be.visible');
- });
- });
-
- describe('pressing an alpha-numeric key', () => {
- it('opens the dropdown and the input value', () => {
- const inputValue = 'test';
-
- cy.get('[data-test-hook=basic]')
- .find('.choices')
- .focus()
- .type(inputValue);
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .should('have.value', inputValue);
- });
- });
- });
-
- describe('selecting choices', () => {
- beforeEach(() => {
- // open dropdown
- cy.get('[data-test-hook=basic]').find('.choices').click();
- });
-
- const selectedChoiceText = 'Choice 1';
-
- it('allows selecting choices from dropdown', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($item) => {
- expect($item).to.contain(selectedChoiceText);
- });
- });
-
- it('does not remove selected choice from dropdown list', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($item) => {
- expect($item).to.contain(selectedChoiceText);
- });
- });
- });
-
- describe('searching choices', () => {
- beforeEach(() => {
- // open dropdown
- cy.get('[data-test-hook=basic]').find('.choices').click();
- });
-
- describe('on input', () => {
- describe('searching by label', () => {
- it('displays choices filtered by inputted value', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('item 2');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 2');
- });
- });
- });
-
- describe('searching by value', () => {
- it('displays choices filtered by inputted value', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('find me');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 3');
- });
- });
- });
-
- describe('no results found', () => {
- it('displays "no results found" prompt', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type('faergge');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal('No results found');
- });
- });
- });
- });
- });
-
- describe('disabling', () => {
- describe('on disable', () => {
- it('disables the search input', () => {
- cy.get('[data-test-hook=basic]')
- .find('button.disable')
- .focus()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
- });
- });
-
- describe('enabling', () => {
- describe('on enable', () => {
- it('enables the search input', () => {
- cy.get('[data-test-hook=basic]')
- .find('button.enable')
- .focus()
- .click();
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .should('not.be.disabled');
- });
- });
- });
- });
-
- describe('remove button', () => {
- /*
- {
- removeItemButton: true,
- }
- */
- beforeEach(() => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .click();
- });
-
- describe('remove button', () => {
- describe('on click', () => {
- let removedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--single .choices__item')
- .last()
- .then(($choice) => {
- removedChoiceText = $choice.text().trim();
- })
- .click();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--single .choices__item')
- .last()
- .find('.choices__button')
- .focus()
- .click();
- });
-
- it('removes selected choice', () => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--single')
- .children()
- .should('have.length', 0);
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__input[hidden]')
- .should(($select) => {
- const val = $select.val() || [];
-
- expect(val).to.not.contain(removedChoiceText);
- });
- });
- });
- });
- });
-
- describe('disabled choice', () => {
- describe('selecting a disabled choice', () => {
- let selectedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=disabled-choice]').click();
-
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__list--dropdown .choices__item--disabled')
- .then(($choice) => {
- selectedChoiceText = $choice.text().trim();
- })
- .click();
- });
-
- it('does not change selected choice', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text()).to.not.contain(selectedChoiceText);
- });
- });
-
- it('closes the dropdown list', () => {
- cy.get('[data-test-hook=disabled-choice]')
- .find('.choices__list--dropdown')
- .should('not.be.visible');
- });
- });
- });
-
- describe('adding items disabled', () => {
- /*
- {
- addItems: false,
- }
- */
- it('disables the search input', () => {
- cy.get('[data-test-hook=add-items-disabled]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=add-items-disabled]')
- .find('.choices')
- .click();
-
- cy.get('[data-test-hook=add-items-disabled]')
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('disabled via attribute', () => {
- it('disables the search input', () => {
- cy.get('[data-test-hook=disabled-via-attr]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=disabled-via-attr]').find('.choices').click();
-
- cy.get('[data-test-hook=disabled-via-attr]')
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('prepend/append', () => {
- /*
- {
- prependValue: 'before-',
- appendValue: '-after',
- };
- */
-
- let selectedChoiceText;
-
- beforeEach(() => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .then(($choice) => {
- selectedChoiceText = $choice.text().trim();
- })
- .click();
- });
-
- it('prepends and appends value to inputted value', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.data('value')).to.equal(
- `before-${selectedChoiceText}-after`,
- );
- });
- });
-
- it('displays just the inputted value to the user', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text()).to.not.contain(
- `before-${selectedChoiceText}-after`,
- );
- expect($choice.text()).to.contain(selectedChoiceText);
- });
- });
- });
-
- describe('render choice limit', () => {
- /*
- {
- renderChoiceLimit: 1
- }
- */
-
- it('only displays given number of choices in the dropdown', () => {
- cy.get('[data-test-hook=render-choice-limit]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 1);
- });
- });
-
- describe('search disabled', () => {
- /*
- {
- searchEnabled: false
- }
- */
- const selectedChoiceText = 'Choice 3';
-
- beforeEach(() => {
- cy.get('[data-test-hook=search-disabled]').find('.choices').click();
- });
-
- it('does not display a search input', () => {
- cy.get('[data-test-hook=search-disabled]')
- .find('.choices__input--cloned')
- .should('not.exist');
- });
-
- it('allows selecting choices from dropdown', () => {
- cy.get('[data-test-hook=search-disabled]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .last()
- .click();
-
- cy.get('[data-test-hook=search-disabled]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($item) => {
- expect($item).to.contain(selectedChoiceText);
- });
- });
- });
-
- describe('search floor', () => {
- /*
- {
- searchFloor: 10,
- };
- */
-
- describe('on input', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__input--cloned')
- .focus();
- });
-
- describe('search floor not reached', () => {
- it('displays choices not filtered by inputted value', () => {
- const searchTerm = 'item 2';
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__input--cloned')
- .type(searchTerm);
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.not.contain(searchTerm);
- });
- });
- });
-
- describe('search floor reached', () => {
- it('displays choices filtered by inputted value', () => {
- const searchTerm = 'Choice 2';
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__input--cloned')
- .type(searchTerm);
-
- cy.get('[data-test-hook=search-floor]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.contain(searchTerm);
- });
- });
- });
- });
- });
-
- describe('placeholder via empty option value', () => {
- describe('when no choice has been selected', () => {
- it('displays a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__list--single')
- .children()
- .first()
- .should('have.class', 'choices__placeholder')
- .and(($placeholder) => {
- expect($placeholder).to.contain('I am a placeholder');
- });
- });
- });
-
- describe('when a choice has been selected', () => {
- it('does not display a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
-
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__input--cloned')
- .should('not.have.value', 'I am a placeholder');
- });
- });
-
- describe('when choice list is open', () => {
- it('displays the placeholder choice first', () => {
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=placeholder-via-option-value]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should('have.class', 'choices__placeholder')
- .should('have.text', 'I am a placeholder');
- });
- });
- });
-
- describe('placeholder via option attribute', () => {
- describe('when no choice has been selected', () => {
- it('displays a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__list--single')
- .children()
- .first()
- .should('have.class', 'choices__placeholder')
- .and(($placeholder) => {
- expect($placeholder).to.contain('I am a placeholder');
- });
- });
- });
-
- describe('when a choice has been selected', () => {
- it('does not display a placeholder', () => {
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .click();
-
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__input--cloned')
- .should('not.have.value', 'I am a placeholder');
- });
- });
-
- describe('when choice list is open', () => {
- it('displays the placeholder choice first', () => {
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=placeholder-via-option-attr]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should('have.class', 'choices__placeholder')
- .should('have.text', 'I am a placeholder');
- });
- });
- });
-
- describe('remote data', () => {
- beforeEach(() => {
- cy.reload(true);
- });
-
- describe('when loading data', () => {
- it('shows a loading message as a placeholder', () => {
- cy.get('[data-test-hook=remote-data]')
- .find('.choices__list--single')
- .children()
- .should('have.length', 1)
- .first()
- .should('have.class', 'choices__placeholder')
- .and(($placeholder) => {
- expect($placeholder).to.contain('Loading...');
- });
- });
-
- describe('on click', () => {
- it('does not open choice dropdown', () => {
- cy.get('[data-test-hook=remote-data]')
- .find('.choices')
- .click()
- .find('.choices__list--dropdown')
- .should('not.have.class', 'is-active');
- });
- });
- });
-
- describe('when data has loaded', () => {
- describe('opening the dropdown', () => {
- it('displays the loaded data', () => {
- cy.wait(1000);
- cy.get('[data-test-hook=remote-data]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 51) // 50 choices + 1 placeholder choice
- .each(($choice, index) => {
- if (index === 0) {
- expect($choice.text().trim()).to.equal('I am a placeholder');
- } else {
- expect($choice.text().trim()).to.equal(`Label ${index}`);
- expect($choice.data('value')).to.equal(`Value ${index}`);
- }
- });
- });
- });
- });
- });
-
- describe('scrolling dropdown', () => {
- let choicesCount;
-
- beforeEach(() => {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .then(($choices) => {
- choicesCount = $choices.length;
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]').find('.choices').click();
- });
-
- it('highlights first choice on dropdown open', () => {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
-
- it('scrolls to next choice on down arrow', () => {
- for (let index = 0; index < choicesCount; index++) {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(`Choice ${index + 1}`);
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{downarrow}');
- }
- });
-
- it('scrolls up to previous choice on up arrow', () => {
- // scroll to last choice
- for (let index = 0; index < choicesCount; index++) {
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{downarrow}');
- }
-
- // scroll up to first choice
- for (let index = choicesCount; index > 0; index--) {
- cy.wait(100); // allow for dropdown animation to finish
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__list--dropdown .choices__list .is-highlighted')
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(`Choice ${index}`);
- });
-
- cy.get('[data-test-hook=scrolling-dropdown]')
- .find('.choices__input--cloned')
- .type('{uparrow}');
- }
- });
- });
-
- describe('choice groups', () => {
- const choicesInGroup = 3;
- let groupValue;
-
- beforeEach(() => {
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .then(($group) => {
- groupValue = $group.text().trim();
- });
- });
-
- describe('selecting all choices in group', () => {
- it('removes group from dropdown', () => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .first()
- .click();
- }
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .should(($group) => {
- expect($group.text().trim()).to.not.equal(groupValue);
- });
- });
- });
-
- describe('deselecting all choices in group', () => {
- beforeEach(() => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus();
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__item')
- .first()
- .click();
- }
- });
-
- it('shows group in dropdown', () => {
- for (let index = 0; index < choicesInGroup; index++) {
- cy.get('[data-test-hook=groups]')
- .find('.choices__input--cloned')
- .focus()
- .type('{backspace}');
- }
-
- cy.get('[data-test-hook=groups]')
- .find('.choices__list--dropdown .choices__list .choices__group')
- .first()
- .should(($group) => {
- expect($group.text().trim()).to.equal(groupValue);
- });
- });
- });
- });
-
- describe('parent/child', () => {
- describe('selecting "Parent choice 2"', () => {
- it('enables the child Choices instance', () => {
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(1)
- .should('have.class', 'is-disabled');
-
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(0)
- .click();
-
- cy.get('[data-test-hook=parent-child]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .eq(1)
- .click();
-
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(1)
- .should('not.have.class', 'is-disabled');
- });
- });
-
- describe('changing selection from "Parent choice 2" to something else', () => {
- it('disables the child Choices instance', () => {
- // open parent instance and select second choice
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(0)
- .click()
- .find('.choices__list--dropdown .choices__list')
- .children()
- .eq(1)
- .click();
-
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(1)
- .should('not.have.class', 'is-disabled');
-
- // open parent instance and select third choice
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(0)
- .click()
- .find('.choices__list--dropdown .choices__list')
- .children()
- .eq(2)
- .click();
-
- cy.get('[data-test-hook=parent-child]')
- .find('.choices')
- .eq(1)
- .should('have.class', 'is-disabled');
- });
- });
- });
-
- describe('custom properties', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=custom-properties]').find('.choices').click();
- });
-
- describe('on input', () => {
- it('filters choices based on custom property', () => {
- const data = [
- {
- country: 'Germany',
- city: 'Berlin',
- },
- {
- country: 'United Kingdom',
- city: 'London',
- },
- {
- country: 'Portugal',
- city: 'Lisbon',
- },
- ];
-
- data.forEach(({ country, city }) => {
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__input--cloned')
- .type(country);
-
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(city);
- });
-
- cy.get('[data-test-hook=custom-properties]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
- });
- });
-
- describe('custom properties via HTML', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices')
- .click();
- });
-
- describe('on input', () => {
- it('filters choices based on a string custom property', () => {
- const data = [
- {
- searchText: 'fantastic',
- label: 'Label Three',
- },
- ];
-
- data.forEach(({ searchText, label }) => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type(searchText);
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(label);
- });
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
-
- it('filters choices based on a JSON custom property', () => {
- const data = [
- {
- searchText: 'foo',
- label: 'Label Four',
- },
- ];
-
- data.forEach(({ searchText, label }) => {
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type(searchText);
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(label);
- });
-
- cy.get('[data-test-hook=custom-properties-html]')
- .find('.choices__input--cloned')
- .type('{selectall}{del}');
- });
- });
- });
- });
-
- describe('non-string values', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=non-string-values]').find('.choices').click();
- });
-
- it('displays expected amount of choices in dropdown', () => {
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 4);
- });
-
- it('allows selecting choices from dropdown', () => {
- let $selectedChoice;
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .then(($choice) => {
- $selectedChoice = $choice;
- })
- .click();
-
- cy.get('[data-test-hook=non-string-values]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($item) => {
- expect($item.text().trim()).to.equal($selectedChoice.text().trim());
- });
- });
- });
-
- describe('within form', () => {
- describe('selecting choice', () => {
- describe('on enter key', () => {
- it('does not submit form', () => {
- cy.get('[data-test-hook=within-form] form').then(($form) => {
- $form.submit(() => {
- // this will fail the test if the form submits
- throw new Error('Form submitted');
- });
- });
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices')
- .click()
- .find('.choices__input--cloned')
- .type('{enter}');
-
- cy.get('[data-test-hook=within-form]').find('.choices').click();
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($item) => {
- expect($item).to.contain('Choice 1');
- });
- });
- });
- });
- });
-
- describe('dynamically setting choice by value', () => {
- const dynamicallySelectedChoiceValue = 'Choice 2';
-
- it('selects choice', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__list--single .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(
- dynamicallySelectedChoiceValue,
- );
- });
- });
-
- it('does not remove choice from dropdown list', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__list--dropdown .choices__list')
- .then(($choicesList) => {
- expect($choicesList).to.contain(dynamicallySelectedChoiceValue);
- });
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=set-choice-by-value]')
- .find('.choices__input[hidden]')
- .should(($select) => {
- const val = $select.val() || [];
- expect(val).to.contain(dynamicallySelectedChoiceValue);
- });
- });
- });
-
- describe('searching by label only', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=search-by-label]').find('.choices').click();
- });
-
- it('gets zero results when searching by value', () => {
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__input--cloned')
- .type('value1');
-
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('No results found');
- });
- });
-
- it('gets a result when searching by label', () => {
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__input--cloned')
- .type('label1');
-
- cy.get('[data-test-hook=search-by-label]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('label1');
- });
- });
- });
-
- describe('disabling first choice via options', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=disabled-first-choice-via-options]')
- .find('.choices')
- .click();
- });
-
- let disabledValue;
-
- it('disables the first choice', () => {
- cy.get('[data-test-hook=disabled-first-choice-via-options]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should('have.class', 'choices__item--disabled')
- .then(($choice) => {
- disabledValue = $choice.val();
- });
- });
-
- it('selects the first enabled choice', () => {
- cy.get('[data-test-hook=disabled-first-choice-via-options]')
- .find('.choices__input[hidden]')
- .then(($option) => {
- expect($option.text().trim()).to.not.equal(disabledValue);
- });
-
- cy.get('[data-test-hook=disabled-first-choice-via-options]')
- .find('.choices__item.choices__item--selectable')
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.not.equal(disabledValue);
- });
- });
- });
-
- describe('allow html', () => {
- describe('set to true', () => {
- it('does not show html as text', () => {
- cy.get('[data-test-hook=allowhtml-true]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
- });
-
- describe('set to false', () => {
- it('shows html as text', () => {
- cy.get('[data-test-hook=allowhtml-false]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Choice 1');
- });
- });
- });
- });
-
- describe('re-initialising a choices instance', () => {
- it('preserves the choices list', () => {
- cy.get('[data-test-hook=new-destroy-init]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 3);
-
- cy.get('[data-test-hook=new-destroy-init]')
- .find('button.destroy')
- .click();
- cy.get('[data-test-hook=new-destroy-init]').find('button.init').click();
-
- cy.get('[data-test-hook=new-destroy-init]')
- .find('.choices__list--dropdown .choices__list')
- .children()
- .should('have.length', 3);
- });
- });
-
- describe('destroying the choices instance', () => {
- it('preserves the original select element', () => {
- cy.get('[data-test-hook=new-destroy-init]')
- .find('button.destroy')
- .click();
-
- cy.get('[data-test-hook=new-destroy-init]')
- .find('select')
- .children()
- .should('have.length', 3);
- });
- });
-
- describe('adding user-created choices', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=add-choices]').find('.choices').click();
- });
-
- it('allows the user to add choices', () => {
- const newChoice = 'New Choice';
-
- cy.get('[data-test-hook=add-choices]')
- .find('.choices__input--cloned')
- .type(newChoice)
- .type('{enter}');
-
- cy.get('[data-test-hook=add-choices]')
- .find('.choices__list--single .choices__item')
- .should(($el) => {
- expect($el).to.contain(newChoice);
- });
- });
- });
- });
-});
diff --git a/cypress/e2e/text.spec.ts b/cypress/e2e/text.spec.ts
deleted file mode 100644
index 98eb6247..00000000
--- a/cypress/e2e/text.spec.ts
+++ /dev/null
@@ -1,413 +0,0 @@
-describe('Choices - text element', () => {
- beforeEach(() => {
- cy.visit('/text', {
- onBeforeLoad(win) {
- cy.stub(win.console, 'warn').as('consoleWarn');
- },
- });
- });
-
- describe('scenarios', () => {
- const textInput = 'testing';
-
- describe('basic', () => {
- describe('adding items', () => {
- it('allows me to input items', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type(textInput)
- .type('{enter}');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($el) => {
- expect($el).to.contain(textInput);
- });
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type(textInput)
- .type('{enter}');
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__input[hidden]')
- .should('have.value', textInput);
- });
-
- describe('inputting data', () => {
- it('shows a dropdown prompt', () => {
- cy.get('[data-test-hook=basic]')
- .find('.choices__input--cloned')
- .type(textInput);
-
- cy.get('[data-test-hook=basic]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal(
- `Press Enter to add "${textInput}"`,
- );
- });
- });
- });
- });
- });
-
- describe('editing items', () => {
- beforeEach(() => {
- for (let index = 0; index < 3; index++) {
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__input--cloned')
- .type(textInput)
- .type('{enter}');
- }
- });
-
- describe('on back space', () => {
- it('allows me to change my entry', () => {
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__input--cloned')
- .type('{backspace}')
- .type('-edited')
- .type('{enter}');
-
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.data('value')).to.equal(`${textInput}-edited`);
- });
- });
- });
-
- describe('on cmd+a', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__input--cloned')
- .type('{cmd}a');
- });
-
- it('highlights all items', () => {
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__list--multiple .choices__item')
- .each(($choice) => {
- expect($choice.hasClass('is-highlighted')).to.equal(true);
- });
- });
-
- describe('on backspace', () => {
- it('clears all inputted values', () => {
- // two backspaces are needed as Cypress has an issue where
- // it will also insert an 'a' character into the text input
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__input--cloned')
- .type('{backspace}{backspace}');
-
- cy.get('[data-test-hook=edit-items]')
- .find('.choices__list--multiple .choices__item')
- .should('have.length', 0);
- });
- });
- });
- });
-
- describe('remove button', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__input--cloned')
- .type(`${textInput}`)
- .type('{enter}');
- });
-
- describe('on click', () => {
- it('removes respective choice', () => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple')
- .children()
- .should(($items) => {
- expect($items.length).to.equal(1);
- });
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .find('.choices__button')
- .focus()
- .click();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple .choices__item')
- .should(($items) => {
- expect($items.length).to.equal(0);
- });
- });
-
- it('updates the value of the original input', () => {
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .find('.choices__button')
- .focus()
- .click();
-
- cy.get('[data-test-hook=remove-button]')
- .find('.choices__input[hidden]')
- .then(($input) => {
- expect($input.val()).to.not.contain(textInput);
- });
- });
- });
- });
-
- describe('unique values only', () => {
- describe('unique values', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=unique-values]')
- .find('.choices__input--cloned')
- .type(`${textInput}`)
- .type('{enter}')
- .type(`${textInput}`)
- .type('{enter}');
- });
-
- it('only allows me to input unique values', () => {
- cy.get('[data-test-hook=unique-values]')
- .find('.choices__list--multiple')
- .first()
- .children()
- .should(($items) => {
- expect($items.length).to.equal(1);
- });
- });
-
- describe('inputting a non-unique value', () => {
- it('displays dropdown prompt', () => {
- cy.get('[data-test-hook=unique-values]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal(
- 'Only unique values can be added',
- );
- });
- });
- });
- });
- });
-
- describe('input limit', () => {
- const inputLimit = 5;
- beforeEach(() => {
- for (let index = 0; index < inputLimit + 1; index++) {
- cy.get('[data-test-hook=input-limit]')
- .find('.choices__input--cloned')
- .type(`${textInput} + ${index}`)
- .type('{enter}');
- }
- });
-
- it('does not let me input more than 5 choices', () => {
- cy.get('[data-test-hook=input-limit]')
- .find('.choices__list--multiple')
- .first()
- .children()
- .should(($items) => {
- expect($items.length).to.equal(inputLimit);
- });
- });
-
- describe('reaching input limit', () => {
- it('displays dropdown prompt', () => {
- cy.get('[data-test-hook=input-limit]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal(
- `Only ${inputLimit} values can be added`,
- );
- });
- });
- });
- });
-
- describe('add item filter', () => {
- describe('inputting a value that satisfies the filter', () => {
- const input = 'joe@bloggs.com';
-
- it('allows me to add choice', () => {
- cy.get('[data-test-hook=add-item-filter]')
- .find('.choices__input--cloned')
- .type(input)
- .type('{enter}');
-
- cy.get('[data-test-hook=add-item-filter]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal(input);
- });
- });
- });
-
- describe('inputting a value that does not satisfy the regex', () => {
- it('displays dropdown prompt', () => {
- cy.get('[data-test-hook=add-item-filter]')
- .find('.choices__input--cloned')
- .type(`this is not an email address`)
- .type('{enter}');
-
- cy.get('[data-test-hook=add-item-filter]')
- .find('.choices__list--dropdown')
- .should('be.visible')
- .should(($dropdown) => {
- const dropdownText = $dropdown.text().trim();
- expect(dropdownText).to.equal(
- 'Only values matching specific conditions can be added',
- );
- });
- });
- });
- });
-
- describe('prepend/append', () => {
- beforeEach(() => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__input--cloned')
- .type(textInput)
- .type('{enter}');
- });
-
- it('prepends and appends value to inputted value', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.data('value')).to.equal(`before-${textInput}-after`);
- });
- });
-
- it('displays just the inputted value to the user', () => {
- cy.get('[data-test-hook=prepend-append]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text()).to.not.contain(`before-${textInput}-after`);
- expect($choice.text()).to.contain(textInput);
- });
- });
- });
-
- describe('adding items disabled', () => {
- it('does not allow me to input data', () => {
- cy.get('[data-test-hook=adding-items-disabled]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
- });
-
- describe('disabled via attribute', () => {
- it('does not allow me to input data', () => {
- cy.get('[data-test-hook=disabled-via-attr]')
- .find('.choices__input--cloned')
- .should('be.disabled');
- });
- });
-
- describe('pre-populated choices', () => {
- it('pre-populates choices', () => {
- cy.get('[data-test-hook=prepopulated]')
- .find('.choices__list--multiple .choices__item')
- .should(($choices) => {
- expect($choices.length).to.equal(2);
- });
-
- cy.get('[data-test-hook=prepopulated]')
- .find('.choices__list--multiple .choices__item')
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Josh Johnson');
- });
-
- cy.get('[data-test-hook=prepopulated]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Joe Bloggs');
- });
- });
- });
-
- describe('placeholder', () => {
- /*
- {
- placeholder: true,
- placeholderValue: 'I am a placeholder',
- }
- */
- describe('when no value has been inputted', () => {
- it('displays a placeholder', () => {
- cy.get('[data-test-hook=placeholder]')
- .find('.choices__input--cloned')
- .should('have.attr', 'placeholder', 'I am a placeholder');
- });
- });
- });
-
- describe('allow html', () => {
- describe('set to true', () => {
- it('does not show html as text', () => {
- cy.get('[data-test-hook=allowhtml-true]')
- .find('.choices__list--multiple .choices__item')
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Mason Rogers');
- });
- });
- });
-
- describe('set to false', () => {
- it('shows html as text', () => {
- cy.get('[data-test-hook=allowhtml-false]')
- .find('.choices__list--multiple .choices__item')
- .first()
- .should(($choice) => {
- expect($choice.text().trim()).to.equal('Mason Rogers');
- });
- });
- });
- });
-
- describe('within form', () => {
- describe('inputting item', () => {
- describe('on enter key', () => {
- it('does not submit form', () => {
- cy.get('[data-test-hook=within-form] form').then(($form) => {
- $form.submit(() => {
- // this will fail the test if the form submits
- throw new Error('Form submitted');
- });
- });
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices__input--cloned')
- .type(textInput)
- .type('{enter}');
-
- cy.get('[data-test-hook=within-form]')
- .find('.choices__list--multiple .choices__item')
- .last()
- .should(($el) => {
- expect($el).to.contain(textInput);
- });
- });
- });
- });
- });
- });
-});
diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json
deleted file mode 100644
index da18d935..00000000
--- a/cypress/fixtures/example.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "Using fixtures to represent data",
- "email": "hello@cypress.io",
- "body": "Fixtures are a great way to mock data for responses to routes"
-}
\ No newline at end of file
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
deleted file mode 100644
index c1f5a772..00000000
--- a/cypress/support/commands.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// ***********************************************
-// This example commands.js shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add("login", (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This is will overwrite an existing command --
-// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js
deleted file mode 100644
index 37a498fb..00000000
--- a/cypress/support/e2e.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// ***********************************************************
-// This example support/index.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 change the location of this file or turn off
-// automatically serving support files with the
-// 'supportFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.js using ES2015 syntax:
-import './commands';
-
-// Alternatively you can use CommonJS syntax:
-// require('./commands')
diff --git a/cypress/tsconfig.json b/e2e/tsconfig.json
similarity index 67%
rename from cypress/tsconfig.json
rename to e2e/tsconfig.json
index 1e24a936..833c6bb1 100644
--- a/cypress/tsconfig.json
+++ b/e2e/tsconfig.json
@@ -3,20 +3,21 @@
"module": "es6",
"lib": ["es2017", "dom"],
"target": "es5",
- "moduleResolution": "node",
+ "moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"strict": false,
"noImplicitAny": false,
- "declaration": true,
"allowJs": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"newLine": "lf",
- "types": ["cypress", "node"],
- "declarationDir": "../public/types/cypress"
+ "declaration": false,
+ "declarationMap": false,
+ "types": [],
},
- "include": ["."]
-}
\ No newline at end of file
+ "include": [".", "../src"],
+ "exclude": ["**/node_modules", "**/public"]
+}
diff --git a/jsconfig.json b/jsconfig.json
index d5c3a53e..d4f0681f 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -3,7 +3,7 @@
"checkJs": true,
"target": "es2020",
"lib": ["esnext", "dom"],
- "types": ["cypress"],
+ "types": [],
"strict": true,
"moduleResolution": "node",
/* Additional Checks */
diff --git a/package-lock.json b/package-lock.json
index 4e6db4ee..3e40e1c9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "choices.js",
- "version": "11.0.0-rc5",
+ "version": "11.0.0-rc6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "choices.js",
- "version": "11.0.0-rc5",
+ "version": "11.0.0-rc6",
"license": "MIT",
"dependencies": {
"fuse.js": "^7.0.0"
@@ -17,6 +17,7 @@
"@babel/plugin-transform-object-rest-spread": "^7.24.7",
"@babel/preset-env": "^7.25.3",
"@babel/preset-typescript": "^7.24.7",
+ "@playwright/test": "^1.46.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-eslint": "^9.0.5",
"@rollup/plugin-node-resolve": "^15.2.3",
@@ -24,6 +25,7 @@
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/chai": "^4.3.17",
+ "@types/node": "^22.2.0",
"@types/sinon": "^17.0.3",
"@types/sinon-chai": "^3.2.12",
"@vitest/coverage-v8": "^2.0.5",
@@ -31,13 +33,11 @@
"bundlesize": "^0.18.2",
"chai": "^5.1.1",
"csso-cli": "^4.0.2",
- "cypress": "^13.13.2",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-compat": "6.0.0",
- "eslint-plugin-cypress": "^3.4.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-sort-class-members": "^1.20.0",
@@ -1951,17 +1951,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@colors/colors": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
- "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.1.90"
- }
- },
"node_modules/@csstools/css-parser-algorithms": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz",
@@ -2052,72 +2041,6 @@
"postcss-selector-parser": "^6.0.13"
}
},
- "node_modules/@cypress/request": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz",
- "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==",
- "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": "~2.3.2",
- "http-signature": "~1.3.6",
- "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.10.4",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "^4.1.3",
- "tunnel-agent": "^0.6.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@cypress/request/node_modules/form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "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/@dual-bundle/import-meta-resolve": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
@@ -3114,6 +3037,22 @@
"url": "https://opencollective.com/unts"
}
},
+ "node_modules/@playwright/test": {
+ "version": "1.46.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz",
+ "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.46.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz",
@@ -3616,12 +3555,11 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.1.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz",
- "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==",
+ "version": "22.2.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz",
+ "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==",
"dev": true,
"license": "MIT",
- "optional": true,
"dependencies": {
"undici-types": "~6.13.0"
}
@@ -3661,24 +3599,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/sizzle": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
- "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/yauzl": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
- "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
@@ -4082,20 +4002,6 @@
"node": ">= 14"
}
},
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -4123,22 +4029,6 @@
"node": ">=6"
}
},
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -4183,27 +4073,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/arch": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
- "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
@@ -4370,26 +4239,6 @@
"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": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -4420,13 +4269,6 @@
"node": ">=8"
}
},
- "node_modules/async": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
- "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -4434,16 +4276,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
"node_modules/atomic-sleep": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
@@ -4521,23 +4353,6 @@
"queue-microtask": "^1.1.2"
}
},
- "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.1",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz",
- "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/axios": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz",
@@ -4620,16 +4435,6 @@
],
"license": "MIT"
},
- "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/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -4670,20 +4475,6 @@
"node": ">= 6"
}
},
- "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/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
@@ -4874,16 +4665,6 @@
"ieee754": "^1.1.13"
}
},
- "node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -4955,16 +4736,6 @@
"node": ">=8"
}
},
- "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",
@@ -5042,13 +4813,6 @@
],
"license": "CC-BY-4.0"
},
- "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/chai": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
@@ -5091,16 +4855,6 @@
"node": ">= 16"
}
},
- "node_modules/check-more-types": {
- "version": "2.24.0",
- "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
- "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -5140,22 +4894,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/clap": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/clap/-/clap-3.1.1.tgz",
@@ -5170,62 +4908,6 @@
"npm": ">=7.0.0"
}
},
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cli-table3": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz",
- "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": "10.* || >= 12.*"
- },
- "optionalDependencies": {
- "@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/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -5305,16 +4987,6 @@
"node": ">= 6"
}
},
- "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/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -5526,196 +5198,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cypress": {
- "version": "13.13.2",
- "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz",
- "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "@cypress/request": "^3.0.1",
- "@cypress/xvfb": "^1.2.4",
- "@types/sinonjs__fake-timers": "8.1.1",
- "@types/sizzle": "^2.3.2",
- "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",
- "check-more-types": "^2.24.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",
- "getos": "^3.2.1",
- "is-ci": "^3.0.1",
- "is-installed-globally": "~0.4.0",
- "lazy-ass": "^1.6.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",
- "semver": "^7.5.3",
- "supports-color": "^8.1.1",
- "tmp": "~0.2.3",
- "untildify": "^4.0.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "cypress": "bin/cypress"
- },
- "engines": {
- "node": "^16.0.0 || ^18.0.0 || >=20.0.0"
- }
- },
- "node_modules/cypress/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/cypress/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/cypress/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/cypress/node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cypress/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/cypress/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cypress/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "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/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/cypress/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "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-urls": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
@@ -5800,13 +5282,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/dayjs": {
- "version": "1.11.12",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz",
- "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
@@ -6025,17 +5500,6 @@
"dev": true,
"license": "MIT"
},
- "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/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -6087,20 +5551,6 @@
"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/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -6556,48 +6006,6 @@
"node": ">=10"
}
},
- "node_modules/eslint-plugin-cypress": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-3.4.0.tgz",
- "integrity": "sha512-Rrrr3Ri6wHqzrRr+TyUV7bDS4UnMMrFY1R1PP2F7XdGfe9txDC6lQEshyoNOWqGoPkbbeDm1x1XPc/adxemsnA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "globals": "^13.20.0"
- },
- "peerDependencies": {
- "eslint": ">=7"
- }
- },
- "node_modules/eslint-plugin-cypress/node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint-plugin-cypress/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/eslint-plugin-import": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
@@ -7051,13 +6459,6 @@
"node": ">= 0.6"
}
},
- "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/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
@@ -7065,43 +6466,6 @@
"dev": true,
"license": "MIT"
},
- "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/executable": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
- "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pify": "^2.2.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -7254,44 +6618,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/extract-zip": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
- "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "debug": "^4.1.1",
- "get-stream": "^5.1.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "extract-zip": "cli.js"
- },
- "engines": {
- "node": ">= 10.17.0"
- },
- "optionalDependencies": {
- "@types/yauzl": "^2.9.1"
- }
- },
- "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/fast-content-type-parse": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz",
@@ -7466,16 +6792,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/fd-slicer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pend": "~1.2.0"
- }
- },
"node_modules/femtocolor": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/femtocolor/-/femtocolor-2.0.3.tgz",
@@ -7483,22 +6799,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/figures": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
- "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -7697,16 +6997,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "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.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -7763,22 +7053,6 @@
"dev": true,
"license": "MIT"
},
- "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/fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@@ -8014,22 +7288,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "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/get-symbol-description": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
@@ -8048,26 +7306,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/getos": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
- "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "async": "^3.2.0"
- }
- },
- "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/github-build": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/github-build/-/github-build-1.2.4.tgz",
@@ -8156,22 +7394,6 @@
"node": "*"
}
},
- "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-modules": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
@@ -8502,21 +7724,6 @@
"node": ">= 14"
}
},
- "node_modules/http-signature": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
- "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "jsprim": "^2.0.2",
- "sshpk": "^1.14.1"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
@@ -8531,16 +7738,6 @@
"node": ">= 14"
}
},
- "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/husky": {
"version": "9.1.4",
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.4.tgz",
@@ -8655,16 +7852,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -8684,16 +7871,6 @@
"dev": true,
"license": "ISC"
},
- "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/internal-slot": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
@@ -8815,19 +7992,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-ci": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
- "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ci-info": "^3.2.0"
- },
- "bin": {
- "is-ci": "bin.js"
- }
- },
"node_modules/is-core-module": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
@@ -8919,23 +8083,6 @@
"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-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
@@ -9042,19 +8189,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-string": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
@@ -9103,26 +8237,6 @@
"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-unicode-supported": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
- "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -9150,13 +8264,6 @@
"dev": true,
"license": "ISC"
},
- "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/istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
@@ -9314,13 +8421,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "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/jsdom": {
"version": "24.1.1",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz",
@@ -9396,13 +8496,6 @@
"dev": true,
"license": "MIT"
},
- "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": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -9417,13 +8510,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -9450,22 +8536,6 @@
"graceful-fs": "^4.1.6"
}
},
- "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/just-extend": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz",
@@ -9500,16 +8570,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/lazy-ass": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
- "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "> 0.8"
- }
- },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -10044,34 +9104,6 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "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",
@@ -10114,13 +9146,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -10149,13 +9174,6 @@
"dev": true,
"license": "MIT"
},
- "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.truncate": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
@@ -10163,187 +9181,6 @@
"dev": true,
"license": "MIT"
},
- "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/log-symbols/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/log-symbols/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/log-symbols/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/log-symbols/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/log-update/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/log-update/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "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/loupe": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
@@ -10554,16 +9391,6 @@
"node": ">= 0.6"
}
},
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/mimic-function": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
@@ -10997,19 +9824,6 @@
"which": "bin/which"
}
},
- "node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
@@ -11183,22 +9997,6 @@
"wrappy": "1"
}
},
- "node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -11217,13 +10015,6 @@
"node": ">= 0.8.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-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -11256,22 +10047,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@@ -11434,20 +10209,6 @@
"node": ">= 14.16"
}
},
- "node_modules/pend": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
- "dev": true,
- "license": "MIT"
- },
- "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": "1.0.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
@@ -11517,6 +10278,53 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/playwright": {
+ "version": "1.46.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz",
+ "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.46.0"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.46.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz",
+ "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/possible-typed-array-names": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
@@ -11873,19 +10681,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/pretty-bytes": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
- "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/pretty-hrtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
@@ -11944,16 +10739,6 @@
"node": ">=4"
}
},
- "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",
@@ -12024,22 +10809,6 @@
"node": ">=6"
}
},
- "node_modules/qs": {
- "version": "6.10.4",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz",
- "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -12337,16 +11106,6 @@
"jsesc": "bin/jsesc"
}
},
- "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",
@@ -12402,20 +11161,6 @@
"node": ">=4"
}
},
- "node_modules/restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
- "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ret": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz",
@@ -12554,16 +11299,6 @@
"queue-microtask": "^1.2.2"
}
},
- "node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/safe-array-concat": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
@@ -13129,57 +11864,6 @@
"node": ">=6"
}
},
- "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/slice-ansi/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/slice-ansi/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/slice-ansi/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/smob": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
@@ -13272,32 +11956,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
- "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/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -13496,16 +12154,6 @@
"node": ">=4"
}
},
- "node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -14218,23 +12866,6 @@
"dev": true,
"license": "Apache-2.0"
},
- "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",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/time-zone": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/time-zone/-/time-zone-2.0.0.tgz",
@@ -14295,16 +12926,6 @@
"node": ">=14.0.0"
}
},
- "node_modules/tmp": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
- "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.14"
- }
- },
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -14446,13 +13067,6 @@
"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-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -14476,19 +13090,6 @@
"node": ">=4"
}
},
- "node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -14862,8 +13463,7 @@
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==",
"dev": true,
- "license": "MIT",
- "optional": true
+ "license": "MIT"
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
@@ -14942,16 +13542,6 @@
"node": ">= 0.8"
}
},
- "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.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
@@ -15021,16 +13611,6 @@
"node": ">= 0.4.0"
}
},
- "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/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -15052,28 +13632,6 @@
"node": ">= 0.8"
}
},
- "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/vite": {
"version": "5.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz",
@@ -15763,17 +14321,6 @@
"node": ">=12"
}
},
- "node_modules/yauzl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-crc32": "~0.2.3",
- "fd-slicer": "~1.1.0"
- }
- },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 38d277bf..82a4e6ef 100644
--- a/package.json
+++ b/package.json
@@ -30,17 +30,16 @@
"start": "run-p js:watch css:watch",
"build": "run-p js:build css:build",
"lint": "run-p lint:js lint:scss",
- "lint:js": "eslint src/scripts test/scripts",
+ "lint:js": "eslint src/scripts test/scripts e2e",
"lint:scss": "stylelint src/**/*.scss",
"bundlesize": "bundlesize",
- "cypress:run": "cypress run --config-file cypress/cypress.config.ts --browser chromium",
- "cypress:open": "cypress open --config-file cypress/cypress.config.ts ",
- "cypress:ci": "cypress run --config-file cypress/cypress.config.ts --browser chromium --record --group $GITHUB_REF --ci-build-id $GITHUB_SHA",
+ "playwright:cli": "playwright test",
+ "playwright:gui": "playwright test --ui",
"test": "run-s test:unit test:e2e",
"test:unit": "vitest --config test/vitest.config.ts run",
"test:unit:watch": "npm run test:unit -- --watch --inspect=5556",
"test:unit:coverage": "vitest --config test/vitest.config.ts run --coverage",
- "test:e2e": "run-p --race start cypress:run",
+ "test:e2e": "run-s playwright:cli",
"js:watch": "rollup -w --bundleConfigAsCjs -c scripts/rollup.config.mjs --environment TARGET:. --environment OUTPUT_TYPES:umd --environment WATCH_HOST:localhost",
"js:build": "rollup --bundleConfigAsCjs -c scripts/rollup.config.mjs --environment WITH_D_TS_FILES:1 && mv public/assets/scripts/src public/types/",
"js:build-dev": "rollup --bundleConfigAsCjs -c scripts/rollup.config.mjs --environment TARGET:. --environment OUTPUT_TYPES:umd",
@@ -83,6 +82,7 @@
"@babel/plugin-transform-object-rest-spread": "^7.24.7",
"@babel/preset-env": "^7.25.3",
"@babel/preset-typescript": "^7.24.7",
+ "@playwright/test": "^1.46.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-eslint": "^9.0.5",
"@rollup/plugin-node-resolve": "^15.2.3",
@@ -90,6 +90,7 @@
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/chai": "^4.3.17",
+ "@types/node": "^22.2.0",
"@types/sinon": "^17.0.3",
"@types/sinon-chai": "^3.2.12",
"@vitest/coverage-v8": "^2.0.5",
@@ -97,13 +98,11 @@
"bundlesize": "^0.18.2",
"chai": "^5.1.1",
"csso-cli": "^4.0.2",
- "cypress": "^13.13.2",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-compat": "6.0.0",
- "eslint-plugin-cypress": "^3.4.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-sort-class-members": "^1.20.0",
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 00000000..9872068b
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,82 @@
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './e2e',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: process.env.CI ? 'dot' : 'list',
+ timeout: 1000,
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://127.0.0.1:3001/',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ testIdAttribute: 'data-test-hook',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+/*
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+*/
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ //webServer: {
+ // command: 'npm run start',
+ // url: 'http://127.0.0.1:3001',
+ // reuseExistingServer: !process.env.CI,
+ //},
+});
diff --git a/public/index.html b/public/index.html
index ba032bb2..ec303523 100644
--- a/public/index.html
+++ b/public/index.html
@@ -942,7 +942,6 @@
-