Playwright for e2e tests

This commit is contained in:
Xon 2024-08-13 20:22:02 +08:00
commit d1de64e8a0
28 changed files with 279 additions and 4473 deletions

View file

@ -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": {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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 }}

View file

@ -23,7 +23,6 @@ jobs:
- name: Install dependencies
run: npm ci
env:
CYPRESS_INSTALL_BINARY: 0
HUSKY_SKIP_INSTALL: true
- name: run eslint

59
.github/workflows/playwright.yml vendored Normal file
View file

@ -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

View file

@ -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

6
.gitignore vendored
View file

@ -11,5 +11,7 @@ tests/reports
tests/results
.nyc_output
coverage
cypress/videos
cypress/screenshots
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

30
.vscode/launch.json vendored
View file

@ -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:*"
}
}
]
}

View file

@ -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"],

5
.vscode/tasks.json vendored
View file

@ -78,10 +78,5 @@
"script": "test:unit",
"group": "test"
},
{
"type": "npm",
"script": "cypress:open",
"isBackground": true
}
]
}

View file

@ -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

View file

@ -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 |

View file

@ -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}',
},
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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('<b>Mason Rogers</b>');
});
});
});
});
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);
});
});
});
});
});
});
});

View file

@ -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"
}

View file

@ -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) => { ... })

View file

@ -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')

View file

@ -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": ["."]
}
"include": [".", "../src"],
"exclude": ["**/node_modules", "**/public"]
}

View file

@ -3,7 +3,7 @@
"checkJs": true,
"target": "es2020",
"lib": ["esnext", "dom"],
"types": ["cypress"],
"types": [],
"strict": true,
"moduleResolution": "node",
/* Additional Checks */

1595
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -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",

82
playwright.config.ts Normal file
View file

@ -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,
//},
});

View file

@ -942,7 +942,6 @@
</script>
<!-- Google Analytics - Ignore me -->
<!-- google analytics is currently breaking puppeteer tests
<script>
try {
window.ga =
@ -958,7 +957,6 @@
}
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
-->
<!-- End Google Analytics -->
</body>
</html>