diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6744d4dc..9893a7e9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -100,12 +100,12 @@ jobs: run: npx playwright install --with-deps webkit - name: Run browser tests - run: npm run test-browser -- --static-logging + run: npm run test-browser:ci -- --static-logging - name: Run browser tests (lightweight) # overwrite test/lib run: | npm run build-test --lightweight - npm run test-browser -- --static-logging + npm run test-browser:ci -- --static-logging test-browsers-compatibility: name: Browsers (older, on Browserstack) @@ -119,6 +119,15 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 + - name: Generate self-signed HTTPS certificates for web-test-runner server + uses: kofemann/action-create-certificate@v0.0.4 + with: + hostcert: '127.0.0.1.pem' + hostkey: '127.0.0.1-key.pem' + cachain: 'ca-chain.pem' + - name: Adjust HTTPS certificates permissions + run: sudo chown runner:docker *.pem + - name: Install dependencies run: npm ci --ignore-scripts diff --git a/README.md b/README.md index 2c60f3d2..68bcde05 100644 --- a/README.md +++ b/README.md @@ -667,7 +667,7 @@ To create your own build of the library, just run the following command after cl npm install && npm test -For debugging browser errors, you can run `npm start` and open [`http://localhost:8080/test/unittests.html`](http://localhost:8080/test/unittests.html) in a browser, or run the following command: +For debugging browser errors, run the following command: npm run browsertest diff --git a/package-lock.json b/package-lock.json index 74383bd7..411eef7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2543,17 +2543,36 @@ "node": ">=18.0.0" } }, - "node_modules/@web/dev-server-core": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@web/dev-server-core/-/dev-server-core-0.7.2.tgz", - "integrity": "sha512-Q/0jpF13Ipk+qGGQ+Yx/FW1TQBYazpkfgYHHo96HBE7qv4V4KKHqHglZcSUxti/zd4bToxX1cFTz8dmbTlb8JA==", + "node_modules/@web/dev-server-rollup": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@web/dev-server-rollup/-/dev-server-rollup-0.6.4.tgz", + "integrity": "sha512-sJZfTGCCrdku5xYnQQG51odGI092hKY9YFM0X3Z0tRY3iXKXcYRaLZrErw5KfCxr6g0JRuhe4BBhqXTA5Q2I3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-node-resolve": "^15.0.1", + "@web/dev-server-core": "^0.7.2", + "nanocolors": "^0.2.1", + "parse5": "^6.0.1", + "rollup": "^4.4.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@web/dev-server-rollup/node_modules/@web/dev-server-core": { + "name": "@openpgp/wtr-dev-server-core", + "version": "0.7.3-patch.0", + "resolved": "https://registry.npmjs.org/@openpgp/wtr-dev-server-core/-/wtr-dev-server-core-0.7.3-patch.0.tgz", + "integrity": "sha512-f6Vl/ZwvvExZJ9JB5g2nrGbm/H8Uy22zm3nojC/wokuYrPAhW65YMUn4AL5FbmI8Cx+4X1JeEBOfzvTrdeSgWQ==", "dev": true, "license": "MIT", "dependencies": { "@types/koa": "^2.11.6", "@types/ws": "^7.4.0", "@web/parse5-utils": "^2.1.0", - "chokidar": "^3.4.3", + "chokidar": "^4.0.1", "clone": "^2.1.2", "es-module-lexer": "^1.0.0", "get-stream": "^6.0.0", @@ -2567,26 +2586,43 @@ "mime-types": "^2.1.27", "parse5": "^6.0.1", "picomatch": "^2.2.2", - "ws": "^7.4.2" + "ws": "^7.5.10" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@web/dev-server-core/node_modules/isbinaryfile": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", - "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", + "node_modules/@web/dev-server-rollup/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web/dev-server-rollup/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 18.0.0" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/gjtorikian/" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@web/dev-server-core/node_modules/ws": { + "node_modules/@web/dev-server-rollup/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", @@ -2608,24 +2644,89 @@ } } }, - "node_modules/@web/dev-server-rollup": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@web/dev-server-rollup/-/dev-server-rollup-0.6.4.tgz", - "integrity": "sha512-sJZfTGCCrdku5xYnQQG51odGI092hKY9YFM0X3Z0tRY3iXKXcYRaLZrErw5KfCxr6g0JRuhe4BBhqXTA5Q2I3Q==", + "node_modules/@web/dev-server/node_modules/@web/dev-server-core": { + "name": "@openpgp/wtr-dev-server-core", + "version": "0.7.3-patch.0", + "resolved": "https://registry.npmjs.org/@openpgp/wtr-dev-server-core/-/wtr-dev-server-core-0.7.3-patch.0.tgz", + "integrity": "sha512-f6Vl/ZwvvExZJ9JB5g2nrGbm/H8Uy22zm3nojC/wokuYrPAhW65YMUn4AL5FbmI8Cx+4X1JeEBOfzvTrdeSgWQ==", "dev": true, "license": "MIT", "dependencies": { - "@rollup/plugin-node-resolve": "^15.0.1", - "@web/dev-server-core": "^0.7.2", - "nanocolors": "^0.2.1", + "@types/koa": "^2.11.6", + "@types/ws": "^7.4.0", + "@web/parse5-utils": "^2.1.0", + "chokidar": "^4.0.1", + "clone": "^2.1.2", + "es-module-lexer": "^1.0.0", + "get-stream": "^6.0.0", + "is-stream": "^2.0.0", + "isbinaryfile": "^5.0.0", + "koa": "^2.13.0", + "koa-etag": "^4.0.0", + "koa-send": "^5.0.1", + "koa-static": "^5.0.0", + "lru-cache": "^8.0.4", + "mime-types": "^2.1.27", "parse5": "^6.0.1", - "rollup": "^4.4.0", - "whatwg-url": "^14.0.0" + "picomatch": "^2.2.2", + "ws": "^7.5.10" }, "engines": { "node": ">=18.0.0" } }, + "node_modules/@web/dev-server/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web/dev-server/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web/dev-server/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@web/parse5-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@web/parse5-utils/-/parse5-utils-2.1.0.tgz", @@ -2757,6 +2858,67 @@ "node": ">=18.0.0" } }, + "node_modules/@web/test-runner-core/node_modules/@web/dev-server-core": { + "name": "@openpgp/wtr-dev-server-core", + "version": "0.7.3-patch.0", + "resolved": "https://registry.npmjs.org/@openpgp/wtr-dev-server-core/-/wtr-dev-server-core-0.7.3-patch.0.tgz", + "integrity": "sha512-f6Vl/ZwvvExZJ9JB5g2nrGbm/H8Uy22zm3nojC/wokuYrPAhW65YMUn4AL5FbmI8Cx+4X1JeEBOfzvTrdeSgWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/koa": "^2.11.6", + "@types/ws": "^7.4.0", + "@web/parse5-utils": "^2.1.0", + "chokidar": "^4.0.1", + "clone": "^2.1.2", + "es-module-lexer": "^1.0.0", + "get-stream": "^6.0.0", + "is-stream": "^2.0.0", + "isbinaryfile": "^5.0.0", + "koa": "^2.13.0", + "koa-etag": "^4.0.0", + "koa-send": "^5.0.1", + "koa-static": "^5.0.0", + "lru-cache": "^8.0.4", + "mime-types": "^2.1.27", + "parse5": "^6.0.1", + "picomatch": "^2.2.2", + "ws": "^7.5.10" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@web/test-runner-core/node_modules/@web/dev-server-core/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@web/test-runner-core/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@web/test-runner-core/node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -2767,6 +2929,28 @@ "node": ">= 8" } }, + "node_modules/@web/test-runner-core/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@web/test-runner-coverage-v8": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.8.0.tgz", @@ -7601,6 +7785,19 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, + "node_modules/isbinaryfile": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", + "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", diff --git a/package.json b/package.json index 4883e418..71397ab0 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "prebrowsertest": "npm run build-test", "browsertest": "web-test-runner --config test/web-test-runner.config.js --group local --manual --open", "test-browser": "web-test-runner --config test/web-test-runner.config.js --group local --playwright --browsers chromium firefox webkit", - "test-browserstack": "web-test-runner --config test/web-test-runner.config.js --group browserstack", + "test-browser:ci": "web-test-runner --config test/web-test-runner.config.js --group headless:ci", + "test-browserstack": "web-test-runner --config test/web-test-runner.browserstack.config.js", "coverage": "c8 npm test", "lint": "eslint .", "docs": "jsdoc --configure .jsdocrc.cjs --destination docs --recurse README.md src && printf '%s' 'docs.openpgpjs.org' > docs/CNAME", @@ -108,6 +109,9 @@ "typescript": "^5.5.4", "web-streams-polyfill": "^4.0.0" }, + "overrides": { + "@web/dev-server-core": "npm:@openpgp/wtr-dev-server-core@0.7.3-patch.0" + }, "repository": { "type": "git", "url": "https://github.com/openpgpjs/openpgpjs" diff --git a/test/web-test-runner.browserstack.config.js b/test/web-test-runner.browserstack.config.js new file mode 100644 index 00000000..1f02314f --- /dev/null +++ b/test/web-test-runner.browserstack.config.js @@ -0,0 +1,49 @@ +import { browserstackLauncher } from '@web/test-runner-browserstack'; +import wtrConfig from './web-test-runner.config.js'; + +const sharedBrowserstackCapabilities = { + 'browserstack.user': process.env.BROWSERSTACK_USERNAME, + 'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY, + + project: `openpgpjs/${process.env.GITHUB_EVENT_NAME || 'push'}${process.env.LIGHTWEIGHT ? '/lightweight' : ''}`, + name: process.env.GITHUB_WORKFLOW || 'local', + build: process.env.GITHUB_SHA || 'local', + 'browserstack.acceptInsecureCerts': true +}; + +export default { + ...wtrConfig, + protocol: 'https:', + http2: true, + sslKey: './127.0.0.1-key.pem', + sslCert: './127.0.0.1.pem', + testsStartTimeout: 45000, + browserStartTimeout: 120000, + testsFinishTimeout: 450000, + concurrentBrowsers: 3, + concurrency: 1, // see https://github.com/modernweb-dev/web/issues/2706 + coverage: false, + groups: [], // overwrite the field coming from `wrtConfig` + browsers: [ + browserstackLauncher({ + capabilities: { + ...sharedBrowserstackCapabilities, + browserName: 'Safari iOS 14', + device: 'iPhone 12', + real_mobile: true, + os: 'ios', + os_version: '14' // min supported version (iOS/Safari < 14 does not support native BigInts) + } + }), + browserstackLauncher({ + capabilities: { + ...sharedBrowserstackCapabilities, + browserName: 'Safari iOS latest', + device: 'iPhone 16', + real_mobile: true, + os: 'ios', + os_version: 'latest' + } + }) + ] +}; diff --git a/test/web-test-runner.config.js b/test/web-test-runner.config.js index 8604a04d..706a8a05 100644 --- a/test/web-test-runner.config.js +++ b/test/web-test-runner.config.js @@ -1,50 +1,33 @@ -import { browserstackLauncher } from '@web/test-runner-browserstack'; +import { playwrightLauncher } from '@web/test-runner-playwright'; -const sharedBrowserstackCapabilities = { - 'browserstack.user': process.env.BROWSERSTACK_USERNAME, - 'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY, - - project: `openpgpjs/${process.env.GITHUB_EVENT_NAME || 'push'}${process.env.LIGHTWEIGHT ? '/lightweight' : ''}`, - name: process.env.GITHUB_WORKFLOW, - build: process.env.GITHUB_SHA, - timeout: 450 +const sharedPlaywrightCIOptions = { + // createBrowserContext: ({ browser }) => browser.newContext({ ignoreHTTPSErrors: true }), + headless: true }; export default { nodeResolve: true, // to resolve npm module imports in `unittests.html` files: './test/unittests.html', - + protocol: 'http:', + hostname: '127.0.0.1', + testsStartTimeout: 45000, + browserStartTimeout: 120000, + testsFinishTimeout: 450000, + concurrentBrowsers: 3, + concurrency: 1, // see https://github.com/modernweb-dev/web/issues/2706 + coverage: false, groups: [ { name: 'local' }, // group meant to be used with either --browser or --manual options via CLI { - name: 'browserstack', - browsers: process.env.BROWSERSTACK_USERNAME && [ - browserstackLauncher({ - capabilities: { - ...sharedBrowserstackCapabilities, - browserName: 'Safari', - browser_version: 'latest', // Webkit and Safari can differ in behavior - os: 'OS X', - os_version: 'Ventura' - } + name: 'headless:ci', + browsers: [ + playwrightLauncher({ + ...sharedPlaywrightCIOptions, + product: 'chromium' }), - browserstackLauncher({ - capabilities: { - ...sharedBrowserstackCapabilities, - browserName: 'Safari', - browser_version: '14', // min supported version - os: 'OS X', - os_version: 'Big Sur' - } - }), - browserstackLauncher({ - capabilities: { - ...sharedBrowserstackCapabilities, - device: 'iPhone 12', - real_mobile: true, - os: 'ios', - os_version: '14' - } + playwrightLauncher({ + ...sharedPlaywrightCIOptions, + product: 'firefox' }) ] }