Merge branch 'main' into stevanfreeborn/feat-29531/retain-first-failure-only
This commit is contained in:
commit
c2c8e3a279
|
|
@ -20,3 +20,4 @@ tests/installation/fixture-scripts/
|
||||||
examples/
|
examples/
|
||||||
DEPS
|
DEPS
|
||||||
.cache/
|
.cache/
|
||||||
|
utils/
|
||||||
|
|
|
||||||
15
.eslintrc-with-ts-config.js
Normal file
15
.eslintrc-with-ts-config.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: "./.eslintrc.js",
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 9,
|
||||||
|
sourceType: "module",
|
||||||
|
project: "./tsconfig.json",
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-base-to-string": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-boolean-literal-compare": 2,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
project: "./tsconfig.json"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -48,6 +48,7 @@ module.exports = {
|
||||||
"arrow-parens": [2, "as-needed"],
|
"arrow-parens": [2, "as-needed"],
|
||||||
"prefer-const": 2,
|
"prefer-const": 2,
|
||||||
"quote-props": [2, "consistent"],
|
"quote-props": [2, "consistent"],
|
||||||
|
"nonblock-statement-body-position": [2, "below"],
|
||||||
|
|
||||||
// anti-patterns
|
// anti-patterns
|
||||||
"no-var": 2,
|
"no-var": 2,
|
||||||
|
|
|
||||||
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -23,7 +23,7 @@ body:
|
||||||
value: |
|
value: |
|
||||||
## Make a minimal reproduction
|
## Make a minimal reproduction
|
||||||
To file the report, you will need a GitHub repository with a minimal (but complete) example and simple/clear steps on how to reproduce the bug.
|
To file the report, you will need a GitHub repository with a minimal (but complete) example and simple/clear steps on how to reproduce the bug.
|
||||||
The simpler you can make it, the more likely we are to successfully verify and fix the bug.
|
The simpler you can make it, the more likely we are to successfully verify and fix the bug. You can create a new project with `npm init playwright@latest new-project` and then add the test code there.
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
|
||||||
| :--- | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: |
|
||||||
| Chromium <!-- GEN:chromium-version -->123.0.6312.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Chromium <!-- GEN:chromium-version -->123.0.6312.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: |
|
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| Firefox <!-- GEN:firefox-version -->122.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Firefox <!-- GEN:firefox-version -->123.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
|
||||||
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
|
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ title: "CI GitHub Actions"
|
||||||
|
|
||||||
Playwright tests can be run on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed [doc on Continuous Integration](./ci.md).
|
Playwright tests can be run on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed [doc on Continuous Integration](./ci.md).
|
||||||
|
|
||||||
When [installing Playwright](./intro.md) using the [VS Code extension](./getting-started-vscode.md) or with `npm init playwright@latest` you are given the option to add a [GitHub Actions](https://docs.github.com/en/actions). This creates a `playwright.yml` file inside a `.github/workflows` folder containing everything you need so that your tests run on each push and pull request into the main/master branch.
|
When [installing Playwright](./intro.md) using the [VS Code extension](./getting-started-vscode.md) or with `npm init playwright@latest` you are given the option to add a [GitHub Actions](https://docs.github.com/en/actions) workflow. This creates a `playwright.yml` file inside a `.github/workflows` folder containing everything you need so that your tests run on each push and pull request into the main/master branch.
|
||||||
|
|
||||||
#### You will learn
|
#### You will learn
|
||||||
* langs: js
|
* langs: js
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,82 @@ toc_max_heading_level: 2
|
||||||
|
|
||||||
import LiteYouTube from '@site/src/components/LiteYouTube';
|
import LiteYouTube from '@site/src/components/LiteYouTube';
|
||||||
|
|
||||||
|
## Version 1.42
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
- New method [`method: Page.addLocatorHandler`] registers a callback that will be invoked when specified element becomes visible and may block Playwright actions. The callback can get rid of the overlay. Here is an example that closes a cookie dialog when it appears:
|
||||||
|
```js
|
||||||
|
// Setup the handler.
|
||||||
|
await page.addLocatorHandler(page.getByRole('button', { name: 'Accept all cookies' }), async () => {
|
||||||
|
await page.getByRole('button', { name: 'Reject all cookies' }).click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write the test as usual.
|
||||||
|
await page.goto('https://example.com');
|
||||||
|
await page.getByRole('button', { name: 'Start here' }).click();
|
||||||
|
```
|
||||||
|
|
||||||
|
- `expect(callback).toPass()` timeout can now be configured by `expect.toPass.timeout` option [globally](./api/class-testconfig#test-config-expect) or in [project config](./api/class-testproject#test-project-expect)
|
||||||
|
|
||||||
|
- [`event: ElectronApplication.console`] event is emitted when Electron main process calls console API methods.
|
||||||
|
```js
|
||||||
|
electronApp.on('console', async msg => {
|
||||||
|
const values = [];
|
||||||
|
for (const arg of msg.args())
|
||||||
|
values.push(await arg.jsonValue());
|
||||||
|
console.log(...values);
|
||||||
|
});
|
||||||
|
await electronApp.evaluate(() => console.log('hello', 5, { foo: 'bar' }));
|
||||||
|
```
|
||||||
|
|
||||||
|
- [New syntax](./test-annotations#tag-tests) for adding tags to the tests (@-tokens in the test title are still supported):
|
||||||
|
```js
|
||||||
|
test('test customer login', {
|
||||||
|
tag: ['@fast', '@login'],
|
||||||
|
}, async ({ page }) => {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
Use `--grep` command line option to run only tests with certain tags.
|
||||||
|
```sh
|
||||||
|
npx playwright test --grep @fast
|
||||||
|
```
|
||||||
|
|
||||||
|
- `--project` command line [flag](./test-cli#reference) now supports '*' wildcard:
|
||||||
|
```sh
|
||||||
|
npx playwright test --project='*mobile*'
|
||||||
|
```
|
||||||
|
|
||||||
|
- [New syntax](./test-annotations#annotate-tests) for test annotations:
|
||||||
|
```js
|
||||||
|
test('test full report', {
|
||||||
|
annotation: [
|
||||||
|
{ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/23180' },
|
||||||
|
{ type: 'docs', description: 'https://playwright.dev/docs/test-annotations#tag-tests' },
|
||||||
|
],
|
||||||
|
}, async ({ page }) => {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- [`method: Page.pdf`] accepts two new options [`tagged`](./api/class-page#page-pdf-option-tagged) and [`outline`](./api/class-page#page-pdf-option-outline).
|
||||||
|
|
||||||
|
### Announcements
|
||||||
|
|
||||||
|
* ⚠️ Ubuntu 18 is not supported anymore.
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 123.0.6312.4
|
||||||
|
* Mozilla Firefox 123.0
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 122
|
||||||
|
* Microsoft Edge 123
|
||||||
|
|
||||||
## Version 1.41
|
## Version 1.41
|
||||||
|
|
||||||
### New APIs
|
### New APIs
|
||||||
|
|
|
||||||
|
|
@ -137,10 +137,12 @@ self.addEventListener('fetch', event => {
|
||||||
(async () => {
|
(async () => {
|
||||||
// 1. Try to first serve directly from caches
|
// 1. Try to first serve directly from caches
|
||||||
const response = await caches.match(event.request);
|
const response = await caches.match(event.request);
|
||||||
if (response) return response;
|
if (response)
|
||||||
|
return response;
|
||||||
|
|
||||||
// 2. Re-write request for /foo to /bar
|
// 2. Re-write request for /foo to /bar
|
||||||
if (event.request.url.endsWith('foo')) return fetch('./bar');
|
if (event.request.url.endsWith('foo'))
|
||||||
|
return fetch('./bar');
|
||||||
|
|
||||||
// 3. Prevent tracker.js from being retrieved, and returns a placeholder response
|
// 3. Prevent tracker.js from being retrieved, and returns a placeholder response
|
||||||
if (event.request.url.endsWith('tracker.js')) {
|
if (event.request.url.endsWith('tracker.js')) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,26 @@ title: "TypeScript"
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Playwright supports TypeScript out of the box. You just write tests in TypeScript, and Playwright will read them, transform to JavaScript and run.
|
Playwright supports TypeScript out of the box. You just write tests in TypeScript, and Playwright will read them, transform to JavaScript and run. Note that Playwright does not check the types and will run tests even if there are non-critical TypeScript compilation errors.
|
||||||
|
|
||||||
|
We recommend you run TypeScript compiler alongside Playwright. For example on GitHub actions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
...
|
||||||
|
- name: Run type checks
|
||||||
|
run: npx tsc -p tsconfig.json --noEmit
|
||||||
|
- name: Run Playwright tests
|
||||||
|
run: npx playwright test
|
||||||
|
```
|
||||||
|
|
||||||
|
For local development, you can run `tsc` in [watch](https://www.typescriptlang.org/docs/handbook/configuring-watch.html) mode like this:
|
||||||
|
```sh
|
||||||
|
npx tsc -p tsconfig.json --noEmit -w
|
||||||
|
```
|
||||||
|
|
||||||
## tsconfig.json
|
## tsconfig.json
|
||||||
|
|
||||||
|
|
|
||||||
68
package-lock.json
generated
68
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
@ -8136,10 +8136,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright": {
|
"packages/playwright": {
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8153,11 +8153,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-chromium": {
|
"packages/playwright-browser-chromium": {
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8165,11 +8165,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-firefox": {
|
"packages/playwright-browser-firefox": {
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8177,22 +8177,22 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-webkit": {
|
"packages/playwright-browser-webkit": {
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-chromium": {
|
"packages/playwright-chromium": {
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8202,7 +8202,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-core": {
|
"packages/playwright-core": {
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
|
|
@ -8213,11 +8213,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-core": {
|
"packages/playwright-ct-core": {
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.42.0-next",
|
"playwright": "1.43.0-next",
|
||||||
"playwright-core": "1.42.0-next",
|
"playwright-core": "1.43.0-next",
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.0.12"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8229,10 +8229,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react": {
|
"packages/playwright-ct-react": {
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8245,10 +8245,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react17": {
|
"packages/playwright-ct-react17": {
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8261,10 +8261,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-solid": {
|
"packages/playwright-ct-solid": {
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8280,10 +8280,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-svelte": {
|
"packages/playwright-ct-svelte": {
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8299,10 +8299,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue": {
|
"packages/playwright-ct-vue": {
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8315,10 +8315,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue2": {
|
"packages/playwright-ct-vue2": {
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8368,11 +8368,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-firefox": {
|
"packages/playwright-firefox": {
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8383,10 +8383,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-test": {
|
"packages/playwright-test": {
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.42.0-next"
|
"playwright": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8396,11 +8396,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-webkit": {
|
"packages/playwright-webkit": {
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
"ttest": "node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts",
|
"ttest": "node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts",
|
||||||
"ct": "playwright test tests/components/test-all.spec.js --reporter=list",
|
"ct": "playwright test tests/components/test-all.spec.js --reporter=list",
|
||||||
"test": "playwright test --config=tests/library/playwright.config.ts",
|
"test": "playwright test --config=tests/library/playwright.config.ts",
|
||||||
"eslint": "eslint --cache --report-unused-disable-directives --ext ts,tsx .",
|
"eslint": "eslint --cache --report-unused-disable-directives --ext ts,tsx,js,jsx,mjs .",
|
||||||
"tsc": "tsc -p .",
|
"tsc": "tsc -p .",
|
||||||
"build-installer": "babel -s --extensions \".ts\" --out-dir packages/playwright-core/lib/utils/ packages/playwright-core/src/utils",
|
"build-installer": "babel -s --extensions \".ts\" --out-dir packages/playwright-core/lib/utils/ packages/playwright-core/src/utils",
|
||||||
"doc": "node utils/doclint/cli.js",
|
"doc": "node utils/doclint/cli.js",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
extends: ".eslintrc.js",
|
|
||||||
rules: {
|
|
||||||
"@typescript-eslint/no-base-to-string": "error",
|
|
||||||
},
|
|
||||||
parserOptions: {
|
|
||||||
project: "./tsconfig.json"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-chromium",
|
"name": "playwright-chromium",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: "../.eslintrc-with-ts-config.js",
|
extends: "../../.eslintrc-with-ts-config.js",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,15 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox",
|
"name": "firefox",
|
||||||
"revision": "1439",
|
"revision": "1440",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "122.0"
|
"browserVersion": "123.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox-asan",
|
"name": "firefox-asan",
|
||||||
"revision": "1439",
|
"revision": "1440",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "122.0"
|
"browserVersion": "123.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox-beta",
|
"name": "firefox-beta",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-core",
|
"name": "playwright-core",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -526,7 +526,7 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
|
||||||
function toAcceptDownloadsProtocol(acceptDownloads?: boolean) {
|
function toAcceptDownloadsProtocol(acceptDownloads?: boolean) {
|
||||||
if (acceptDownloads === undefined)
|
if (acceptDownloads === undefined)
|
||||||
return undefined;
|
return undefined;
|
||||||
if (acceptDownloads === true)
|
if (acceptDownloads)
|
||||||
return 'accept';
|
return 'accept';
|
||||||
return 'deny';
|
return 'deny';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -594,7 +594,8 @@ export class CRBrowserContext extends BrowserContext {
|
||||||
targetId = (page._delegate as CRPage)._targetId;
|
targetId = (page._delegate as CRPage)._targetId;
|
||||||
} else if (page instanceof Frame) {
|
} else if (page instanceof Frame) {
|
||||||
const session = (page._page._delegate as CRPage)._sessions.get(page._id);
|
const session = (page._page._delegate as CRPage)._sessions.get(page._id);
|
||||||
if (!session) throw new Error(`This frame does not have a separate CDP session, it is a part of the parent frame's session`);
|
if (!session)
|
||||||
|
throw new Error(`This frame does not have a separate CDP session, it is a part of the parent frame's session`);
|
||||||
targetId = session._targetId;
|
targetId = session._targetId;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('page: expected Page or Frame');
|
throw new Error('page: expected Page or Frame');
|
||||||
|
|
|
||||||
|
|
@ -1472,7 +1472,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Firefox HiDPI": {
|
"Desktop Firefox HiDPI": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1792,
|
"width": 1792,
|
||||||
"height": 1120
|
"height": 1120
|
||||||
|
|
@ -1532,7 +1532,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Firefox": {
|
"Desktop Firefox": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1920,
|
"width": 1920,
|
||||||
"height": 1080
|
"height": 1080
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,18 @@ function buildComponentsTreeVue3(instance: VueVNode): ComponentNode {
|
||||||
// @see https://github.com/vuejs/devtools/blob/e7132f3392b975e39e1d9a23cf30456c270099c2/packages/app-backend-vue3/src/components/util.ts#L29
|
// @see https://github.com/vuejs/devtools/blob/e7132f3392b975e39e1d9a23cf30456c270099c2/packages/app-backend-vue3/src/components/util.ts#L29
|
||||||
function getInstanceName(instance: VueVNode): string {
|
function getInstanceName(instance: VueVNode): string {
|
||||||
const name = getComponentTypeName(instance.type || {});
|
const name = getComponentTypeName(instance.type || {});
|
||||||
if (name) return name;
|
if (name)
|
||||||
if (instance.root === instance) return 'Root';
|
return name;
|
||||||
for (const key in instance.parent?.type?.components)
|
if (instance.root === instance)
|
||||||
if (instance.parent?.type.components[key] === instance.type) return saveComponentName(instance, key);
|
return 'Root';
|
||||||
for (const key in instance.appContext?.components)
|
for (const key in instance.parent?.type?.components) {
|
||||||
if (instance.appContext.components[key] === instance.type) return saveComponentName(instance, key);
|
if (instance.parent?.type.components[key] === instance.type)
|
||||||
|
return saveComponentName(instance, key);
|
||||||
|
}
|
||||||
|
for (const key in instance.appContext?.components) {
|
||||||
|
if (instance.appContext.components[key] === instance.type)
|
||||||
|
return saveComponentName(instance, key);
|
||||||
|
}
|
||||||
return 'Anonymous Component';
|
return 'Anonymous Component';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +138,8 @@ function buildComponentsTreeVue3(instance: VueVNode): ComponentNode {
|
||||||
|
|
||||||
// @see https://github.com/vuejs/devtools/blob/e7132f3392b975e39e1d9a23cf30456c270099c2/packages/app-backend-vue3/src/components/el.ts#L15
|
// @see https://github.com/vuejs/devtools/blob/e7132f3392b975e39e1d9a23cf30456c270099c2/packages/app-backend-vue3/src/components/el.ts#L15
|
||||||
function getFragmentRootElements(vnode: any): Element[] {
|
function getFragmentRootElements(vnode: any): Element[] {
|
||||||
if (!vnode.children) return [];
|
if (!vnode.children)
|
||||||
|
return [];
|
||||||
|
|
||||||
const list = [];
|
const list = [];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,10 @@ function preprocess(str: string): number[] {
|
||||||
if (code === 0xd && str.charCodeAt(i + 1) === 0xa) {
|
if (code === 0xd && str.charCodeAt(i + 1) === 0xa) {
|
||||||
code = 0xa; i++;
|
code = 0xa; i++;
|
||||||
}
|
}
|
||||||
if (code === 0xd || code === 0xc) code = 0xa;
|
if (code === 0xd || code === 0xc)
|
||||||
if (code === 0x0) code = 0xfffd;
|
code = 0xa;
|
||||||
|
if (code === 0x0)
|
||||||
|
code = 0xfffd;
|
||||||
if (between(code, 0xd800, 0xdbff) && between(str.charCodeAt(i + 1), 0xdc00, 0xdfff)) {
|
if (between(code, 0xd800, 0xdbff) && between(str.charCodeAt(i + 1), 0xdc00, 0xdfff)) {
|
||||||
// Decode a surrogate pair into an astral codepoint.
|
// Decode a surrogate pair into an astral codepoint.
|
||||||
const lead = code - 0xd800;
|
const lead = code - 0xd800;
|
||||||
|
|
@ -63,7 +65,8 @@ function preprocess(str: string): number[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringFromCode(code: number) {
|
function stringFromCode(code: number) {
|
||||||
if (code <= 0xffff) return String.fromCharCode(code);
|
if (code <= 0xffff)
|
||||||
|
return String.fromCharCode(code);
|
||||||
// Otherwise, encode astral char as surrogate pair.
|
// Otherwise, encode astral char as surrogate pair.
|
||||||
code -= Math.pow(2, 16);
|
code -= Math.pow(2, 16);
|
||||||
const lead = Math.floor(code / Math.pow(2, 10)) + 0xd800;
|
const lead = Math.floor(code / Math.pow(2, 10)) + 0xd800;
|
||||||
|
|
@ -107,8 +110,10 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
num = 1;
|
num = 1;
|
||||||
i += num;
|
i += num;
|
||||||
code = codepoint(i);
|
code = codepoint(i);
|
||||||
if (newline(code)) incrLineno();
|
if (newline(code))
|
||||||
else column += num;
|
incrLineno();
|
||||||
|
else
|
||||||
|
column += num;
|
||||||
// console.log('Consume '+i+' '+String.fromCharCode(code) + ' 0x' + code.toString(16));
|
// console.log('Consume '+i+' '+String.fromCharCode(code) + ' 0x' + code.toString(16));
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
@ -125,7 +130,8 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
const eof = function(codepoint?: number): boolean {
|
const eof = function(codepoint?: number): boolean {
|
||||||
if (codepoint === undefined) codepoint = code;
|
if (codepoint === undefined)
|
||||||
|
codepoint = code;
|
||||||
return codepoint === -1;
|
return codepoint === -1;
|
||||||
};
|
};
|
||||||
const donothing = function() { };
|
const donothing = function() { };
|
||||||
|
|
@ -138,12 +144,14 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
consumeComments();
|
consumeComments();
|
||||||
consume();
|
consume();
|
||||||
if (whitespace(code)) {
|
if (whitespace(code)) {
|
||||||
while (whitespace(next())) consume();
|
while (whitespace(next()))
|
||||||
|
consume();
|
||||||
return new WhitespaceToken();
|
return new WhitespaceToken();
|
||||||
} else if (code === 0x22) {return consumeAStringToken();} else if (code === 0x23) {
|
} else if (code === 0x22) {return consumeAStringToken();} else if (code === 0x23) {
|
||||||
if (namechar(next()) || areAValidEscape(next(1), next(2))) {
|
if (namechar(next()) || areAValidEscape(next(1), next(2))) {
|
||||||
const token = new HashToken('');
|
const token = new HashToken('');
|
||||||
if (wouldStartAnIdentifier(next(1), next(2), next(3))) token.type = 'id';
|
if (wouldStartAnIdentifier(next(1), next(2), next(3)))
|
||||||
|
token.type = 'id';
|
||||||
token.value = consumeAName();
|
token.value = consumeAName();
|
||||||
return token;
|
return token;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -288,7 +296,8 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
const str = consumeAName();
|
const str = consumeAName();
|
||||||
if (str.toLowerCase() === 'url' && next() === 0x28) {
|
if (str.toLowerCase() === 'url' && next() === 0x28) {
|
||||||
consume();
|
consume();
|
||||||
while (whitespace(next(1)) && whitespace(next(2))) consume();
|
while (whitespace(next(1)) && whitespace(next(2)))
|
||||||
|
consume();
|
||||||
if (next() === 0x22 || next() === 0x27)
|
if (next() === 0x22 || next() === 0x27)
|
||||||
return new FunctionToken(str);
|
return new FunctionToken(str);
|
||||||
else if (whitespace(next()) && (next(2) === 0x22 || next(2) === 0x27))
|
else if (whitespace(next()) && (next(2) === 0x22 || next(2) === 0x27))
|
||||||
|
|
@ -305,7 +314,8 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
};
|
};
|
||||||
|
|
||||||
const consumeAStringToken = function(endingCodePoint?: number): CSSParserToken {
|
const consumeAStringToken = function(endingCodePoint?: number): CSSParserToken {
|
||||||
if (endingCodePoint === undefined) endingCodePoint = code;
|
if (endingCodePoint === undefined)
|
||||||
|
endingCodePoint = code;
|
||||||
let string = '';
|
let string = '';
|
||||||
while (consume()) {
|
while (consume()) {
|
||||||
if (code === endingCodePoint || eof()) {
|
if (code === endingCodePoint || eof()) {
|
||||||
|
|
@ -331,13 +341,16 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
|
|
||||||
const consumeAURLToken = function(): CSSTokenInterface {
|
const consumeAURLToken = function(): CSSTokenInterface {
|
||||||
const token = new URLToken('');
|
const token = new URLToken('');
|
||||||
while (whitespace(next())) consume();
|
while (whitespace(next()))
|
||||||
if (eof(next())) return token;
|
consume();
|
||||||
|
if (eof(next()))
|
||||||
|
return token;
|
||||||
while (consume()) {
|
while (consume()) {
|
||||||
if (code === 0x29 || eof()) {
|
if (code === 0x29 || eof()) {
|
||||||
return token;
|
return token;
|
||||||
} else if (whitespace(code)) {
|
} else if (whitespace(code)) {
|
||||||
while (whitespace(next())) consume();
|
while (whitespace(next()))
|
||||||
|
consume();
|
||||||
if (next() === 0x29 || eof(next())) {
|
if (next() === 0x29 || eof(next())) {
|
||||||
consume();
|
consume();
|
||||||
return token;
|
return token;
|
||||||
|
|
@ -379,9 +392,11 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (whitespace(next())) consume();
|
if (whitespace(next()))
|
||||||
|
consume();
|
||||||
let value = parseInt(digits.map(function(x) { return String.fromCharCode(x); }).join(''), 16);
|
let value = parseInt(digits.map(function(x) { return String.fromCharCode(x); }).join(''), 16);
|
||||||
if (value > maximumallowedcodepoint) value = 0xfffd;
|
if (value > maximumallowedcodepoint)
|
||||||
|
value = 0xfffd;
|
||||||
return value;
|
return value;
|
||||||
} else if (eof()) {
|
} else if (eof()) {
|
||||||
return 0xfffd;
|
return 0xfffd;
|
||||||
|
|
@ -391,8 +406,10 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
};
|
};
|
||||||
|
|
||||||
const areAValidEscape = function(c1: number, c2: number) {
|
const areAValidEscape = function(c1: number, c2: number) {
|
||||||
if (c1 !== 0x5c) return false;
|
if (c1 !== 0x5c)
|
||||||
if (newline(c2)) return false;
|
return false;
|
||||||
|
if (newline(c2))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
const startsWithAValidEscape = function() {
|
const startsWithAValidEscape = function() {
|
||||||
|
|
@ -416,11 +433,14 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
|
|
||||||
const wouldStartANumber = function(c1: number, c2: number, c3: number) {
|
const wouldStartANumber = function(c1: number, c2: number, c3: number) {
|
||||||
if (c1 === 0x2b || c1 === 0x2d) {
|
if (c1 === 0x2b || c1 === 0x2d) {
|
||||||
if (digit(c2)) return true;
|
if (digit(c2))
|
||||||
if (c2 === 0x2e && digit(c3)) return true;
|
return true;
|
||||||
|
if (c2 === 0x2e && digit(c3))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
} else if (c1 === 0x2e) {
|
} else if (c1 === 0x2e) {
|
||||||
if (digit(c2)) return true;
|
if (digit(c2))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
} else if (digit(c1)) {
|
} else if (digit(c1)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -519,7 +539,8 @@ export function tokenize(str1: string): CSSTokenInterface[] {
|
||||||
while (!eof(next())) {
|
while (!eof(next())) {
|
||||||
tokens.push(consumeAToken());
|
tokens.push(consumeAToken());
|
||||||
iterationCount++;
|
iterationCount++;
|
||||||
if (iterationCount > str.length * 2) throw new Error("I'm infinite-looping!");
|
if (iterationCount > str.length * 2)
|
||||||
|
throw new Error("I'm infinite-looping!");
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: "../.eslintrc-with-ts-config.js",
|
extends: "../../.eslintrc-with-ts-config.js",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"description": "Playwright Component Testing Helpers",
|
"description": "Playwright Component Testing Helpers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -26,9 +26,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.42.0-next",
|
"playwright-core": "1.43.0-next",
|
||||||
"vite": "^5.0.12",
|
"vite": "^5.0.12",
|
||||||
"playwright": "1.42.0-next"
|
"playwright": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,11 @@ function __pwRender(value) {
|
||||||
if (isJsxComponent(v)) {
|
if (isJsxComponent(v)) {
|
||||||
const component = v;
|
const component = v;
|
||||||
const props = component.props ? __pwRender(component.props) : {};
|
const props = component.props ? __pwRender(component.props) : {};
|
||||||
const {children, ...propsWithoutChildren} = props;
|
const { children, ...propsWithoutChildren } = props;
|
||||||
/** @type {[any, any, any?]} */
|
const createElementArguments = [propsWithoutChildren];
|
||||||
const createElementArguments = [component.type, propsWithoutChildren];
|
if (children)
|
||||||
if(children){
|
|
||||||
createElementArguments.push(children);
|
createElementArguments.push(children);
|
||||||
}
|
return { result: __pwReact.createElement(component.type, ...createElementArguments) };
|
||||||
return { result: __pwReact.createElement(...createElementArguments) };
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,11 @@ function __pwRender(value) {
|
||||||
if (isJsxComponent(v)) {
|
if (isJsxComponent(v)) {
|
||||||
const component = v;
|
const component = v;
|
||||||
const props = component.props ? __pwRender(component.props) : {};
|
const props = component.props ? __pwRender(component.props) : {};
|
||||||
|
const { children, ...propsWithoutChildren } = props;
|
||||||
const {children, ...propsWithoutChildren} = props;
|
const createElementArguments = [propsWithoutChildren];
|
||||||
/** @type {[any, any, any?]} */
|
if (children)
|
||||||
const createElementArguments = [component.type, propsWithoutChildren];
|
|
||||||
if(children){
|
|
||||||
createElementArguments.push(children);
|
createElementArguments.push(children);
|
||||||
}
|
return { result: __pwReact.createElement(component.type, ...createElementArguments) };
|
||||||
return { result: __pwReact.createElement(...createElementArguments) };
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@
|
||||||
|
|
||||||
import { render as __pwSolidRender, createComponent as __pwSolidCreateComponent } from 'solid-js/web';
|
import { render as __pwSolidRender, createComponent as __pwSolidCreateComponent } from 'solid-js/web';
|
||||||
import __pwH from 'solid-js/h';
|
import __pwH from 'solid-js/h';
|
||||||
|
|
||||||
/** @typedef {import('../playwright-ct-core/types/component').JsxComponent} JsxComponent */
|
/** @typedef {import('../playwright-ct-core/types/component').JsxComponent} JsxComponent */
|
||||||
/** @typedef {() => import('solid-js').JSX.Element} FrameworkComponent */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} component
|
* @param {any} component
|
||||||
|
|
@ -32,42 +30,20 @@ function isJsxComponent(component) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} child
|
* @param {any} value
|
||||||
*/
|
*/
|
||||||
function __pwCreateChild(child) {
|
function __pwCreateComponent(value) {
|
||||||
if (Array.isArray(child))
|
return window.__pwTransformObject(value, v => {
|
||||||
return child.map(grandChild => __pwCreateChild(grandChild));
|
if (isJsxComponent(v)) {
|
||||||
if (isJsxComponent(child))
|
const component = v;
|
||||||
return __pwCreateComponent(child);
|
const props = component.props ? __pwCreateComponent(component.props) : {};
|
||||||
return child;
|
if (typeof component.type === 'string') {
|
||||||
}
|
const { children, ...propsWithoutChildren } = props;
|
||||||
|
return { result: __pwH(component.type, propsWithoutChildren, children) };
|
||||||
/**
|
}
|
||||||
* @param {JsxComponent} component
|
return { result: __pwSolidCreateComponent(component.type, props) };
|
||||||
* @returns {any[] | undefined}
|
}
|
||||||
*/
|
|
||||||
function __pwJsxChildArray(component) {
|
|
||||||
if (!component.props.children)
|
|
||||||
return;
|
|
||||||
if (Array.isArray(component.props.children))
|
|
||||||
return component.props.children;
|
|
||||||
return [component.props.children];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {JsxComponent} component
|
|
||||||
*/
|
|
||||||
function __pwCreateComponent(component) {
|
|
||||||
const children = __pwJsxChildArray(component)?.map(child => __pwCreateChild(child)).filter(child => {
|
|
||||||
if (typeof child === 'string')
|
|
||||||
return !!child.trim();
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof component.type === 'string')
|
|
||||||
return __pwH(component.type, component.props, children);
|
|
||||||
|
|
||||||
return __pwSolidCreateComponent(component.type, { ...component.props, children });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const __pwUnmountKey = Symbol('unmountKey');
|
const __pwUnmountKey = Symbol('unmountKey');
|
||||||
|
|
@ -96,6 +72,7 @@ window.playwrightUnmount = async rootElement => {
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
delete rootElement[__pwUnmountKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUpdate = async (rootElement, component) => {
|
window.playwrightUpdate = async (rootElement, component) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ function __pwCreateSlots(slots) {
|
||||||
|
|
||||||
for (const slotName in slots) {
|
for (const slotName in slots) {
|
||||||
const template = document
|
const template = document
|
||||||
.createRange()
|
.createRange()
|
||||||
.createContextualFragment(slots[slotName]);
|
.createContextualFragment(slots[slotName]);
|
||||||
svelteSlots[slotName] = [createSlotFn(template)];
|
svelteSlots[slotName] = [createSlotFn(template)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,7 +55,8 @@ function __pwCreateSlots(slots) {
|
||||||
__pwInsert(target, element, anchor);
|
__pwInsert(target, element, anchor);
|
||||||
},
|
},
|
||||||
d: function destroy(detaching) {
|
d: function destroy(detaching) {
|
||||||
if (detaching) __pwDetach(element);
|
if (detaching)
|
||||||
|
__pwDetach(element);
|
||||||
},
|
},
|
||||||
l: __pwNoop,
|
l: __pwNoop,
|
||||||
};
|
};
|
||||||
|
|
@ -108,6 +109,7 @@ window.playwrightUnmount = async rootElement => {
|
||||||
if (!svelteComponent)
|
if (!svelteComponent)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
svelteComponent.$destroy();
|
svelteComponent.$destroy();
|
||||||
|
delete rootElement[__pwSvelteComponentKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUpdate = async (rootElement, component) => {
|
window.playwrightUpdate = async (rootElement, component) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,9 @@ function __pwCreateSlot(html) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string | string[]} slot
|
||||||
|
*/
|
||||||
function __pwSlotToFunction(slot) {
|
function __pwSlotToFunction(slot) {
|
||||||
if (typeof slot === 'string')
|
if (typeof slot === 'string')
|
||||||
return __pwCreateSlot(slot)();
|
return __pwCreateSlot(slot)();
|
||||||
|
|
@ -175,7 +178,11 @@ function __pwCreateComponent(component) {
|
||||||
return { Component: component.type, props, slots: lastArg, listeners };
|
return { Component: component.type, props, slots: lastArg, listeners };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} slots
|
||||||
|
*/
|
||||||
function __pwWrapFunctions(slots) {
|
function __pwWrapFunctions(slots) {
|
||||||
|
/** @type {import('vue').ComponentInternalInstance['slots']} */
|
||||||
const slotsWithRenderFunctions = {};
|
const slotsWithRenderFunctions = {};
|
||||||
if (!Array.isArray(slots)) {
|
if (!Array.isArray(slots)) {
|
||||||
for (const [key, value] of Object.entries(slots || {}))
|
for (const [key, value] of Object.entries(slots || {}))
|
||||||
|
|
@ -198,25 +205,27 @@ function __pwCreateWrapper(component) {
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function __pwSetDevTools() {
|
||||||
* @returns {any}
|
__pwSetDevtoolsHook({
|
||||||
*/
|
|
||||||
function __pwCreateDevTools() {
|
|
||||||
return {
|
|
||||||
emit(eventType, ...payload) {
|
emit(eventType, ...payload) {
|
||||||
if (eventType === 'component:emit') {
|
if (eventType !== 'component:emit')
|
||||||
const [, componentVM, event, eventArgs] = payload;
|
return;
|
||||||
for (const [wrapper, listeners] of __pwAllListeners) {
|
|
||||||
if (wrapper.component !== componentVM)
|
const [, componentVM, event, eventArgs] = payload;
|
||||||
continue;
|
for (const [wrapper, listeners] of __pwAllListeners) {
|
||||||
const listener = listeners[event];
|
if (wrapper.component !== componentVM)
|
||||||
if (!listener)
|
continue;
|
||||||
return;
|
const listener = listeners[event];
|
||||||
listener(...eventArgs);
|
if (!listener)
|
||||||
}
|
return;
|
||||||
|
listener(...eventArgs);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
on() {},
|
||||||
|
off() {},
|
||||||
|
once() {},
|
||||||
|
appRecords: []
|
||||||
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
const __pwAppKey = Symbol('appKey');
|
const __pwAppKey = Symbol('appKey');
|
||||||
|
|
@ -230,7 +239,7 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
__pwSetDevtoolsHook(__pwCreateDevTools(), {});
|
__pwSetDevTools();
|
||||||
|
|
||||||
for (const hook of window.__pw_hooks_before_mount || [])
|
for (const hook of window.__pw_hooks_before_mount || [])
|
||||||
await hook({ app, hooksConfig });
|
await hook({ app, hooksConfig });
|
||||||
|
|
@ -242,13 +251,16 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUnmount = async rootElement => {
|
window.playwrightUnmount = async rootElement => {
|
||||||
const app = /** @type {import('vue').App} */ (rootElement[__pwAppKey]);
|
/** @type {import('vue').App<Element> | undefined} */
|
||||||
|
const app = rootElement[__pwAppKey];
|
||||||
if (!app)
|
if (!app)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
app.unmount();
|
app.unmount();
|
||||||
|
delete rootElement[__pwAppKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUpdate = async (rootElement, component) => {
|
window.playwrightUpdate = async (rootElement, component) => {
|
||||||
|
/** @type {import('vue').VNode | undefined} */
|
||||||
const wrapper = rootElement[__pwWrapperKey];
|
const wrapper = rootElement[__pwWrapperKey];
|
||||||
if (!wrapper)
|
if (!wrapper)
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next",
|
"@playwright/experimental-ct-core": "1.43.0-next",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,7 @@ window.playwrightUnmount = async rootElement => {
|
||||||
throw new Error('Component was not mounted');
|
throw new Error('Component was not mounted');
|
||||||
component.$destroy();
|
component.$destroy();
|
||||||
component.$el.remove();
|
component.$el.remove();
|
||||||
|
delete rootElement[instanceKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
window.playwrightUpdate = async (element, options) => {
|
window.playwrightUpdate = async (element, options) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-firefox",
|
"name": "playwright-firefox",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-webkit",
|
"name": "playwright-webkit",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,5 @@
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: '../.eslintrc.js',
|
extends: '../../.eslintrc-with-ts-config.js',
|
||||||
parser: "@typescript-eslint/parser",
|
|
||||||
plugins: ["@typescript-eslint", "notice"],
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 9,
|
|
||||||
sourceType: "module",
|
|
||||||
project: path.join(__dirname, '..', '..', 'tsconfig.json'),
|
|
||||||
},
|
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-floating-promises': 'error',
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright",
|
"name": "playwright",
|
||||||
"version": "1.42.0-next",
|
"version": "1.43.0-next",
|
||||||
"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.42.0-next"
|
"playwright-core": "1.43.0-next"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "2.3.2"
|
"fsevents": "2.3.2"
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export function matcherHint(state: ExpectMatcherContext, locator: Locator | unde
|
||||||
if (timeout)
|
if (timeout)
|
||||||
header = colors.red(`Timed out ${timeout}ms waiting for `) + header;
|
header = colors.red(`Timed out ${timeout}ms waiting for `) + header;
|
||||||
if (locator)
|
if (locator)
|
||||||
header += `Locator: ${locator}\n`;
|
header += `Locator: ${String(locator)}\n`;
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ export function toBeAttached(
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { attached?: boolean, timeout?: number },
|
options?: { attached?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
const attached = !options || options.attached === undefined || options.attached === true;
|
const attached = !options || options.attached === undefined || options.attached;
|
||||||
const expected = attached ? 'attached' : 'detached';
|
const expected = attached ? 'attached' : 'detached';
|
||||||
const unexpected = attached ? 'detached' : 'attached';
|
const unexpected = attached ? 'detached' : 'attached';
|
||||||
const arg = attached ? '' : '{ attached: false }';
|
const arg = attached ? '' : '{ attached: false }';
|
||||||
|
|
@ -54,7 +54,7 @@ export function toBeChecked(
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { checked?: boolean, timeout?: number },
|
options?: { checked?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
const checked = !options || options.checked === undefined || options.checked === true;
|
const checked = !options || options.checked === undefined || options.checked;
|
||||||
const expected = checked ? 'checked' : 'unchecked';
|
const expected = checked ? 'checked' : 'unchecked';
|
||||||
const unexpected = checked ? 'unchecked' : 'checked';
|
const unexpected = checked ? 'unchecked' : 'checked';
|
||||||
const arg = checked ? '' : '{ checked: false }';
|
const arg = checked ? '' : '{ checked: false }';
|
||||||
|
|
@ -78,7 +78,7 @@ export function toBeEditable(
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { editable?: boolean, timeout?: number },
|
options?: { editable?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
const editable = !options || options.editable === undefined || options.editable === true;
|
const editable = !options || options.editable === undefined || options.editable;
|
||||||
const expected = editable ? 'editable' : 'readOnly';
|
const expected = editable ? 'editable' : 'readOnly';
|
||||||
const unexpected = editable ? 'readOnly' : 'editable';
|
const unexpected = editable ? 'readOnly' : 'editable';
|
||||||
const arg = editable ? '' : '{ editable: false }';
|
const arg = editable ? '' : '{ editable: false }';
|
||||||
|
|
@ -102,7 +102,7 @@ export function toBeEnabled(
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { enabled?: boolean, timeout?: number },
|
options?: { enabled?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
const enabled = !options || options.enabled === undefined || options.enabled === true;
|
const enabled = !options || options.enabled === undefined || options.enabled;
|
||||||
const expected = enabled ? 'enabled' : 'disabled';
|
const expected = enabled ? 'enabled' : 'disabled';
|
||||||
const unexpected = enabled ? 'disabled' : 'enabled';
|
const unexpected = enabled ? 'disabled' : 'enabled';
|
||||||
const arg = enabled ? '' : '{ enabled: false }';
|
const arg = enabled ? '' : '{ enabled: false }';
|
||||||
|
|
@ -136,7 +136,7 @@ export function toBeVisible(
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { visible?: boolean, timeout?: number },
|
options?: { visible?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
const visible = !options || options.visible === undefined || options.visible === true;
|
const visible = !options || options.visible === undefined || options.visible;
|
||||||
const expected = visible ? 'visible' : 'hidden';
|
const expected = visible ? 'visible' : 'hidden';
|
||||||
const unexpected = visible ? 'hidden' : 'visible';
|
const unexpected = visible ? 'hidden' : 'visible';
|
||||||
const arg = visible ? '' : '{ visible: false }';
|
const arg = visible ? '' : '{ visible: false }';
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export async function runTestServer() {
|
||||||
onConnection(request: http.IncomingMessage, url: URL, ws: WebSocket, id: string) {
|
onConnection(request: http.IncomingMessage, url: URL, ws: WebSocket, id: string) {
|
||||||
const dispatcher = new Dispatcher(ws);
|
const dispatcher = new Dispatcher(ws);
|
||||||
ws.on('message', async message => {
|
ws.on('message', async message => {
|
||||||
const { id, method, params } = JSON.parse(message.toString());
|
const { id, method, params } = JSON.parse(String(message));
|
||||||
try {
|
try {
|
||||||
const result = await (dispatcher as any)[method](params);
|
const result = await (dispatcher as any)[method](params);
|
||||||
ws.send(JSON.stringify({ id, result }));
|
ws.send(JSON.stringify({ id, result }));
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,8 @@ export function addSuffixToFilePath(filePath: string, suffix: string, customExte
|
||||||
*/
|
*/
|
||||||
export function getContainedPath(parentPath: string, subPath: string = ''): string | null {
|
export function getContainedPath(parentPath: string, subPath: string = ''): string | null {
|
||||||
const resolvedPath = path.resolve(parentPath, subPath);
|
const resolvedPath = path.resolve(parentPath, subPath);
|
||||||
if (resolvedPath === parentPath || resolvedPath.startsWith(parentPath + path.sep)) return resolvedPath;
|
if (resolvedPath === parentPath || resolvedPath.startsWith(parentPath + path.sep))
|
||||||
|
return resolvedPath;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ const callbacks = new Map<number, { resolve: (arg: any) => void, reject: (arg: E
|
||||||
|
|
||||||
export async function connect(options: { onEvent: (method: string, params?: any) => void, onClose: () => void }): Promise<(method: string, params?: any) => Promise<any>> {
|
export async function connect(options: { onEvent: (method: string, params?: any) => void, onClose: () => void }): Promise<(method: string, params?: any) => Promise<any>> {
|
||||||
const guid = new URLSearchParams(window.location.search).get('ws');
|
const guid = new URLSearchParams(window.location.search).get('ws');
|
||||||
const ws = new WebSocket(`${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.hostname}:${window.location.port}/${guid}`);
|
const wsURL = new URL(`../${guid}`, window.location.toString());
|
||||||
|
wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:');
|
||||||
|
const ws = new WebSocket(wsURL);
|
||||||
await new Promise(f => ws.addEventListener('open', f));
|
await new Promise(f => ws.addEventListener('open', f));
|
||||||
ws.addEventListener('close', options.onClose);
|
ws.addEventListener('close', options.onClose);
|
||||||
ws.addEventListener('message', event => {
|
ws.addEventListener('message', event => {
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-floating-promises': 'error',
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
|
"@typescript-eslint/no-unnecessary-boolean-literal-compare": 2,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
type DefaultChildrenProps = {
|
import type { PropsWithChildren } from 'react';
|
||||||
children?: any;
|
|
||||||
}
|
type DefaultChildrenProps = PropsWithChildren<{}>;
|
||||||
|
|
||||||
export default function CheckChildrenProp(props: DefaultChildrenProps) {
|
export default function CheckChildrenProp(props: DefaultChildrenProps) {
|
||||||
const content = 'children' in props ? props.children : 'No Children';
|
return <>{'children' in props ? props.children : 'No Children'}</>
|
||||||
return <div>
|
|
||||||
<h1>Welcome!</h1>
|
|
||||||
<main>
|
|
||||||
{content}
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
Thanks for visiting.
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ test('render number as child', async ({ mount }) => {
|
||||||
await expect(component).toContainText('1337');
|
await expect(component).toContainText('1337');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('render without children', async ({ mount }) => {
|
test('absence of children when children prop is not provided', async ({ mount }) => {
|
||||||
const component = await mount(<CheckChildrenProp />);
|
const component = await mount(<CheckChildrenProp />);
|
||||||
await expect(component).toContainText('No Children');
|
await expect(component).toContainText('No Children');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,9 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
type DefaultChildrenProps = {
|
import type { PropsWithChildren } from 'react';
|
||||||
children?: any;
|
|
||||||
}
|
type DefaultChildrenProps = PropsWithChildren<{}>;
|
||||||
|
|
||||||
export default function CheckChildrenProp(props: DefaultChildrenProps) {
|
export default function CheckChildrenProp(props: DefaultChildrenProps) {
|
||||||
const content = 'children' in props ? props.children : 'No Children';
|
return <>{'children' in props ? props.children : 'No Children'}</>
|
||||||
return <div>
|
|
||||||
<h1>Welcome!</h1>
|
|
||||||
<main>
|
|
||||||
{content}
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
Thanks for visiting.
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ test('render number as child', async ({ mount }) => {
|
||||||
await expect(component).toContainText('1337');
|
await expect(component).toContainText('1337');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('render without children', async ({ mount }) => {
|
test('absence of children when children prop is not provided', async ({ mount }) => {
|
||||||
const component = await mount(<CheckChildrenProp />);
|
const component = await mount(<CheckChildrenProp />);
|
||||||
await expect(component).toContainText('No Children');
|
await expect(component).toContainText('No Children');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,9 @@ test('unmount a multi root component', async ({ page, mount }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { type ParentProps } from 'solid-js';
|
||||||
|
|
||||||
|
type DefaultChildrenProps = ParentProps<{}>;
|
||||||
|
|
||||||
|
export default function CheckChildrenProp(props: DefaultChildrenProps) {
|
||||||
|
return <>{'children' in props ? props.children : 'No Children'}</>
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-solid';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import DefaultChildren from '@/components/DefaultChildren';
|
import DefaultChildren from '@/components/DefaultChildren';
|
||||||
import MultipleChildren from '@/components/MultipleChildren';
|
import MultipleChildren from '@/components/MultipleChildren';
|
||||||
|
import CheckChildrenProp from '@/components/CheckChildrenProp'
|
||||||
|
|
||||||
test('render a default child', async ({ mount }) => {
|
test('render a default child', async ({ mount }) => {
|
||||||
const component = await mount(
|
const component = await mount(
|
||||||
|
|
@ -58,3 +59,8 @@ test('render number as child', async ({ mount }) => {
|
||||||
const component = await mount(<DefaultChildren>{1337}</DefaultChildren>);
|
const component = await mount(<DefaultChildren>{1337}</DefaultChildren>);
|
||||||
await expect(component).toContainText('1337');
|
await expect(component).toContainText('1337');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('absence of children when children prop is not provided', async ({ mount }) => {
|
||||||
|
const component = await mount(<CheckChildrenProp />);
|
||||||
|
await expect(component).toContainText('No Children');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,9 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,13 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(Button, {
|
||||||
|
props: {
|
||||||
|
title: 'Submit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,13 @@ test('unmount a multi root component', async ({ page, mount }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(Button, {
|
||||||
|
props: {
|
||||||
|
title: 'Submit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,14 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(Button, {
|
||||||
|
props: {
|
||||||
|
title: 'Submit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,9 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,13 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(Button, {
|
||||||
|
props: {
|
||||||
|
title: 'Submit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import MultiRoot from '@/components/MultiRoot.vue';
|
import MultiRoot from '@/components/MultiRoot.vue';
|
||||||
|
import Button from '@/components/Button.vue';
|
||||||
|
|
||||||
test('unmount a multi root component', async ({ mount, page }) => {
|
test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
const component = await mount(<MultiRoot />);
|
const component = await mount(<MultiRoot />);
|
||||||
|
|
@ -9,3 +10,9 @@ test('unmount a multi root component', async ({ mount, page }) => {
|
||||||
await expect(page.locator('#root')).not.toContainText('root 1');
|
await expect(page.locator('#root')).not.toContainText('root 1');
|
||||||
await expect(page.locator('#root')).not.toContainText('root 2');
|
await expect(page.locator('#root')).not.toContainText('root 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,13 @@ test('unmount', async ({ page, mount }) => {
|
||||||
await component.unmount();
|
await component.unmount();
|
||||||
await expect(page.locator('#root')).not.toContainText('Submit');
|
await expect(page.locator('#root')).not.toContainText('Submit');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(Button, {
|
||||||
|
props: {
|
||||||
|
title: 'Submit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,9 @@ test('unmount', async ({ page, mount }) => {
|
||||||
await component.unmount();
|
await component.unmount();
|
||||||
await expect(page.locator('#root')).not.toContainText('Submit');
|
await expect(page.locator('#root')).not.toContainText('Submit');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unmount twice throws an error', async ({ mount }) => {
|
||||||
|
const component = await mount(<Button title="Submit" />);
|
||||||
|
await component.unmount();
|
||||||
|
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,39 @@ it('should create new context @smoke', async function({ browser }) {
|
||||||
expect(browser).toBe(context.browser());
|
expect(browser).toBe(context.browser());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to click across browser contexts', async function({ browser }) {
|
||||||
|
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29096' });
|
||||||
|
expect(browser.contexts().length).toBe(0);
|
||||||
|
|
||||||
|
const createPage = async () => {
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.setContent(`<button>Click me</button>`);
|
||||||
|
await page.locator('button').evaluate(button => {
|
||||||
|
window['clicks'] = 0;
|
||||||
|
button.addEventListener('click', () => ++window['clicks'], false);
|
||||||
|
});
|
||||||
|
return page;
|
||||||
|
};
|
||||||
|
|
||||||
|
const clickInPage = async (page, count) => {
|
||||||
|
for (let i = 0; i < count; ++i)
|
||||||
|
await page.locator('button').click();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getClicks = async page => page.evaluate(() => window['clicks']);
|
||||||
|
|
||||||
|
const page1 = await createPage();
|
||||||
|
const page2 = await createPage();
|
||||||
|
|
||||||
|
const CLICK_COUNT = 20;
|
||||||
|
await Promise.all([
|
||||||
|
clickInPage(page1, CLICK_COUNT),
|
||||||
|
clickInPage(page2, CLICK_COUNT),
|
||||||
|
]);
|
||||||
|
expect(await getClicks(page1)).toBe(CLICK_COUNT);
|
||||||
|
expect(await getClicks(page2)).toBe(CLICK_COUNT);
|
||||||
|
});
|
||||||
|
|
||||||
it('window.open should use parent tab context', async function({ browser, server }) {
|
it('window.open should use parent tab context', async function({ browser, server }) {
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,10 @@ it('should work @smoke', async ({ page, browserName }) => {
|
||||||
it('should emit same log twice', async ({ page }) => {
|
it('should emit same log twice', async ({ page }) => {
|
||||||
const messages = [];
|
const messages = [];
|
||||||
page.on('console', m => messages.push(m.text()));
|
page.on('console', m => messages.push(m.text()));
|
||||||
await page.evaluate(() => { for (let i = 0; i < 2; ++i) console.log('hello'); });
|
await page.evaluate(() => {
|
||||||
|
for (let i = 0; i < 2; ++i)
|
||||||
|
console.log('hello');
|
||||||
|
});
|
||||||
expect(messages).toEqual(['hello', 'hello']);
|
expect(messages).toEqual(['hello', 'hello']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -723,7 +723,7 @@ it.describe('page screenshot animations', () => {
|
||||||
el.addEventListener('transitionend', () => {
|
el.addEventListener('transitionend', () => {
|
||||||
const time = Date.now();
|
const time = Date.now();
|
||||||
// Block main thread for 200ms, emulating heavy layout.
|
// Block main thread for 200ms, emulating heavy layout.
|
||||||
while (Date.now() - time < 200) ;
|
while (Date.now() - time < 200) {}
|
||||||
const h1 = document.createElement('h1');
|
const h1 = document.createElement('h1');
|
||||||
h1.textContent = 'woof-woof';
|
h1.textContent = 'woof-woof';
|
||||||
document.body.append(h1);
|
document.body.append(h1);
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,15 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": "1.41.0-beta-1705101589000"
|
"@playwright/test": "1.42.0-beta-1708994059000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@playwright/test": {
|
"node_modules/@playwright/test": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-tpaEm+ih0PhJdk6yrRtk40I9ahErhGYZT2lR65ZZ6Il7tMnUgzxF5OOw3XLGJ59T29nMyI1+hKGqQnf8nUKkQw==",
|
"integrity": "sha512-dfCvXGLsNRTOIRXyU7Cx8EdmMJxpHP3Dg2yD+ACM4GhpcSTJqLD0kwggZY2ziDJNG1sNJ1zN/aDgRqv4G3NREQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.41.0-beta-1705101589000"
|
"playwright": "1.42.0-beta-1708994059000"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -36,11 +36,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright": {
|
"node_modules/playwright": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-3mMpZXmkw+fGIb+wBpvDZ4OEm7L1QYptgJgTdP8/OEitYjV5Q05MRZWbgelF/9ameoRpMz7rbkZTWUh/1UtrIw==",
|
"integrity": "sha512-+lMRsLfaLx/Okb3qH9r8eUfDBQ7Vq0eTLehxG9plLorSBQnU1b9kQnmchV3jl2hjm9Oh7vNf/No+vgsRBuj7/Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.41.0-beta-1705101589000"
|
"playwright-core": "1.42.0-beta-1708994059000"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -53,9 +53,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright-core": {
|
"node_modules/playwright-core": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-w3aDw2Kp/ZwAUSqLZdmd+mq6khl3ufb2csM51b85r9t8S4m2JYoz1WHFNGNHqFWHBXSrjSBXzFLNgKUmwizRuA==",
|
"integrity": "sha512-mdXcpctceoX0aHouE+ZglhB7JnLO1NtQgTF8MBgL/Wsa3r6jRI8DESCVTmbcazr8QGs9MT9wTKSx8Y70zYkaxw==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
},
|
},
|
||||||
|
|
@ -66,11 +66,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": {
|
"@playwright/test": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-tpaEm+ih0PhJdk6yrRtk40I9ahErhGYZT2lR65ZZ6Il7tMnUgzxF5OOw3XLGJ59T29nMyI1+hKGqQnf8nUKkQw==",
|
"integrity": "sha512-dfCvXGLsNRTOIRXyU7Cx8EdmMJxpHP3Dg2yD+ACM4GhpcSTJqLD0kwggZY2ziDJNG1sNJ1zN/aDgRqv4G3NREQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"playwright": "1.41.0-beta-1705101589000"
|
"playwright": "1.42.0-beta-1708994059000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
|
|
@ -80,18 +80,18 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-3mMpZXmkw+fGIb+wBpvDZ4OEm7L1QYptgJgTdP8/OEitYjV5Q05MRZWbgelF/9ameoRpMz7rbkZTWUh/1UtrIw==",
|
"integrity": "sha512-+lMRsLfaLx/Okb3qH9r8eUfDBQ7Vq0eTLehxG9plLorSBQnU1b9kQnmchV3jl2hjm9Oh7vNf/No+vgsRBuj7/Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "2.3.2",
|
"fsevents": "2.3.2",
|
||||||
"playwright-core": "1.41.0-beta-1705101589000"
|
"playwright-core": "1.42.0-beta-1708994059000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"playwright-core": {
|
"playwright-core": {
|
||||||
"version": "1.41.0-beta-1705101589000",
|
"version": "1.42.0-beta-1708994059000",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0-beta-1705101589000.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0-beta-1708994059000.tgz",
|
||||||
"integrity": "sha512-w3aDw2Kp/ZwAUSqLZdmd+mq6khl3ufb2csM51b85r9t8S4m2JYoz1WHFNGNHqFWHBXSrjSBXzFLNgKUmwizRuA=="
|
"integrity": "sha512-mdXcpctceoX0aHouE+ZglhB7JnLO1NtQgTF8MBgL/Wsa3r6jRI8DESCVTmbcazr8QGs9MT9wTKSx8Y70zYkaxw=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": "1.41.0-beta-1705101589000"
|
"@playwright/test": "1.42.0-beta-1708994059000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,8 @@ test(`should support self signed certificate`, async ({ runInlineTest, httpsServ
|
||||||
test('should send Accept header', async ({ runInlineTest, server }) => {
|
test('should send Accept header', async ({ runInlineTest, server }) => {
|
||||||
let acceptHeader: string | undefined | null = null;
|
let acceptHeader: string | undefined | null = null;
|
||||||
server.setRoute('/hello', (req, res) => {
|
server.setRoute('/hello', (req, res) => {
|
||||||
if (acceptHeader === null) acceptHeader = req.headers.accept;
|
if (acceptHeader === null)
|
||||||
|
acceptHeader = req.headers.accept;
|
||||||
res.end('<html><body>hello</body></html>');
|
res.end('<html><body>hello</body></html>');
|
||||||
});
|
});
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,5 @@
|
||||||
"include": ["packages"],
|
"include": ["packages"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"packages/*/lib",
|
"packages/*/lib",
|
||||||
"packages/playwright-ct-react",
|
|
||||||
"packages/playwright-ct-react17",
|
|
||||||
"packages/playwright-ct-solid",
|
|
||||||
"packages/playwright-ct-svelte",
|
|
||||||
"packages/playwright-ct-vue",
|
|
||||||
"packages/playwright-ct-vue2"
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,10 @@ class JSLintingService extends LintingService {
|
||||||
* @returns {Promise<LintResult[]>}
|
* @returns {Promise<LintResult[]>}
|
||||||
*/
|
*/
|
||||||
async lint(snippets) {
|
async lint(snippets) {
|
||||||
return Promise.all(snippets.map(async snippet => this._lintSnippet(snippet)));
|
const result = [];
|
||||||
|
for (let i = 0; i < snippets.length; ++i)
|
||||||
|
result.push(await this._lintSnippet(snippets[i]));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue