Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6aa50b0c7 | ||
|
|
54c157dec5 | ||
|
|
2d437e86e2 | ||
|
|
7637399834 | ||
|
|
9e091e74bd |
|
|
@ -1,6 +1,6 @@
|
||||||
# 🎭 Playwright
|
# 🎭 Playwright
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop -->
|
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop -->
|
||||||
|
|
||||||
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
|
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
|
||||||
|
|
||||||
| | Linux | macOS | Windows |
|
| | Linux | macOS | Windows |
|
||||||
| :--- | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: |
|
||||||
| Chromium <!-- GEN:chromium-version -->125.0.6422.14<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Chromium <!-- GEN:chromium-version -->125.0.6422.26<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| Firefox <!-- GEN:firefox-version -->125.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Firefox <!-- GEN:firefox-version -->125.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ Blob report supports following configuration options and environment variables:
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `PLAYWRIGHT_BLOB_OUTPUT_DIR` | `outputDir` | Directory to save the output. Existing content is deleted before writing the new report. | `blob-report`
|
| `PLAYWRIGHT_BLOB_OUTPUT_DIR` | `outputDir` | Directory to save the output. Existing content is deleted before writing the new report. | `blob-report`
|
||||||
| `PLAYWRIGHT_BLOB_OUTPUT_NAME` | `fileName` | Report file name. | `report-<project>-<hash>-<shard_number>.zip`
|
| `PLAYWRIGHT_BLOB_OUTPUT_NAME` | `fileName` | Report file name. | `report-<project>-<hash>-<shard_number>.zip`
|
||||||
| `PLAYWRIGHT_BLOB_OUTPUT_FILE` | `outputFile` | Full path for the output. If defined, `outputDir` and `fileName` will be ignored. | `undefined`
|
| `PLAYWRIGHT_BLOB_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `outputDir` and `fileName` will be ignored. | `undefined`
|
||||||
|
|
||||||
### JSON reporter
|
### JSON reporter
|
||||||
|
|
||||||
|
|
@ -267,7 +267,9 @@ JSON report supports following configuration options and environment variables:
|
||||||
|
|
||||||
| Environment Variable Name | Reporter Config Option| Description | Default
|
| Environment Variable Name | Reporter Config Option| Description | Default
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `PLAYWRIGHT_JUNIT_OUTPUT_NAME` | `outputFile` | Report file path. | JSON report is printed to stdout.
|
| `PLAYWRIGHT_JSON_OUTPUT_DIR` | | Directory to save the output file. Ignored if output file is specified. | `cwd` or config directory.
|
||||||
|
| `PLAYWRIGHT_JSON_OUTPUT_NAME` | `outputFile` | Base file name for the output, relative to the output dir. | JSON report is printed to the stdout.
|
||||||
|
| `PLAYWRIGHT_JSON_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `PLAYWRIGHT_JSON_OUTPUT_DIR` and `PLAYWRIGHT_JSON_OUTPUT_NAME` will be ignored. | JSON report is printed to the stdout.
|
||||||
|
|
||||||
### JUnit reporter
|
### JUnit reporter
|
||||||
|
|
||||||
|
|
@ -303,7 +305,9 @@ JUnit report supports following configuration options and environment variables:
|
||||||
|
|
||||||
| Environment Variable Name | Reporter Config Option| Description | Default
|
| Environment Variable Name | Reporter Config Option| Description | Default
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `PLAYWRIGHT_JUNIT_OUTPUT_NAME` | `outputFile` | Report file path. | JUnit report is printed to stdout.
|
| `PLAYWRIGHT_JUNIT_OUTPUT_DIR` | | Directory to save the output file. Ignored if output file is not specified. | `cwd` or config directory.
|
||||||
|
| `PLAYWRIGHT_JUNIT_OUTPUT_NAME` | `outputFile` | Base file name for the output, relative to the output dir. | JUnit report is printed to the stdout.
|
||||||
|
| `PLAYWRIGHT_JUNIT_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `PLAYWRIGHT_JUNIT_OUTPUT_DIR` and `PLAYWRIGHT_JUNIT_OUTPUT_NAME` will be ignored. | JUnit report is printed to the stdout.
|
||||||
| | `stripANSIControlSequences` | Whether to remove ANSI control sequences from the text before writing it in the report. | By default output text is added as is.
|
| | `stripANSIControlSequences` | Whether to remove ANSI control sequences from the text before writing it in the report. | By default output text is added as is.
|
||||||
| | `includeProjectInTestName` | Whether to include Playwright project name in every test case as a name prefix. | By default not included.
|
| | `includeProjectInTestName` | Whether to include Playwright project name in every test case as a name prefix. | By default not included.
|
||||||
| `PLAYWRIGHT_JUNIT_SUITE_ID` | | Value of the `id` attribute on the root `<testsuites/>` report entry. | Empty string.
|
| `PLAYWRIGHT_JUNIT_SUITE_ID` | | Value of the `id` attribute on the root `<testsuites/>` report entry. | Empty string.
|
||||||
|
|
|
||||||
68
package-lock.json
generated
68
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
@ -8162,10 +8162,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright": {
|
"packages/playwright": {
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8179,11 +8179,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-chromium": {
|
"packages/playwright-browser-chromium": {
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8191,11 +8191,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-firefox": {
|
"packages/playwright-browser-firefox": {
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8203,22 +8203,22 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-webkit": {
|
"packages/playwright-browser-webkit": {
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-chromium": {
|
"packages/playwright-chromium": {
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8228,7 +8228,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-core": {
|
"packages/playwright-core": {
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
|
|
@ -8239,11 +8239,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-core": {
|
"packages/playwright-ct-core": {
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.44.0-next",
|
"playwright": "1.44.0",
|
||||||
"playwright-core": "1.44.0-next",
|
"playwright-core": "1.44.0",
|
||||||
"vite": "^5.2.8"
|
"vite": "^5.2.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -8252,10 +8252,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react": {
|
"packages/playwright-ct-react": {
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8267,10 +8267,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react17": {
|
"packages/playwright-ct-react17": {
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8282,10 +8282,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-solid": {
|
"packages/playwright-ct-solid": {
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8300,10 +8300,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-svelte": {
|
"packages/playwright-ct-svelte": {
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8318,10 +8318,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue": {
|
"packages/playwright-ct-vue": {
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8333,10 +8333,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue2": {
|
"packages/playwright-ct-vue2": {
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8385,11 +8385,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-firefox": {
|
"packages/playwright-firefox": {
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8400,10 +8400,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-test": {
|
"packages/playwright-test": {
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.44.0-next"
|
"playwright": "1.44.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8413,11 +8413,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-webkit": {
|
"packages/playwright-webkit": {
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright package that automatically installs Chromium",
|
"description": "Playwright package that automatically installs Chromium",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright package that automatically installs Firefox",
|
"description": "Playwright package that automatically installs Firefox",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright package that automatically installs WebKit",
|
"description": "Playwright package that automatically installs WebKit",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-chromium",
|
"name": "playwright-chromium",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate Chromium",
|
"description": "A high-level API to automate Chromium",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
"browsers": [
|
"browsers": [
|
||||||
{
|
{
|
||||||
"name": "chromium",
|
"name": "chromium",
|
||||||
"revision": "1116",
|
"revision": "1117",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "125.0.6422.14"
|
"browserVersion": "125.0.6422.26"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chromium-tip-of-tree",
|
"name": "chromium-tip-of-tree",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-core",
|
"name": "playwright-core",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Galaxy S5": {
|
"Galaxy S5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -121,7 +121,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S5 landscape": {
|
"Galaxy S5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S8": {
|
"Galaxy S8": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 740
|
"height": 740
|
||||||
|
|
@ -143,7 +143,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S8 landscape": {
|
"Galaxy S8 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 740,
|
"width": 740,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -154,7 +154,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S9+": {
|
"Galaxy S9+": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 320,
|
"width": 320,
|
||||||
"height": 658
|
"height": 658
|
||||||
|
|
@ -165,7 +165,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S9+ landscape": {
|
"Galaxy S9+ landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 658,
|
"width": 658,
|
||||||
"height": 320
|
"height": 320
|
||||||
|
|
@ -176,7 +176,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy Tab S4": {
|
"Galaxy Tab S4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 712,
|
"width": 712,
|
||||||
"height": 1138
|
"height": 1138
|
||||||
|
|
@ -187,7 +187,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy Tab S4 landscape": {
|
"Galaxy Tab S4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 1138,
|
"width": 1138,
|
||||||
"height": 712
|
"height": 712
|
||||||
|
|
@ -978,7 +978,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"LG Optimus L70": {
|
"LG Optimus L70": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 384,
|
"width": 384,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -989,7 +989,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"LG Optimus L70 landscape": {
|
"LG Optimus L70 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 384
|
"height": 384
|
||||||
|
|
@ -1000,7 +1000,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 550": {
|
"Microsoft Lumia 550": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1011,7 +1011,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 550 landscape": {
|
"Microsoft Lumia 550 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1022,7 +1022,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 950": {
|
"Microsoft Lumia 950": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1033,7 +1033,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 950 landscape": {
|
"Microsoft Lumia 950 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1044,7 +1044,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 10": {
|
"Nexus 10": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 800,
|
"width": 800,
|
||||||
"height": 1280
|
"height": 1280
|
||||||
|
|
@ -1055,7 +1055,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 10 landscape": {
|
"Nexus 10 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 1280,
|
"width": 1280,
|
||||||
"height": 800
|
"height": 800
|
||||||
|
|
@ -1066,7 +1066,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 4": {
|
"Nexus 4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 384,
|
"width": 384,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1077,7 +1077,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 4 landscape": {
|
"Nexus 4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 384
|
"height": 384
|
||||||
|
|
@ -1088,7 +1088,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5": {
|
"Nexus 5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1099,7 +1099,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5 landscape": {
|
"Nexus 5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1110,7 +1110,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5X": {
|
"Nexus 5X": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1121,7 +1121,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5X landscape": {
|
"Nexus 5X landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1132,7 +1132,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6": {
|
"Nexus 6": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1143,7 +1143,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6 landscape": {
|
"Nexus 6 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1154,7 +1154,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6P": {
|
"Nexus 6P": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1165,7 +1165,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6P landscape": {
|
"Nexus 6P landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1176,7 +1176,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 7": {
|
"Nexus 7": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 600,
|
"width": 600,
|
||||||
"height": 960
|
"height": 960
|
||||||
|
|
@ -1187,7 +1187,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 7 landscape": {
|
"Nexus 7 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 960,
|
"width": 960,
|
||||||
"height": 600
|
"height": 600
|
||||||
|
|
@ -1242,7 +1242,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Pixel 2": {
|
"Pixel 2": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 411,
|
"width": 411,
|
||||||
"height": 731
|
"height": 731
|
||||||
|
|
@ -1253,7 +1253,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 landscape": {
|
"Pixel 2 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 731,
|
"width": 731,
|
||||||
"height": 411
|
"height": 411
|
||||||
|
|
@ -1264,7 +1264,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 XL": {
|
"Pixel 2 XL": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 411,
|
"width": 411,
|
||||||
"height": 823
|
"height": 823
|
||||||
|
|
@ -1275,7 +1275,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 XL landscape": {
|
"Pixel 2 XL landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 823,
|
"width": 823,
|
||||||
"height": 411
|
"height": 411
|
||||||
|
|
@ -1286,7 +1286,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 3": {
|
"Pixel 3": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 393,
|
"width": 393,
|
||||||
"height": 786
|
"height": 786
|
||||||
|
|
@ -1297,7 +1297,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 3 landscape": {
|
"Pixel 3 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 786,
|
"width": 786,
|
||||||
"height": 393
|
"height": 393
|
||||||
|
|
@ -1308,7 +1308,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4": {
|
"Pixel 4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 353,
|
"width": 353,
|
||||||
"height": 745
|
"height": 745
|
||||||
|
|
@ -1319,7 +1319,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4 landscape": {
|
"Pixel 4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 745,
|
"width": 745,
|
||||||
"height": 353
|
"height": 353
|
||||||
|
|
@ -1330,7 +1330,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4a (5G)": {
|
"Pixel 4a (5G)": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 892
|
"height": 892
|
||||||
|
|
@ -1345,7 +1345,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4a (5G) landscape": {
|
"Pixel 4a (5G) landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"height": 892,
|
"height": 892,
|
||||||
"width": 412
|
"width": 412
|
||||||
|
|
@ -1360,7 +1360,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 5": {
|
"Pixel 5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 393,
|
"width": 393,
|
||||||
"height": 851
|
"height": 851
|
||||||
|
|
@ -1375,7 +1375,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 5 landscape": {
|
"Pixel 5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 851,
|
"width": 851,
|
||||||
"height": 393
|
"height": 393
|
||||||
|
|
@ -1390,7 +1390,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 7": {
|
"Pixel 7": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 915
|
"height": 915
|
||||||
|
|
@ -1405,7 +1405,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 7 landscape": {
|
"Pixel 7 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 915,
|
"width": 915,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1420,7 +1420,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Moto G4": {
|
"Moto G4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1431,7 +1431,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Moto G4 landscape": {
|
"Moto G4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1442,7 +1442,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Chrome HiDPI": {
|
"Desktop Chrome HiDPI": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1792,
|
"width": 1792,
|
||||||
"height": 1120
|
"height": 1120
|
||||||
|
|
@ -1457,7 +1457,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Edge HiDPI": {
|
"Desktop Edge HiDPI": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36 Edg/125.0.6422.14",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36 Edg/125.0.6422.26",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1792,
|
"width": 1792,
|
||||||
"height": 1120
|
"height": 1120
|
||||||
|
|
@ -1502,7 +1502,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Desktop Chrome": {
|
"Desktop Chrome": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1920,
|
"width": 1920,
|
||||||
"height": 1080
|
"height": 1080
|
||||||
|
|
@ -1517,7 +1517,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Edge": {
|
"Desktop Edge": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.14 Safari/537.36 Edg/125.0.6422.14",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36 Edg/125.0.6422.26",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1920,
|
"width": 1920,
|
||||||
"height": 1080
|
"height": 1080
|
||||||
|
|
|
||||||
|
|
@ -125,3 +125,12 @@ export function isVisibleTextNode(node: Text) {
|
||||||
const rect = range.getBoundingClientRect();
|
const rect = range.getBoundingClientRect();
|
||||||
return rect.width > 0 && rect.height > 0;
|
return rect.width > 0 && rect.height > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function elementSafeTagName(element: Element) {
|
||||||
|
// Named inputs, e.g. <input name=tagName>, will be exposed as fields on the parent <form>
|
||||||
|
// and override its properties.
|
||||||
|
if (element instanceof HTMLFormElement)
|
||||||
|
return 'FORM';
|
||||||
|
// Elements from the svg namespace do not have uppercase tagName right away.
|
||||||
|
return element.tagName.toUpperCase();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { closestCrossShadow, enclosingShadowRootOrDocument, getElementComputedStyle, isElementStyleVisibilityVisible, isVisibleTextNode, parentElementOrShadowHost } from './domUtils';
|
import { closestCrossShadow, elementSafeTagName, enclosingShadowRootOrDocument, getElementComputedStyle, isElementStyleVisibilityVisible, isVisibleTextNode, parentElementOrShadowHost } from './domUtils';
|
||||||
|
|
||||||
function hasExplicitAccessibleName(e: Element) {
|
function hasExplicitAccessibleName(e: Element) {
|
||||||
return e.hasAttribute('aria-label') || e.hasAttribute('aria-labelledby');
|
return e.hasAttribute('aria-label') || e.hasAttribute('aria-labelledby');
|
||||||
|
|
@ -70,7 +70,7 @@ function isFocusable(element: Element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNativelyFocusable(element: Element) {
|
function isNativelyFocusable(element: Element) {
|
||||||
const tagName = element.tagName.toUpperCase();
|
const tagName = elementSafeTagName(element);
|
||||||
if (['BUTTON', 'DETAILS', 'SELECT', 'TEXTAREA'].includes(tagName))
|
if (['BUTTON', 'DETAILS', 'SELECT', 'TEXTAREA'].includes(tagName))
|
||||||
return true;
|
return true;
|
||||||
if (tagName === 'A' || tagName === 'AREA')
|
if (tagName === 'A' || tagName === 'AREA')
|
||||||
|
|
@ -124,7 +124,7 @@ const kImplicitRoleByTagName: { [tagName: string]: (e: Element) => string | null
|
||||||
if (['email', 'tel', 'text', 'url', ''].includes(type)) {
|
if (['email', 'tel', 'text', 'url', ''].includes(type)) {
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#concept-input-list
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-list
|
||||||
const list = getIdRefs(e, e.getAttribute('list'))[0];
|
const list = getIdRefs(e, e.getAttribute('list'))[0];
|
||||||
return (list && list.tagName === 'DATALIST') ? 'combobox' : 'textbox';
|
return (list && elementSafeTagName(list) === 'DATALIST') ? 'combobox' : 'textbox';
|
||||||
}
|
}
|
||||||
if (type === 'hidden')
|
if (type === 'hidden')
|
||||||
return '';
|
return '';
|
||||||
|
|
@ -201,8 +201,7 @@ const kPresentationInheritanceParents: { [tagName: string]: string[] } = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getImplicitAriaRole(element: Element): string | null {
|
function getImplicitAriaRole(element: Element): string | null {
|
||||||
// Elements from the svg namespace do not have uppercase tagName.
|
const implicitRole = kImplicitRoleByTagName[elementSafeTagName(element)]?.(element) || '';
|
||||||
const implicitRole = kImplicitRoleByTagName[element.tagName.toUpperCase()]?.(element) || '';
|
|
||||||
if (!implicitRole)
|
if (!implicitRole)
|
||||||
return null;
|
return null;
|
||||||
// Inherit presentation role when required.
|
// Inherit presentation role when required.
|
||||||
|
|
@ -210,8 +209,8 @@ function getImplicitAriaRole(element: Element): string | null {
|
||||||
let ancestor: Element | null = element;
|
let ancestor: Element | null = element;
|
||||||
while (ancestor) {
|
while (ancestor) {
|
||||||
const parent = parentElementOrShadowHost(ancestor);
|
const parent = parentElementOrShadowHost(ancestor);
|
||||||
const parents = kPresentationInheritanceParents[ancestor.tagName];
|
const parents = kPresentationInheritanceParents[elementSafeTagName(ancestor)];
|
||||||
if (!parents || !parent || !parents.includes(parent.tagName))
|
if (!parents || !parent || !parents.includes(elementSafeTagName(parent)))
|
||||||
break;
|
break;
|
||||||
const parentExplicitRole = getExplicitAriaRole(parent);
|
const parentExplicitRole = getExplicitAriaRole(parent);
|
||||||
if ((parentExplicitRole === 'none' || parentExplicitRole === 'presentation') && !hasPresentationConflictResolution(parent, parentExplicitRole))
|
if ((parentExplicitRole === 'none' || parentExplicitRole === 'presentation') && !hasPresentationConflictResolution(parent, parentExplicitRole))
|
||||||
|
|
@ -267,7 +266,7 @@ function getAriaBoolean(attr: string | null) {
|
||||||
// `Any descendants of elements that have the characteristic "Children Presentational: True"`
|
// `Any descendants of elements that have the characteristic "Children Presentational: True"`
|
||||||
// https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
|
// https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
|
||||||
export function isElementHiddenForAria(element: Element): boolean {
|
export function isElementHiddenForAria(element: Element): boolean {
|
||||||
if (['STYLE', 'SCRIPT', 'NOSCRIPT', 'TEMPLATE'].includes(element.tagName))
|
if (['STYLE', 'SCRIPT', 'NOSCRIPT', 'TEMPLATE'].includes(elementSafeTagName(element)))
|
||||||
return true;
|
return true;
|
||||||
const style = getElementComputedStyle(element);
|
const style = getElementComputedStyle(element);
|
||||||
const isSlot = element.nodeName === 'SLOT';
|
const isSlot = element.nodeName === 'SLOT';
|
||||||
|
|
@ -527,6 +526,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = getAriaRole(element) || '';
|
const role = getAriaRole(element) || '';
|
||||||
|
const tagName = elementSafeTagName(element);
|
||||||
|
|
||||||
// step 2c:
|
// step 2c:
|
||||||
// if the current node is a control embedded within the label (e.g. any element directly referenced by aria-labelledby) for another widget...
|
// if the current node is a control embedded within the label (e.g. any element directly referenced by aria-labelledby) for another widget...
|
||||||
|
|
@ -542,14 +542,14 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
if (!isOwnLabel && !isOwnLabelledBy) {
|
if (!isOwnLabel && !isOwnLabelledBy) {
|
||||||
if (role === 'textbox') {
|
if (role === 'textbox') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA')
|
if (tagName === 'INPUT' || tagName === 'TEXTAREA')
|
||||||
return (element as HTMLInputElement | HTMLTextAreaElement).value;
|
return (element as HTMLInputElement | HTMLTextAreaElement).value;
|
||||||
return element.textContent || '';
|
return element.textContent || '';
|
||||||
}
|
}
|
||||||
if (['combobox', 'listbox'].includes(role)) {
|
if (['combobox', 'listbox'].includes(role)) {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
let selectedOptions: Element[];
|
let selectedOptions: Element[];
|
||||||
if (element.tagName === 'SELECT') {
|
if (tagName === 'SELECT') {
|
||||||
selectedOptions = [...(element as HTMLSelectElement).selectedOptions];
|
selectedOptions = [...(element as HTMLSelectElement).selectedOptions];
|
||||||
if (!selectedOptions.length && (element as HTMLSelectElement).options.length)
|
if (!selectedOptions.length && (element as HTMLSelectElement).options.length)
|
||||||
selectedOptions.push((element as HTMLSelectElement).options[0]);
|
selectedOptions.push((element as HTMLSelectElement).options[0]);
|
||||||
|
|
@ -557,7 +557,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
const listbox = role === 'combobox' ? queryInAriaOwned(element, '*').find(e => getAriaRole(e) === 'listbox') : element;
|
const listbox = role === 'combobox' ? queryInAriaOwned(element, '*').find(e => getAriaRole(e) === 'listbox') : element;
|
||||||
selectedOptions = listbox ? queryInAriaOwned(listbox, '[aria-selected="true"]').filter(e => getAriaRole(e) === 'option') : [];
|
selectedOptions = listbox ? queryInAriaOwned(listbox, '[aria-selected="true"]').filter(e => getAriaRole(e) === 'option') : [];
|
||||||
}
|
}
|
||||||
if (!selectedOptions.length && element.tagName === 'INPUT') {
|
if (!selectedOptions.length && tagName === 'INPUT') {
|
||||||
// SPEC DIFFERENCE:
|
// SPEC DIFFERENCE:
|
||||||
// This fallback is not explicitly mentioned in the spec, but all browsers and
|
// This fallback is not explicitly mentioned in the spec, but all browsers and
|
||||||
// wpt test name_heading-combobox-focusable-alternative-manual.html do this.
|
// wpt test name_heading-combobox-focusable-alternative-manual.html do this.
|
||||||
|
|
@ -596,7 +596,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
// Spec says to ignore this when aria-labelledby is defined.
|
// Spec says to ignore this when aria-labelledby is defined.
|
||||||
// WebKit follows the spec, while Chromium and Firefox do not.
|
// WebKit follows the spec, while Chromium and Firefox do not.
|
||||||
// We align with Chromium and Firefox here.
|
// We align with Chromium and Firefox here.
|
||||||
if (element.tagName === 'INPUT' && ['button', 'submit', 'reset'].includes((element as HTMLInputElement).type)) {
|
if (tagName === 'INPUT' && ['button', 'submit', 'reset'].includes((element as HTMLInputElement).type)) {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const value = (element as HTMLInputElement).value || '';
|
const value = (element as HTMLInputElement).value || '';
|
||||||
if (trimFlatString(value))
|
if (trimFlatString(value))
|
||||||
|
|
@ -613,7 +613,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
//
|
//
|
||||||
// SPEC DIFFERENCE.
|
// SPEC DIFFERENCE.
|
||||||
// Spec says to ignore this when aria-labelledby is defined, but all browsers take it into account.
|
// Spec says to ignore this when aria-labelledby is defined, but all browsers take it into account.
|
||||||
if (element.tagName === 'INPUT' && (element as HTMLInputElement).type === 'image') {
|
if (tagName === 'INPUT' && (element as HTMLInputElement).type === 'image') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const labels = (element as HTMLInputElement).labels || [];
|
const labels = (element as HTMLInputElement).labels || [];
|
||||||
if (labels.length && !options.embeddedInLabelledBy)
|
if (labels.length && !options.embeddedInLabelledBy)
|
||||||
|
|
@ -630,7 +630,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#button-element-accessible-name-computation
|
// https://w3c.github.io/html-aam/#button-element-accessible-name-computation
|
||||||
if (!labelledBy && element.tagName === 'BUTTON') {
|
if (!labelledBy && tagName === 'BUTTON') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const labels = (element as HTMLButtonElement).labels || [];
|
const labels = (element as HTMLButtonElement).labels || [];
|
||||||
if (labels.length)
|
if (labels.length)
|
||||||
|
|
@ -639,7 +639,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#output-element-accessible-name-computation
|
// https://w3c.github.io/html-aam/#output-element-accessible-name-computation
|
||||||
if (!labelledBy && element.tagName === 'OUTPUT') {
|
if (!labelledBy && tagName === 'OUTPUT') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const labels = (element as HTMLOutputElement).labels || [];
|
const labels = (element as HTMLOutputElement).labels || [];
|
||||||
if (labels.length)
|
if (labels.length)
|
||||||
|
|
@ -652,13 +652,13 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
// For "other form elements", we count select and any other input.
|
// For "other form elements", we count select and any other input.
|
||||||
//
|
//
|
||||||
// Note: WebKit does not follow the spec and uses placeholder when aria-labelledby is present.
|
// Note: WebKit does not follow the spec and uses placeholder when aria-labelledby is present.
|
||||||
if (!labelledBy && (element.tagName === 'TEXTAREA' || element.tagName === 'SELECT' || element.tagName === 'INPUT')) {
|
if (!labelledBy && (tagName === 'TEXTAREA' || tagName === 'SELECT' || tagName === 'INPUT')) {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const labels = (element as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)).labels || [];
|
const labels = (element as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)).labels || [];
|
||||||
if (labels.length)
|
if (labels.length)
|
||||||
return getAccessibleNameFromAssociatedLabels(labels, options);
|
return getAccessibleNameFromAssociatedLabels(labels, options);
|
||||||
|
|
||||||
const usePlaceholder = (element.tagName === 'INPUT' && ['text', 'password', 'search', 'tel', 'email', 'url'].includes((element as HTMLInputElement).type)) || element.tagName === 'TEXTAREA';
|
const usePlaceholder = (tagName === 'INPUT' && ['text', 'password', 'search', 'tel', 'email', 'url'].includes((element as HTMLInputElement).type)) || tagName === 'TEXTAREA';
|
||||||
const placeholder = element.getAttribute('placeholder') || '';
|
const placeholder = element.getAttribute('placeholder') || '';
|
||||||
const title = element.getAttribute('title') || '';
|
const title = element.getAttribute('title') || '';
|
||||||
if (!usePlaceholder || title)
|
if (!usePlaceholder || title)
|
||||||
|
|
@ -667,10 +667,10 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#fieldset-and-legend-elements
|
// https://w3c.github.io/html-aam/#fieldset-and-legend-elements
|
||||||
if (!labelledBy && element.tagName === 'FIELDSET') {
|
if (!labelledBy && tagName === 'FIELDSET') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
||||||
if (child.tagName === 'LEGEND') {
|
if (elementSafeTagName(child) === 'LEGEND') {
|
||||||
return getTextAlternativeInternal(child, {
|
return getTextAlternativeInternal(child, {
|
||||||
...childOptions,
|
...childOptions,
|
||||||
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
||||||
|
|
@ -682,10 +682,10 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#figure-and-figcaption-elements
|
// https://w3c.github.io/html-aam/#figure-and-figcaption-elements
|
||||||
if (!labelledBy && element.tagName === 'FIGURE') {
|
if (!labelledBy && tagName === 'FIGURE') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
||||||
if (child.tagName === 'FIGCAPTION') {
|
if (elementSafeTagName(child) === 'FIGCAPTION') {
|
||||||
return getTextAlternativeInternal(child, {
|
return getTextAlternativeInternal(child, {
|
||||||
...childOptions,
|
...childOptions,
|
||||||
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
||||||
|
|
@ -700,7 +700,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
//
|
//
|
||||||
// SPEC DIFFERENCE.
|
// SPEC DIFFERENCE.
|
||||||
// Spec says to ignore this when aria-labelledby is defined, but all browsers take it into account.
|
// Spec says to ignore this when aria-labelledby is defined, but all browsers take it into account.
|
||||||
if (element.tagName === 'IMG') {
|
if (tagName === 'IMG') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const alt = element.getAttribute('alt') || '';
|
const alt = element.getAttribute('alt') || '';
|
||||||
if (trimFlatString(alt))
|
if (trimFlatString(alt))
|
||||||
|
|
@ -710,10 +710,10 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#table-element
|
// https://w3c.github.io/html-aam/#table-element
|
||||||
if (element.tagName === 'TABLE') {
|
if (tagName === 'TABLE') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
||||||
if (child.tagName === 'CAPTION') {
|
if (elementSafeTagName(child) === 'CAPTION') {
|
||||||
return getTextAlternativeInternal(child, {
|
return getTextAlternativeInternal(child, {
|
||||||
...childOptions,
|
...childOptions,
|
||||||
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) },
|
||||||
|
|
@ -731,7 +731,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/html-aam/#area-element
|
// https://w3c.github.io/html-aam/#area-element
|
||||||
if (element.tagName === 'AREA') {
|
if (tagName === 'AREA') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const alt = element.getAttribute('alt') || '';
|
const alt = element.getAttribute('alt') || '';
|
||||||
if (trimFlatString(alt))
|
if (trimFlatString(alt))
|
||||||
|
|
@ -741,10 +741,10 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/svg-aam-1.0/#mapping_additional_nd
|
// https://www.w3.org/TR/svg-aam-1.0/#mapping_additional_nd
|
||||||
if (element.tagName.toUpperCase() === 'SVG' || (element as SVGElement).ownerSVGElement) {
|
if (tagName === 'SVG' || (element as SVGElement).ownerSVGElement) {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
for (let child = element.firstElementChild; child; child = child.nextElementSibling) {
|
||||||
if (child.tagName.toUpperCase() === 'TITLE' && (child as SVGElement).ownerSVGElement) {
|
if (elementSafeTagName(child) === 'TITLE' && (child as SVGElement).ownerSVGElement) {
|
||||||
return getTextAlternativeInternal(child, {
|
return getTextAlternativeInternal(child, {
|
||||||
...childOptions,
|
...childOptions,
|
||||||
embeddedInLabelledBy: { element: child, hidden: isElementHiddenForAria(child) },
|
embeddedInLabelledBy: { element: child, hidden: isElementHiddenForAria(child) },
|
||||||
|
|
@ -752,7 +752,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((element as SVGElement).ownerSVGElement && element.tagName.toUpperCase() === 'A') {
|
if ((element as SVGElement).ownerSVGElement && tagName === 'A') {
|
||||||
const title = element.getAttribute('xlink:title') || '';
|
const title = element.getAttribute('xlink:title') || '';
|
||||||
if (trimFlatString(title)) {
|
if (trimFlatString(title)) {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
|
|
@ -762,7 +762,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://w3c.github.io/html-aam/#summary-element-accessible-name-computation for "summary"-specific check.
|
// See https://w3c.github.io/html-aam/#summary-element-accessible-name-computation for "summary"-specific check.
|
||||||
const shouldNameFromContentForSummary = element.tagName === 'SUMMARY' && !['presentation', 'none'].includes(role);
|
const shouldNameFromContentForSummary = tagName === 'SUMMARY' && !['presentation', 'none'].includes(role);
|
||||||
|
|
||||||
// step 2f + step 2h.
|
// step 2f + step 2h.
|
||||||
if (allowsNameFromContent(role, options.embeddedInTargetElement === 'descendant') ||
|
if (allowsNameFromContent(role, options.embeddedInTargetElement === 'descendant') ||
|
||||||
|
|
@ -815,7 +815,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 2i.
|
// step 2i.
|
||||||
if (!['presentation', 'none'].includes(role) || element.tagName === 'IFRAME') {
|
if (!['presentation', 'none'].includes(role) || tagName === 'IFRAME') {
|
||||||
options.visitedElements.add(element);
|
options.visitedElements.add(element);
|
||||||
const title = element.getAttribute('title') || '';
|
const title = element.getAttribute('title') || '';
|
||||||
if (trimFlatString(title))
|
if (trimFlatString(title))
|
||||||
|
|
@ -830,7 +830,7 @@ export const kAriaSelectedRoles = ['gridcell', 'option', 'row', 'tab', 'rowheade
|
||||||
export function getAriaSelected(element: Element): boolean {
|
export function getAriaSelected(element: Element): boolean {
|
||||||
// https://www.w3.org/TR/wai-aria-1.2/#aria-selected
|
// https://www.w3.org/TR/wai-aria-1.2/#aria-selected
|
||||||
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
||||||
if (element.tagName === 'OPTION')
|
if (elementSafeTagName(element) === 'OPTION')
|
||||||
return (element as HTMLOptionElement).selected;
|
return (element as HTMLOptionElement).selected;
|
||||||
if (kAriaSelectedRoles.includes(getAriaRole(element) || ''))
|
if (kAriaSelectedRoles.includes(getAriaRole(element) || ''))
|
||||||
return getAriaBoolean(element.getAttribute('aria-selected')) === true;
|
return getAriaBoolean(element.getAttribute('aria-selected')) === true;
|
||||||
|
|
@ -843,11 +843,12 @@ export function getAriaChecked(element: Element): boolean | 'mixed' {
|
||||||
return result === 'error' ? false : result;
|
return result === 'error' ? false : result;
|
||||||
}
|
}
|
||||||
export function getChecked(element: Element, allowMixed: boolean): boolean | 'mixed' | 'error' {
|
export function getChecked(element: Element, allowMixed: boolean): boolean | 'mixed' | 'error' {
|
||||||
|
const tagName = elementSafeTagName(element);
|
||||||
// https://www.w3.org/TR/wai-aria-1.2/#aria-checked
|
// https://www.w3.org/TR/wai-aria-1.2/#aria-checked
|
||||||
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
||||||
if (allowMixed && element.tagName === 'INPUT' && (element as HTMLInputElement).indeterminate)
|
if (allowMixed && tagName === 'INPUT' && (element as HTMLInputElement).indeterminate)
|
||||||
return 'mixed';
|
return 'mixed';
|
||||||
if (element.tagName === 'INPUT' && ['checkbox', 'radio'].includes((element as HTMLInputElement).type))
|
if (tagName === 'INPUT' && ['checkbox', 'radio'].includes((element as HTMLInputElement).type))
|
||||||
return (element as HTMLInputElement).checked;
|
return (element as HTMLInputElement).checked;
|
||||||
if (kAriaCheckedRoles.includes(getAriaRole(element) || '')) {
|
if (kAriaCheckedRoles.includes(getAriaRole(element) || '')) {
|
||||||
const checked = element.getAttribute('aria-checked');
|
const checked = element.getAttribute('aria-checked');
|
||||||
|
|
@ -877,7 +878,7 @@ export const kAriaExpandedRoles = ['application', 'button', 'checkbox', 'combobo
|
||||||
export function getAriaExpanded(element: Element): boolean | 'none' {
|
export function getAriaExpanded(element: Element): boolean | 'none' {
|
||||||
// https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
|
// https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
|
||||||
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
||||||
if (element.tagName === 'DETAILS')
|
if (elementSafeTagName(element) === 'DETAILS')
|
||||||
return (element as HTMLDetailsElement).open;
|
return (element as HTMLDetailsElement).open;
|
||||||
if (kAriaExpandedRoles.includes(getAriaRole(element) || '')) {
|
if (kAriaExpandedRoles.includes(getAriaRole(element) || '')) {
|
||||||
const expanded = element.getAttribute('aria-expanded');
|
const expanded = element.getAttribute('aria-expanded');
|
||||||
|
|
@ -894,7 +895,7 @@ export const kAriaLevelRoles = ['heading', 'listitem', 'row', 'treeitem'];
|
||||||
export function getAriaLevel(element: Element): number {
|
export function getAriaLevel(element: Element): number {
|
||||||
// https://www.w3.org/TR/wai-aria-1.2/#aria-level
|
// https://www.w3.org/TR/wai-aria-1.2/#aria-level
|
||||||
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
// https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
|
||||||
const native = { 'H1': 1, 'H2': 2, 'H3': 3, 'H4': 4, 'H5': 5, 'H6': 6 }[element.tagName];
|
const native = { 'H1': 1, 'H2': 2, 'H3': 3, 'H4': 4, 'H5': 5, 'H6': 6 }[elementSafeTagName(element)];
|
||||||
if (native)
|
if (native)
|
||||||
return native;
|
return native;
|
||||||
if (kAriaLevelRoles.includes(getAriaRole(element) || '')) {
|
if (kAriaLevelRoles.includes(getAriaRole(element) || '')) {
|
||||||
|
|
@ -922,7 +923,7 @@ function isNativelyDisabled(element: Element) {
|
||||||
function belongsToDisabledFieldSet(element: Element | null): boolean {
|
function belongsToDisabledFieldSet(element: Element | null): boolean {
|
||||||
if (!element)
|
if (!element)
|
||||||
return false;
|
return false;
|
||||||
if (element.tagName === 'FIELDSET' && element.hasAttribute('disabled'))
|
if (elementSafeTagName(element) === 'FIELDSET' && element.hasAttribute('disabled'))
|
||||||
return true;
|
return true;
|
||||||
// fieldset does not work across shadow boundaries.
|
// fieldset does not work across shadow boundaries.
|
||||||
return belongsToDisabledFieldSet(element.parentElement);
|
return belongsToDisabledFieldSet(element.parentElement);
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,8 @@ export class HttpServer {
|
||||||
this._urlPrefix = address;
|
this._urlPrefix = address;
|
||||||
} else {
|
} else {
|
||||||
this._port = address.port;
|
this._port = address.port;
|
||||||
this._urlPrefix = `http://${host}:${address.port}`;
|
const resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
|
||||||
|
this._urlPrefix = `http://${resolvedHost}:${address.port}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this._urlPrefix;
|
return this._urlPrefix;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing Helpers",
|
"description": "Playwright Component Testing Helpers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next",
|
"playwright-core": "1.44.0",
|
||||||
"vite": "^5.2.8",
|
"vite": "^5.2.8",
|
||||||
"playwright": "1.44.0-next"
|
"playwright": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for React",
|
"description": "Playwright Component Testing for React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for React",
|
"description": "Playwright Component Testing for React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for Solid",
|
"description": "Playwright Component Testing for Solid",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for Svelte",
|
"description": "Playwright Component Testing for Svelte",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for Vue",
|
"description": "Playwright Component Testing for Vue",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "Playwright Component Testing for Vue2",
|
"description": "Playwright Component Testing for Vue2",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.44.0-next",
|
"@playwright/experimental-ct-core": "1.44.0",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-firefox",
|
"name": "playwright-firefox",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate Firefox",
|
"description": "A high-level API to automate Firefox",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
},
|
},
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.44.0-next"
|
"playwright": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-webkit",
|
"name": "playwright-webkit",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate WebKit",
|
"description": "A high-level API to automate WebKit",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright",
|
"name": "playwright",
|
||||||
"version": "1.44.0-next",
|
"version": "1.44.0",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.44.0-next"
|
"playwright-core": "1.44.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "2.3.2"
|
"fsevents": "2.3.2"
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import path from 'path';
|
||||||
import type { FullConfig, TestCase, Suite, TestResult, TestError, FullResult, TestStep, Location } from '../../types/testReporter';
|
import type { FullConfig, TestCase, Suite, TestResult, TestError, FullResult, TestStep, Location } from '../../types/testReporter';
|
||||||
import { getPackageManagerExecCommand } from 'playwright-core/lib/utils';
|
import { getPackageManagerExecCommand } from 'playwright-core/lib/utils';
|
||||||
import type { ReporterV2 } from './reporterV2';
|
import type { ReporterV2 } from './reporterV2';
|
||||||
|
import { resolveReporterOutputPath } from '../util';
|
||||||
export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' };
|
export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' };
|
||||||
export const kOutputSymbol = Symbol('output');
|
export const kOutputSymbol = Symbol('output');
|
||||||
|
|
||||||
|
|
@ -547,3 +548,49 @@ function fitToWidth(line: string, width: number, prefix?: string): string {
|
||||||
function belongsToNodeModules(file: string) {
|
function belongsToNodeModules(file: string) {
|
||||||
return file.includes(`${path.sep}node_modules${path.sep}`);
|
return file.includes(`${path.sep}node_modules${path.sep}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveFromEnv(name: string): string | undefined {
|
||||||
|
const value = process.env[name];
|
||||||
|
if (value)
|
||||||
|
return path.resolve(process.cwd(), value);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In addition to `outputFile` the function returns `outputDir` which should
|
||||||
|
// be cleaned up if present by some reporters contract.
|
||||||
|
export function resolveOutputFile(reporterName: string, options: {
|
||||||
|
configDir: string,
|
||||||
|
outputDir?: string,
|
||||||
|
fileName?: string,
|
||||||
|
outputFile?: string,
|
||||||
|
default?: {
|
||||||
|
fileName: string,
|
||||||
|
outputDir: string,
|
||||||
|
}
|
||||||
|
}): { outputFile: string, outputDir?: string } |undefined {
|
||||||
|
const name = reporterName.toUpperCase();
|
||||||
|
let outputFile;
|
||||||
|
if (options.outputFile)
|
||||||
|
outputFile = path.resolve(options.configDir, options.outputFile);
|
||||||
|
if (!outputFile)
|
||||||
|
outputFile = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_FILE`);
|
||||||
|
// Return early to avoid deleting outputDir.
|
||||||
|
if (outputFile)
|
||||||
|
return { outputFile };
|
||||||
|
|
||||||
|
let outputDir;
|
||||||
|
if (options.outputDir)
|
||||||
|
outputDir = path.resolve(options.configDir, options.outputDir);
|
||||||
|
if (!outputDir)
|
||||||
|
outputDir = resolveFromEnv(`PLAYWRIGHT_${name}_OUTPUT_DIR`);
|
||||||
|
if (!outputDir && options.default)
|
||||||
|
outputDir = resolveReporterOutputPath(options.default.outputDir, options.configDir, undefined);
|
||||||
|
|
||||||
|
if (!outputFile) {
|
||||||
|
const reportName = options.fileName ?? process.env[`PLAYWRIGHT_${name}_OUTPUT_NAME`] ?? options.default?.fileName;
|
||||||
|
if (!reportName)
|
||||||
|
return undefined;
|
||||||
|
outputFile = path.resolve(outputDir ?? process.cwd(), reportName);
|
||||||
|
}
|
||||||
|
return { outputFile, outputDir };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import type { FullConfig, FullResult, TestResult } from '../../types/testReporte
|
||||||
import type { JsonAttachment, JsonEvent } from '../isomorphic/teleReceiver';
|
import type { JsonAttachment, JsonEvent } from '../isomorphic/teleReceiver';
|
||||||
import { TeleReporterEmitter } from './teleEmitter';
|
import { TeleReporterEmitter } from './teleEmitter';
|
||||||
import { yazl } from 'playwright-core/lib/zipBundle';
|
import { yazl } from 'playwright-core/lib/zipBundle';
|
||||||
import { resolveReporterOutputPath } from '../util';
|
import { resolveOutputFile } from './base';
|
||||||
|
|
||||||
type BlobReporterOptions = {
|
type BlobReporterOptions = {
|
||||||
configDir: string;
|
configDir: string;
|
||||||
|
|
@ -107,17 +107,15 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _prepareOutputFile() {
|
private async _prepareOutputFile() {
|
||||||
let outputFile = reportOutputFileFromEnv();
|
const { outputFile, outputDir } = resolveOutputFile('BLOB', {
|
||||||
if (!outputFile && this._options.outputFile)
|
...this._options,
|
||||||
outputFile = path.resolve(this._options.configDir, this._options.outputFile);
|
default: {
|
||||||
// Explicit `outputFile` overrides `outputDir` and `fileName` options.
|
fileName: this._defaultReportName(this._config),
|
||||||
if (!outputFile) {
|
outputDir: 'blob-report',
|
||||||
const reportName = this._options.fileName || process.env[`PLAYWRIGHT_BLOB_OUTPUT_NAME`] || this._defaultReportName(this._config);
|
}
|
||||||
const outputDir = resolveReporterOutputPath('blob-report', this._options.configDir, this._options.outputDir ?? reportOutputDirFromEnv());
|
})!;
|
||||||
if (!process.env.PWTEST_BLOB_DO_NOT_REMOVE)
|
if (!process.env.PWTEST_BLOB_DO_NOT_REMOVE)
|
||||||
await removeFolders([outputDir]);
|
await removeFolders([outputDir!]);
|
||||||
outputFile = path.resolve(outputDir, reportName);
|
|
||||||
}
|
|
||||||
await fs.promises.mkdir(path.dirname(outputFile), { recursive: true });
|
await fs.promises.mkdir(path.dirname(outputFile), { recursive: true });
|
||||||
return outputFile;
|
return outputFile;
|
||||||
}
|
}
|
||||||
|
|
@ -149,15 +147,3 @@ export class BlobReporter extends TeleReporterEmitter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportOutputDirFromEnv(): string | undefined {
|
|
||||||
if (process.env[`PLAYWRIGHT_BLOB_OUTPUT_DIR`])
|
|
||||||
return path.resolve(process.cwd(), process.env[`PLAYWRIGHT_BLOB_OUTPUT_DIR`]);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reportOutputFileFromEnv(): string | undefined {
|
|
||||||
if (process.env[`PLAYWRIGHT_BLOB_OUTPUT_FILE`])
|
|
||||||
return path.resolve(process.cwd(), process.env[`PLAYWRIGHT_BLOB_OUTPUT_FILE`]);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,24 +17,29 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, FullResult, Location, JSONReport, JSONReportSuite, JSONReportSpec, JSONReportTest, JSONReportTestResult, JSONReportTestStep, JSONReportError } from '../../types/testReporter';
|
import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, FullResult, Location, JSONReport, JSONReportSuite, JSONReportSpec, JSONReportTest, JSONReportTestResult, JSONReportTestStep, JSONReportError } from '../../types/testReporter';
|
||||||
import { formatError, prepareErrorStack } from './base';
|
import { formatError, prepareErrorStack, resolveOutputFile } from './base';
|
||||||
import { MultiMap, assert, toPosixPath } from 'playwright-core/lib/utils';
|
import { MultiMap, toPosixPath } from 'playwright-core/lib/utils';
|
||||||
import { getProjectId } from '../common/config';
|
import { getProjectId } from '../common/config';
|
||||||
import EmptyReporter from './empty';
|
import EmptyReporter from './empty';
|
||||||
|
|
||||||
|
type JSONOptions = {
|
||||||
|
outputFile?: string,
|
||||||
|
configDir: string,
|
||||||
|
};
|
||||||
|
|
||||||
class JSONReporter extends EmptyReporter {
|
class JSONReporter extends EmptyReporter {
|
||||||
config!: FullConfig;
|
config!: FullConfig;
|
||||||
suite!: Suite;
|
suite!: Suite;
|
||||||
private _errors: TestError[] = [];
|
private _errors: TestError[] = [];
|
||||||
private _outputFile: string | undefined;
|
private _resolvedOutputFile: string | undefined;
|
||||||
|
|
||||||
constructor(options: { outputFile?: string } = {}) {
|
constructor(options: JSONOptions) {
|
||||||
super();
|
super();
|
||||||
this._outputFile = options.outputFile || reportOutputNameFromEnv();
|
this._resolvedOutputFile = resolveOutputFile('JSON', options)?.outputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
override printsToStdio() {
|
override printsToStdio() {
|
||||||
return !this._outputFile;
|
return !this._resolvedOutputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
override onConfigure(config: FullConfig) {
|
override onConfigure(config: FullConfig) {
|
||||||
|
|
@ -50,7 +55,7 @@ class JSONReporter extends EmptyReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
override async onEnd(result: FullResult) {
|
override async onEnd(result: FullResult) {
|
||||||
await outputReport(this._serializeReport(result), this.config, this._outputFile);
|
await outputReport(this._serializeReport(result), this._resolvedOutputFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _serializeReport(result: FullResult): JSONReport {
|
private _serializeReport(result: FullResult): JSONReport {
|
||||||
|
|
@ -228,13 +233,11 @@ class JSONReporter extends EmptyReporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function outputReport(report: JSONReport, config: FullConfig, outputFile: string | undefined) {
|
async function outputReport(report: JSONReport, resolvedOutputFile: string | undefined) {
|
||||||
const reportString = JSON.stringify(report, undefined, 2);
|
const reportString = JSON.stringify(report, undefined, 2);
|
||||||
if (outputFile) {
|
if (resolvedOutputFile) {
|
||||||
assert(config.configFile || path.isAbsolute(outputFile), 'Expected fully resolved path if not using config file.');
|
await fs.promises.mkdir(path.dirname(resolvedOutputFile), { recursive: true });
|
||||||
outputFile = config.configFile ? path.resolve(path.dirname(config.configFile), outputFile) : outputFile;
|
await fs.promises.writeFile(resolvedOutputFile, reportString);
|
||||||
await fs.promises.mkdir(path.dirname(outputFile), { recursive: true });
|
|
||||||
await fs.promises.writeFile(outputFile, reportString);
|
|
||||||
} else {
|
} else {
|
||||||
console.log(reportString);
|
console.log(reportString);
|
||||||
}
|
}
|
||||||
|
|
@ -250,12 +253,6 @@ function removePrivateFields(config: FullConfig): FullConfig {
|
||||||
return Object.fromEntries(Object.entries(config).filter(([name, value]) => !name.startsWith('_'))) as FullConfig;
|
return Object.fromEntries(Object.entries(config).filter(([name, value]) => !name.startsWith('_'))) as FullConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportOutputNameFromEnv(): string | undefined {
|
|
||||||
if (process.env[`PLAYWRIGHT_JSON_OUTPUT_NAME`])
|
|
||||||
return path.resolve(process.cwd(), process.env[`PLAYWRIGHT_JSON_OUTPUT_NAME`]);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function serializePatterns(patterns: string | RegExp | (string | RegExp)[]): string[] {
|
export function serializePatterns(patterns: string | RegExp | (string | RegExp)[]): string[] {
|
||||||
if (!Array.isArray(patterns))
|
if (!Array.isArray(patterns))
|
||||||
patterns = [patterns];
|
patterns = [patterns];
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { FullConfig, FullResult, Suite, TestCase } from '../../types/testReporter';
|
import type { FullConfig, FullResult, Suite, TestCase } from '../../types/testReporter';
|
||||||
import { formatFailure, stripAnsiEscapes } from './base';
|
import { formatFailure, resolveOutputFile, stripAnsiEscapes } from './base';
|
||||||
import EmptyReporter from './empty';
|
import EmptyReporter from './empty';
|
||||||
|
|
||||||
type JUnitOptions = {
|
type JUnitOptions = {
|
||||||
|
|
@ -25,7 +25,7 @@ type JUnitOptions = {
|
||||||
stripANSIControlSequences?: boolean,
|
stripANSIControlSequences?: boolean,
|
||||||
includeProjectInTestName?: boolean,
|
includeProjectInTestName?: boolean,
|
||||||
|
|
||||||
configDir?: string,
|
configDir: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
class JUnitReporter extends EmptyReporter {
|
class JUnitReporter extends EmptyReporter {
|
||||||
|
|
@ -40,14 +40,12 @@ class JUnitReporter extends EmptyReporter {
|
||||||
private stripANSIControlSequences = false;
|
private stripANSIControlSequences = false;
|
||||||
private includeProjectInTestName = false;
|
private includeProjectInTestName = false;
|
||||||
|
|
||||||
constructor(options: JUnitOptions = {}) {
|
constructor(options: JUnitOptions) {
|
||||||
super();
|
super();
|
||||||
this.stripANSIControlSequences = options.stripANSIControlSequences || false;
|
this.stripANSIControlSequences = options.stripANSIControlSequences || false;
|
||||||
this.includeProjectInTestName = options.includeProjectInTestName || false;
|
this.includeProjectInTestName = options.includeProjectInTestName || false;
|
||||||
this.configDir = options.configDir || '';
|
this.configDir = options.configDir;
|
||||||
const outputFile = options.outputFile || reportOutputNameFromEnv();
|
this.resolvedOutputFile = resolveOutputFile('JUNIT', options)?.outputFile;
|
||||||
if (outputFile)
|
|
||||||
this.resolvedOutputFile = path.resolve(this.configDir, outputFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override printsToStdio() {
|
override printsToStdio() {
|
||||||
|
|
@ -261,10 +259,4 @@ function escape(text: string, stripANSIControlSequences: boolean, isCharacterDat
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportOutputNameFromEnv(): string | undefined {
|
|
||||||
if (process.env[`PLAYWRIGHT_JUNIT_OUTPUT_NAME`])
|
|
||||||
return path.resolve(process.cwd(), process.env[`PLAYWRIGHT_JUNIT_OUTPUT_NAME`]);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default JUnitReporter;
|
export default JUnitReporter;
|
||||||
|
|
|
||||||
|
|
@ -450,6 +450,18 @@ test('svg role=presentation', async ({ page }) => {
|
||||||
expect.soft(await getNameAndRole(page, 'svg')).toEqual({ role: 'presentation', name: '' });
|
expect.soft(await getNameAndRole(page, 'svg')).toEqual({ role: 'presentation', name: '' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with form and tricky input names', async ({ page }) => {
|
||||||
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30616' });
|
||||||
|
|
||||||
|
await page.setContent(`
|
||||||
|
<form aria-label="my form">
|
||||||
|
<input name="tagName" value="hello" title="tagName input">
|
||||||
|
<input name="localName" value="hello" title="localName input">
|
||||||
|
</form>
|
||||||
|
`);
|
||||||
|
expect.soft(await getNameAndRole(page, 'form')).toEqual({ role: 'form', name: 'my form' });
|
||||||
|
});
|
||||||
|
|
||||||
function toArray(x: any): any[] {
|
function toArray(x: any): any[] {
|
||||||
return Array.isArray(x) ? x : [x];
|
return Array.isArray(x) ? x : [x];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1292,12 +1292,18 @@ test('support PLAYWRIGHT_BLOB_OUTPUT_FILE environment variable', async ({ runInl
|
||||||
test('math 1 @smoke', async ({}) => {});
|
test('math 1 @smoke', async ({}) => {});
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
const defaultDir = test.info().outputPath('blob-report');
|
||||||
|
fs.mkdirSync(defaultDir, { recursive: true });
|
||||||
|
const file = path.join(defaultDir, 'some.file');
|
||||||
|
fs.writeFileSync(file, 'content');
|
||||||
|
|
||||||
await runInlineTest(files, { shard: `1/2` }, { PLAYWRIGHT_BLOB_OUTPUT_FILE: 'subdir/report-one.zip' });
|
await runInlineTest(files, { shard: `1/2` }, { PLAYWRIGHT_BLOB_OUTPUT_FILE: 'subdir/report-one.zip' });
|
||||||
await runInlineTest(files, { shard: `2/2` }, { PLAYWRIGHT_BLOB_OUTPUT_FILE: test.info().outputPath('subdir/report-two.zip') });
|
await runInlineTest(files, { shard: `2/2` }, { PLAYWRIGHT_BLOB_OUTPUT_FILE: test.info().outputPath('subdir/report-two.zip') });
|
||||||
const reportDir = test.info().outputPath('subdir');
|
const reportDir = test.info().outputPath('subdir');
|
||||||
const reportFiles = await fs.promises.readdir(reportDir);
|
const reportFiles = await fs.promises.readdir(reportDir);
|
||||||
expect(reportFiles.sort()).toEqual(['report-one.zip', 'report-two.zip']);
|
expect(reportFiles.sort()).toEqual(['report-one.zip', 'report-two.zip']);
|
||||||
|
|
||||||
|
expect(fs.existsSync(file), 'Default directory should not be cleaned up if output file is specified.').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('keep projects with same name different bot name separate', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
test('keep projects with same name different bot name separate', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||||
|
|
|
||||||
|
|
@ -288,4 +288,42 @@ test.describe('report location', () => {
|
||||||
expect(result.passed).toBe(1);
|
expect(result.passed).toBe(1);
|
||||||
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.json'))).toBe(true);
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.json'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('support PLAYWRIGHT_JSON_OUTPUT_FILE', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'foo/package.json': `{ "name": "foo" }`,
|
||||||
|
// unused config along "search path"
|
||||||
|
'foo/bar/playwright.config.js': `
|
||||||
|
module.exports = { projects: [ {} ] };
|
||||||
|
`,
|
||||||
|
'foo/bar/baz/tests/a.spec.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const fs = require('fs');
|
||||||
|
test('pass', ({}, testInfo) => {
|
||||||
|
});
|
||||||
|
`
|
||||||
|
}, { 'reporter': 'json' }, { 'PW_TEST_HTML_REPORT_OPEN': 'never', 'PLAYWRIGHT_JSON_OUTPUT_FILE': '../my-report.json' }, {
|
||||||
|
cwd: 'foo/bar/baz/tests',
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.json'))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('support PLAYWRIGHT_JSON_OUTPUT_DIR and PLAYWRIGHT_JSON_OUTPUT_NAME', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.js': `
|
||||||
|
module.exports = { projects: [ {} ] };
|
||||||
|
`,
|
||||||
|
'tests/a.spec.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const fs = require('fs');
|
||||||
|
test('pass', ({}, testInfo) => {
|
||||||
|
});
|
||||||
|
`
|
||||||
|
}, { 'reporter': 'json' }, { 'PLAYWRIGHT_JSON_OUTPUT_DIR': 'foo/bar', 'PLAYWRIGHT_JSON_OUTPUT_NAME': 'baz/my-report.json' });
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.json'))).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,44 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||||
expect(result.passed).toBe(1);
|
expect(result.passed).toBe(1);
|
||||||
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.xml'))).toBe(true);
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.xml'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('support PLAYWRIGHT_JUNIT_OUTPUT_FILE', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'foo/package.json': `{ "name": "foo" }`,
|
||||||
|
// unused config along "search path"
|
||||||
|
'foo/bar/playwright.config.js': `
|
||||||
|
module.exports = { projects: [ {} ] };
|
||||||
|
`,
|
||||||
|
'foo/bar/baz/tests/a.spec.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const fs = require('fs');
|
||||||
|
test('pass', ({}, testInfo) => {
|
||||||
|
});
|
||||||
|
`
|
||||||
|
}, { 'reporter': 'junit,line' }, { 'PLAYWRIGHT_JUNIT_OUTPUT_FILE': '../my-report.xml' }, {
|
||||||
|
cwd: 'foo/bar/baz/tests',
|
||||||
|
});
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.xml'))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('support PLAYWRIGHT_JUNIT_OUTPUT_DIR and PLAYWRIGHT_JUNIT_OUTPUT_NAME', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.js': `
|
||||||
|
module.exports = { projects: [ {} ] };
|
||||||
|
`,
|
||||||
|
'tests/a.spec.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const fs = require('fs');
|
||||||
|
test('pass', ({}, testInfo) => {
|
||||||
|
});
|
||||||
|
`
|
||||||
|
}, { 'reporter': 'junit,line' }, { 'PLAYWRIGHT_JUNIT_OUTPUT_DIR': 'foo/bar', 'PLAYWRIGHT_JUNIT_OUTPUT_NAME': 'baz/my-report.xml' });
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report.xml'))).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('testsuites time is test run wall time', async ({ runInlineTest }) => {
|
test('testsuites time is test run wall time', async ({ runInlineTest }) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue