Merge branch 'main' into sharding-algorithm
This commit is contained in:
commit
ef2d35f34a
|
|
@ -60,7 +60,7 @@ jobs:
|
||||||
git checkout -b "$BRANCH_NAME"
|
git checkout -b "$BRANCH_NAME"
|
||||||
git push origin $BRANCH_NAME
|
git push origin $BRANCH_NAME
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
|
|
||||||
2
.github/workflows/create_test_report.yml
vendored
2
.github/workflows/create_test_report.yml
vendored
|
|
@ -58,7 +58,7 @@ jobs:
|
||||||
path: '.'
|
path: '.'
|
||||||
|
|
||||||
- name: Comment on PR
|
- name: Comment on PR
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,13 @@ jobs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.repository == 'microsoft/playwright'
|
if: github.repository == 'microsoft/playwright'
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
- name: Create GitHub issue
|
- name: Create GitHub issue
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
const currentPlaywrightVersion = require('./package.json').version.match(/\d+\.\d+/)[0];
|
||||||
const { data } = await github.rest.git.getCommit({
|
const { data } = await github.rest.git.getCommit({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
|
|
@ -27,10 +29,10 @@ jobs:
|
||||||
});
|
});
|
||||||
const commitHeader = data.message.split('\n')[0];
|
const commitHeader = data.message.split('\n')[0];
|
||||||
|
|
||||||
const title = '[Ports]: Backport client side changes';
|
const title = '[Ports]: Backport client side changes for ' + currentPlaywrightVersion;
|
||||||
for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) {
|
for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) {
|
||||||
const { data: issuesData } = await github.rest.search.issuesAndPullRequests({
|
const { data: issuesData } = await github.rest.search.issuesAndPullRequests({
|
||||||
q: `is:issue is:open repo:microsoft/${repo} in:title "${title}"`
|
q: `is:issue is:open repo:microsoft/${repo} in:title "${title}" author:playwrightmachine"`
|
||||||
})
|
})
|
||||||
let issueNumber = null;
|
let issueNumber = null;
|
||||||
let issueBody = '';
|
let issueBody = '';
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ jobs:
|
||||||
git commit -m "feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}"
|
git commit -m "feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}"
|
||||||
git push origin $BRANCH_NAME
|
git push origin $BRANCH_NAME
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
|
|
||||||
2
.github/workflows/roll_driver_nodejs.yml
vendored
2
.github/workflows/roll_driver_nodejs.yml
vendored
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
git push origin $BRANCH_NAME
|
git push origin $BRANCH_NAME
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }}
|
if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }}
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,12 @@ Prevents automatic playwright driver installation on attach. Assumes that the dr
|
||||||
Optional device serial number to launch the browser on. If not specified, it will
|
Optional device serial number to launch the browser on. If not specified, it will
|
||||||
throw if multiple devices are connected.
|
throw if multiple devices are connected.
|
||||||
|
|
||||||
|
### option: Android.launchServer.host
|
||||||
|
* since: v1.45
|
||||||
|
- `host` <[string]>
|
||||||
|
|
||||||
|
Host to use for the web socket. It is optional and if it is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available, or the unspecified IPv4 address (0.0.0.0) otherwise. Consider hardening it with picking a specific interface.
|
||||||
|
|
||||||
### option: Android.launchServer.port
|
### option: Android.launchServer.port
|
||||||
* since: v1.28
|
* since: v1.28
|
||||||
- `port` <[int]>
|
- `port` <[int]>
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,5 @@ Browser websocket url.
|
||||||
|
|
||||||
Browser websocket endpoint which can be used as an argument to [`method: BrowserType.connect`] to establish connection
|
Browser websocket endpoint which can be used as an argument to [`method: BrowserType.connect`] to establish connection
|
||||||
to the browser.
|
to the browser.
|
||||||
|
|
||||||
|
Note that if the listen `host` option in `launchServer` options is not specified, localhost will be output anyway, even if the actual listening address is an unspecified address.
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,12 @@ const { chromium } = require('playwright'); // Or 'webkit' or 'firefox'.
|
||||||
### option: BrowserType.launchServer.logger = %%-browser-option-logger-%%
|
### option: BrowserType.launchServer.logger = %%-browser-option-logger-%%
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
|
|
||||||
|
### option: BrowserType.launchServer.host
|
||||||
|
* since: v1.45
|
||||||
|
- `host` <[string]>
|
||||||
|
|
||||||
|
Host to use for the web socket. It is optional and if it is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available, or the unspecified IPv4 address (0.0.0.0) otherwise. Consider hardening it with picking a specific interface.
|
||||||
|
|
||||||
### option: BrowserType.launchServer.port
|
### option: BrowserType.launchServer.port
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
- `port` <[int]>
|
- `port` <[int]>
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,6 @@ When you have finished interacting with the page, press the **record** button to
|
||||||
|
|
||||||
Use the **clear** button to clear the code to start recording again. Once finished close the Playwright inspector window or stop the terminal command.
|
Use the **clear** button to clear the code to start recording again. Once finished close the Playwright inspector window or stop the terminal command.
|
||||||
|
|
||||||
To learn more about generating tests check out or detailed guide on [Codegen](./codegen.md).
|
|
||||||
|
|
||||||
### Generating locators
|
### Generating locators
|
||||||
You can generate [locators](/locators.md) with the test generator.
|
You can generate [locators](/locators.md) with the test generator.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ export default defineConfig({
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[RegExp]|[Array]<[RegExp]>>
|
- type: ?<[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only run tests with "cart" in the title. Also available in the [command line](../test-cli.md) with the `-g` option. The regular expression will be tested against the string that consists of the test file name, `test.describe` name (if any) and the test name divided by spaces, e.g. `my-test.spec.ts my-suite my-test`.
|
Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only run tests with "cart" in the title. Also available in the [command line](../test-cli.md) with the `-g` option. The regular expression will be tested against the string that consists of the project name, the test file name, the `test.describe` name (if any), the test name and the test tags divided by spaces, e.g. `chromium my-test.spec.ts my-suite my-test`.
|
||||||
|
|
||||||
`grep` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
`grep` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -559,7 +559,7 @@ Whether to record trace for each test. Defaults to `'off'`.
|
||||||
* `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
* `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
||||||
* `'on-all-retries'`: Record trace only when retrying a test.
|
* `'on-all-retries'`: Record trace only when retrying a test.
|
||||||
* `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
|
* `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
|
||||||
* `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retires. When test run passes, remove the recorded trace.
|
* `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retries. When test run passes, remove the recorded trace.
|
||||||
|
|
||||||
For more control, pass an object that specifies `mode` and trace features to enable.
|
For more control, pass an object that specifies `mode` and trace features to enable.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ You can configure entire test project to concurrently run all tests in all files
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[RegExp]|[Array]<[RegExp]>>
|
- type: ?<[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only run tests with "cart" in the title. Also available globally and in the [command line](../test-cli.md) with the `-g` option. The regular expression will be tested against the string that consists of the test file name, `test.describe` name (if any) and the test name divided by spaces, e.g. `my-test.spec.ts my-suite my-test`.
|
Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only run tests with "cart" in the title. Also available globally and in the [command line](../test-cli.md) with the `-g` option. The regular expression will be tested against the string that consists of the project name, the test file name, the `test.describe` name (if any), the test name and the test tags divided by spaces, e.g. `chromium my-test.spec.ts my-suite my-test`.
|
||||||
|
|
||||||
`grep` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
`grep` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ Complete set of Playwright Test options is available in the [configuration file]
|
||||||
| `--reporter <reporter>` | Choose a reporter: minimalist `dot`, concise `line` or detailed `list`. See [reporters](./test-reporters.md) for more information. You can also pass a path to a [custom reporter](./test-reporters.md#custom-reporters) file. |
|
| `--reporter <reporter>` | Choose a reporter: minimalist `dot`, concise `line` or detailed `list`. See [reporters](./test-reporters.md) for more information. You can also pass a path to a [custom reporter](./test-reporters.md#custom-reporters) file. |
|
||||||
| `--retries <number>` | The maximum number of [retries](./test-retries.md#retries) for flaky tests, defaults to zero (no retries). |
|
| `--retries <number>` | The maximum number of [retries](./test-retries.md#retries) for flaky tests, defaults to zero (no retries). |
|
||||||
| `--shard <shard>` | [Shard](./test-parallel.md#shard-tests-between-multiple-machines) tests and execute only selected shard, specified in the form `current/all`, 1-based, for example `3/5`.|
|
| `--shard <shard>` | [Shard](./test-parallel.md#shard-tests-between-multiple-machines) tests and execute only selected shard, specified in the form `current/all`, 1-based, for example `3/5`.|
|
||||||
| `--tag <tag>` | Only run tests with a tag matching this tag expression. Learn more about [tagging](./test-annotations.md#tag-tests). |
|
|
||||||
| `--timeout <number>` | Maximum timeout in milliseconds for each test, defaults to 30 seconds. Learn more about [various timeouts](./test-timeouts.md).|
|
| `--timeout <number>` | Maximum timeout in milliseconds for each test, defaults to 30 seconds. Learn more about [various timeouts](./test-timeouts.md).|
|
||||||
| `--trace <mode>` | Force tracing mode, can be `on`, `off`, `on-first-retry`, `on-all-retries`, `retain-on-failure` |
|
| `--trace <mode>` | Force tracing mode, can be `on`, `off`, `on-first-retry`, `on-all-retries`, `retain-on-failure` |
|
||||||
| `--update-snapshots` or `-u` | Whether to update [snapshots](./test-snapshots.md) with actual results instead of comparing them. Use this when snapshot expectations have changed.|
|
| `--update-snapshots` or `-u` | Whether to update [snapshots](./test-snapshots.md) with actual results instead of comparing them. Use this when snapshot expectations have changed.|
|
||||||
|
|
|
||||||
|
|
@ -926,9 +926,9 @@ export default defineConfig<MyOptions>({
|
||||||
Each fixture has a setup and teardown phase separated by the `await use()` call in the fixture. Setup is executed before the fixture is used by the test/hook, and teardown is executed when the fixture will not be used by the test/hook anymore.
|
Each fixture has a setup and teardown phase separated by the `await use()` call in the fixture. Setup is executed before the fixture is used by the test/hook, and teardown is executed when the fixture will not be used by the test/hook anymore.
|
||||||
|
|
||||||
Fixtures follow these rules to determine the execution order:
|
Fixtures follow these rules to determine the execution order:
|
||||||
* When fixture A depends on fixture B: B is always set up before A and teared down after A.
|
* When fixture A depends on fixture B: B is always set up before A and torn down after A.
|
||||||
* Non-automatic fixtures are executed lazily, only when the test/hook needs them.
|
* Non-automatic fixtures are executed lazily, only when the test/hook needs them.
|
||||||
* Test-scoped fixtures are teared down after each test, while worker-scoped fixtures are only teared down when the worker process executing tests is shutdown.
|
* Test-scoped fixtures are torn down after each test, while worker-scoped fixtures are only torn down when the worker process executing tests is shutdown.
|
||||||
|
|
||||||
Consider the following example:
|
Consider the following example:
|
||||||
|
|
||||||
|
|
@ -1036,8 +1036,8 @@ Normally, if all tests pass and no errors are thrown, the order of execution is
|
||||||
* `beforeEach` runs.
|
* `beforeEach` runs.
|
||||||
* `first test` runs.
|
* `first test` runs.
|
||||||
* `afterEach` runs.
|
* `afterEach` runs.
|
||||||
* `page` teardown because it is a test-scoped fixture and should be teared down after the test finishes.
|
* `page` teardown because it is a test-scoped fixture and should be torn down after the test finishes.
|
||||||
* `autoTestFixture` teardown because it is a test-scoped fixture and should be teared down after the test finishes.
|
* `autoTestFixture` teardown because it is a test-scoped fixture and should be torn down after the test finishes.
|
||||||
* `second test` section:
|
* `second test` section:
|
||||||
* `autoTestFixture` setup because automatic test fixtures are always set up before test and `beforeEach` hooks.
|
* `autoTestFixture` setup because automatic test fixtures are always set up before test and `beforeEach` hooks.
|
||||||
* `page` setup because it is required in `beforeEach` hook.
|
* `page` setup because it is required in `beforeEach` hook.
|
||||||
|
|
@ -1046,20 +1046,20 @@ Normally, if all tests pass and no errors are thrown, the order of execution is
|
||||||
* `testFixture` setup because it is required by the `second test`.
|
* `testFixture` setup because it is required by the `second test`.
|
||||||
* `second test` runs.
|
* `second test` runs.
|
||||||
* `afterEach` runs.
|
* `afterEach` runs.
|
||||||
* `testFixture` teardown because it is a test-scoped fixture and should be teared down after the test finishes.
|
* `testFixture` teardown because it is a test-scoped fixture and should be torn down after the test finishes.
|
||||||
* `page` teardown because it is a test-scoped fixture and should be teared down after the test finishes.
|
* `page` teardown because it is a test-scoped fixture and should be torn down after the test finishes.
|
||||||
* `autoTestFixture` teardown because it is a test-scoped fixture and should be teared down after the test finishes.
|
* `autoTestFixture` teardown because it is a test-scoped fixture and should be torn down after the test finishes.
|
||||||
* `afterAll` and worker teardown section:
|
* `afterAll` and worker teardown section:
|
||||||
* `afterAll` runs.
|
* `afterAll` runs.
|
||||||
* `workerFixture` teardown because it is a workers-scoped fixture and should be teared down once at the end.
|
* `workerFixture` teardown because it is a workers-scoped fixture and should be torn down once at the end.
|
||||||
* `autoWorkerFixture` teardown because it is a workers-scoped fixture and should be teared down once at the end.
|
* `autoWorkerFixture` teardown because it is a workers-scoped fixture and should be torn down once at the end.
|
||||||
* `browser` teardown because it is a workers-scoped fixture and should be teared down once at the end.
|
* `browser` teardown because it is a workers-scoped fixture and should be torn down once at the end.
|
||||||
|
|
||||||
A few observations:
|
A few observations:
|
||||||
* `page` and `autoTestFixture` are set up and teared down for each test, as test-scoped fixtures.
|
* `page` and `autoTestFixture` are set up and torn down for each test, as test-scoped fixtures.
|
||||||
* `unusedFixture` is never set up because it is not used by any tests/hooks.
|
* `unusedFixture` is never set up because it is not used by any tests/hooks.
|
||||||
* `testFixture` depends on `workerFixture` and triggers its setup.
|
* `testFixture` depends on `workerFixture` and triggers its setup.
|
||||||
* `workerFixture` is lazily set up before the second test, but teared down once during worker shutdown, as a worker-scoped fixture.
|
* `workerFixture` is lazily set up before the second test, but torn down once during worker shutdown, as a worker-scoped fixture.
|
||||||
* `autoWorkerFixture` is set up for `beforeAll` hook, but `autoTestFixture` is not.
|
* `autoWorkerFixture` is set up for `beforeAll` hook, but `autoTestFixture` is not.
|
||||||
|
|
||||||
## Combine custom fixtures from multiple modules
|
## Combine custom fixtures from multiple modules
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chromium-tip-of-tree",
|
"name": "chromium-tip-of-tree",
|
||||||
"revision": "1223",
|
"revision": "1226",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "127.0.6492.0"
|
"browserVersion": "127.0.6505.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox",
|
"name": "firefox",
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webkit",
|
"name": "webkit",
|
||||||
"revision": "2012",
|
"revision": "2013",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"revisionOverrides": {
|
"revisionOverrides": {
|
||||||
"mac10.14": "1446",
|
"mac10.14": "1446",
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export class AndroidServerLauncherImpl {
|
||||||
|
|
||||||
// 2. Start the server
|
// 2. Start the server
|
||||||
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: 1, preLaunchedAndroidDevice: device });
|
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: 1, preLaunchedAndroidDevice: device });
|
||||||
const wsEndpoint = await server.listen(options.port);
|
const wsEndpoint = await server.listen(options.port, options.host);
|
||||||
|
|
||||||
// 3. Return the BrowserServer interface
|
// 3. Return the BrowserServer interface
|
||||||
const browserServer = new ws.EventEmitter() as (BrowserServer & WebSocketEventEmitter);
|
const browserServer = new ws.EventEmitter() as (BrowserServer & WebSocketEventEmitter);
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export class BrowserServerLauncherImpl implements BrowserServerLauncher {
|
||||||
|
|
||||||
// 2. Start the server
|
// 2. Start the server
|
||||||
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: Infinity, preLaunchedBrowser: browser, preLaunchedSocksProxy: socksProxy });
|
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: Infinity, preLaunchedBrowser: browser, preLaunchedSocksProxy: socksProxy });
|
||||||
const wsEndpoint = await server.listen(options.port);
|
const wsEndpoint = await server.listen(options.port, options.host);
|
||||||
|
|
||||||
// 3. Return the BrowserServer interface
|
// 3. Return the BrowserServer interface
|
||||||
const browserServer = new ws.EventEmitter() as (BrowserServer & WebSocketEventEmitter);
|
const browserServer = new ws.EventEmitter() as (BrowserServer & WebSocketEventEmitter);
|
||||||
|
|
|
||||||
|
|
@ -235,11 +235,11 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
|
||||||
context.setDefaultTimeout(this._defaultContextTimeout);
|
context.setDefaultTimeout(this._defaultContextTimeout);
|
||||||
if (this._defaultContextNavigationTimeout !== undefined)
|
if (this._defaultContextNavigationTimeout !== undefined)
|
||||||
context.setDefaultNavigationTimeout(this._defaultContextNavigationTimeout);
|
context.setDefaultNavigationTimeout(this._defaultContextNavigationTimeout);
|
||||||
await this._instrumentation.onDidCreateBrowserContext(context);
|
await this._instrumentation.runAfterCreateBrowserContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _willCloseContext(context: BrowserContext) {
|
async _willCloseContext(context: BrowserContext) {
|
||||||
this._contexts.delete(context);
|
this._contexts.delete(context);
|
||||||
await this._instrumentation.onWillCloseBrowserContext(context);
|
await this._instrumentation.runBeforeCloseBrowserContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,21 +24,23 @@ export interface ClientInstrumentation {
|
||||||
removeAllListeners(): void;
|
removeAllListeners(): void;
|
||||||
onApiCallBegin(apiCall: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }): void;
|
onApiCallBegin(apiCall: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }): void;
|
||||||
onApiCallEnd(userData: any, error?: Error): void;
|
onApiCallEnd(userData: any, error?: Error): void;
|
||||||
onDidCreateBrowserContext(context: BrowserContext): Promise<void>;
|
|
||||||
onDidCreateRequestContext(context: APIRequestContext): Promise<void>;
|
|
||||||
onWillPause(): void;
|
onWillPause(): void;
|
||||||
onWillCloseBrowserContext(context: BrowserContext): Promise<void>;
|
|
||||||
onWillCloseRequestContext(context: APIRequestContext): Promise<void>;
|
runAfterCreateBrowserContext(context: BrowserContext): Promise<void>;
|
||||||
|
runAfterCreateRequestContext(context: APIRequestContext): Promise<void>;
|
||||||
|
runBeforeCloseBrowserContext(context: BrowserContext): Promise<void>;
|
||||||
|
runBeforeCloseRequestContext(context: APIRequestContext): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientInstrumentationListener {
|
export interface ClientInstrumentationListener {
|
||||||
onApiCallBegin?(apiName: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }): void;
|
onApiCallBegin?(apiName: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }): void;
|
||||||
onApiCallEnd?(userData: any, error?: Error): void;
|
onApiCallEnd?(userData: any, error?: Error): void;
|
||||||
onDidCreateBrowserContext?(context: BrowserContext): Promise<void>;
|
|
||||||
onDidCreateRequestContext?(context: APIRequestContext): Promise<void>;
|
|
||||||
onWillPause?(): void;
|
onWillPause?(): void;
|
||||||
onWillCloseBrowserContext?(context: BrowserContext): Promise<void>;
|
|
||||||
onWillCloseRequestContext?(context: APIRequestContext): Promise<void>;
|
runAfterCreateBrowserContext?(context: BrowserContext): Promise<void>;
|
||||||
|
runAfterCreateRequestContext?(context: APIRequestContext): Promise<void>;
|
||||||
|
runBeforeCloseBrowserContext?(context: BrowserContext): Promise<void>;
|
||||||
|
runBeforeCloseRequestContext?(context: APIRequestContext): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createInstrumentation(): ClientInstrumentation {
|
export function createInstrumentation(): ClientInstrumentation {
|
||||||
|
|
@ -53,12 +55,19 @@ export function createInstrumentation(): ClientInstrumentation {
|
||||||
return (listener: ClientInstrumentationListener) => listeners.splice(listeners.indexOf(listener), 1);
|
return (listener: ClientInstrumentationListener) => listeners.splice(listeners.indexOf(listener), 1);
|
||||||
if (prop === 'removeAllListeners')
|
if (prop === 'removeAllListeners')
|
||||||
return () => listeners.splice(0, listeners.length);
|
return () => listeners.splice(0, listeners.length);
|
||||||
if (!prop.startsWith('on'))
|
if (prop.startsWith('run')) {
|
||||||
return obj[prop];
|
return async (...params: any[]) => {
|
||||||
return async (...params: any[]) => {
|
for (const listener of listeners)
|
||||||
for (const listener of listeners)
|
await (listener as any)[prop]?.(...params);
|
||||||
await (listener as any)[prop]?.(...params);
|
};
|
||||||
};
|
}
|
||||||
|
if (prop.startsWith('on')) {
|
||||||
|
return (...params: any[]) => {
|
||||||
|
for (const listener of listeners)
|
||||||
|
(listener as any)[prop]?.(...params);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return obj[prop];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ export class APIRequest implements api.APIRequest {
|
||||||
this._contexts.add(context);
|
this._contexts.add(context);
|
||||||
context._request = this;
|
context._request = this;
|
||||||
context._tracing._tracesDir = tracesDir;
|
context._tracing._tracesDir = tracesDir;
|
||||||
await context._instrumentation.onDidCreateRequestContext(context);
|
await context._instrumentation.runAfterCreateRequestContext(context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +102,7 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
|
||||||
|
|
||||||
async dispose(options: { reason?: string } = {}): Promise<void> {
|
async dispose(options: { reason?: string } = {}): Promise<void> {
|
||||||
this._closeReason = options.reason;
|
this._closeReason = options.reason;
|
||||||
await this._instrumentation.onWillCloseRequestContext(this);
|
await this._instrumentation.runBeforeCloseRequestContext(this);
|
||||||
try {
|
try {
|
||||||
await this._channel.dispose(options);
|
await this._channel.dispose(options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ export type LaunchServerOptions = {
|
||||||
},
|
},
|
||||||
downloadsPath?: string,
|
downloadsPath?: string,
|
||||||
chromiumSandbox?: boolean,
|
chromiumSandbox?: boolean,
|
||||||
|
host?: string,
|
||||||
port?: number,
|
port?: number,
|
||||||
wsPath?: string,
|
wsPath?: string,
|
||||||
logger?: Logger,
|
logger?: Logger,
|
||||||
|
|
@ -122,6 +123,7 @@ export type LaunchAndroidServerOptions = {
|
||||||
adbHost?: string,
|
adbHost?: string,
|
||||||
adbPort?: number,
|
adbPort?: number,
|
||||||
omitDriverInstall?: boolean,
|
omitDriverInstall?: boolean,
|
||||||
|
host?: string,
|
||||||
port?: number,
|
port?: number,
|
||||||
wsPath?: string,
|
wsPath?: string,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
17
packages/playwright-core/types/types.d.ts
vendored
17
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -13745,6 +13745,13 @@ export interface BrowserType<Unused = {}> {
|
||||||
*/
|
*/
|
||||||
headless?: boolean;
|
headless?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host to use for the web socket. It is optional and if it is omitted, the server will accept connections on the
|
||||||
|
* unspecified IPv6 address (::) when IPv6 is available, or the unspecified IPv4 address (0.0.0.0) otherwise. Consider
|
||||||
|
* hardening it with picking a specific interface.
|
||||||
|
*/
|
||||||
|
host?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If `true`, Playwright does not pass its own configurations args and only uses the ones from `args`. If an array is
|
* If `true`, Playwright does not pass its own configurations args and only uses the ones from `args`. If an array is
|
||||||
* given, then filters out the given default arguments. Dangerous option; use with care. Defaults to `false`.
|
* given, then filters out the given default arguments. Dangerous option; use with care. Defaults to `false`.
|
||||||
|
|
@ -14621,6 +14628,13 @@ export interface Android {
|
||||||
*/
|
*/
|
||||||
deviceSerialNumber?: string;
|
deviceSerialNumber?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host to use for the web socket. It is optional and if it is omitted, the server will accept connections on the
|
||||||
|
* unspecified IPv6 address (::) when IPv6 is available, or the unspecified IPv4 address (0.0.0.0) otherwise. Consider
|
||||||
|
* hardening it with picking a specific interface.
|
||||||
|
*/
|
||||||
|
host?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents automatic playwright driver installation on attach. Assumes that the drivers have been installed already.
|
* Prevents automatic playwright driver installation on attach. Assumes that the drivers have been installed already.
|
||||||
*/
|
*/
|
||||||
|
|
@ -17201,6 +17215,9 @@ export interface BrowserServer {
|
||||||
* Browser websocket endpoint which can be used as an argument to
|
* Browser websocket endpoint which can be used as an argument to
|
||||||
* [browserType.connect(wsEndpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect)
|
* [browserType.connect(wsEndpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect)
|
||||||
* to establish connection to the browser.
|
* to establish connection to the browser.
|
||||||
|
*
|
||||||
|
* Note that if the listen `host` option in `launchServer` options is not specified, localhost will be output anyway,
|
||||||
|
* even if the actual listening address is an unspecified address.
|
||||||
*/
|
*/
|
||||||
wsEndpoint(): string;
|
wsEndpoint(): string;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ async function innerMount(page: Page, componentRef: JsxComponent | ImportRef, op
|
||||||
|
|
||||||
const selector = await page.evaluate(async ({ component, hooksConfig }) => {
|
const selector = await page.evaluate(async ({ component, hooksConfig }) => {
|
||||||
component = await window.__pwUnwrapObject(component);
|
component = await window.__pwUnwrapObject(component);
|
||||||
|
hooksConfig = await window.__pwUnwrapObject(hooksConfig);
|
||||||
let rootElement = document.getElementById('root');
|
let rootElement = document.getElementById('root');
|
||||||
if (!rootElement) {
|
if (!rootElement) {
|
||||||
rootElement = document.createElement('div');
|
rootElement = document.createElement('div');
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,6 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type JsonPrimitive = string | number | boolean | null;
|
|
||||||
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
|
||||||
type JsonArray = JsonValue[];
|
|
||||||
export type JsonObject = { [Key in string]?: JsonValue };
|
|
||||||
|
|
||||||
export type JsxComponent = {
|
export type JsxComponent = {
|
||||||
__pw_type: 'jsx',
|
__pw_type: 'jsx',
|
||||||
type: any,
|
type: any,
|
||||||
|
|
@ -47,10 +42,10 @@ declare global {
|
||||||
playwrightMount(component: Component, rootElement: Element, hooksConfig?: any): Promise<void>;
|
playwrightMount(component: Component, rootElement: Element, hooksConfig?: any): Promise<void>;
|
||||||
playwrightUnmount(rootElement: Element): Promise<void>;
|
playwrightUnmount(rootElement: Element): Promise<void>;
|
||||||
playwrightUpdate(rootElement: Element, component: Component): Promise<void>;
|
playwrightUpdate(rootElement: Element, component: Component): Promise<void>;
|
||||||
__pw_hooks_before_mount?: (<HooksConfig extends JsonObject = JsonObject>(
|
__pw_hooks_before_mount?: (<HooksConfig>(
|
||||||
params: { hooksConfig?: HooksConfig; [key: string]: any }
|
params: { hooksConfig?: HooksConfig; [key: string]: any }
|
||||||
) => Promise<any>)[];
|
) => Promise<any>)[];
|
||||||
__pw_hooks_after_mount?: (<HooksConfig extends JsonObject = JsonObject>(
|
__pw_hooks_after_mount?: (<HooksConfig>(
|
||||||
params: { hooksConfig?: HooksConfig; [key: string]: any }
|
params: { hooksConfig?: HooksConfig; [key: string]: any }
|
||||||
) => Promise<void>)[];
|
) => Promise<void>)[];
|
||||||
// Can't start with __pw due to core reuse bindings logic for __pw*.
|
// Can't start with __pw due to core reuse bindings logic for __pw*.
|
||||||
|
|
|
||||||
6
packages/playwright-ct-react/hooks.d.ts
vendored
6
packages/playwright-ct-react/hooks.d.ts
vendored
|
|
@ -14,11 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
export declare function beforeMount<HooksConfig>(
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
|
||||||
callback: (params: { hooksConfig?: HooksConfig; App: () => JSX.Element }) => Promise<void | JSX.Element>
|
callback: (params: { hooksConfig?: HooksConfig; App: () => JSX.Element }) => Promise<void | JSX.Element>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
||||||
): void;
|
): void;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-react/index.d.ts
vendored
5
packages/playwright-ct-react/index.d.ts
vendored
|
|
@ -15,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject> {
|
export interface MountOptions<HooksConfig> {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,7 +27,7 @@ export interface MountResult extends Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject>(
|
mount<HooksConfig>(
|
||||||
component: JSX.Element,
|
component: JSX.Element,
|
||||||
options?: MountOptions<HooksConfig>
|
options?: MountOptions<HooksConfig>
|
||||||
): Promise<MountResult>;
|
): Promise<MountResult>;
|
||||||
|
|
|
||||||
6
packages/playwright-ct-react17/hooks.d.ts
vendored
6
packages/playwright-ct-react17/hooks.d.ts
vendored
|
|
@ -14,11 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
export declare function beforeMount<HooksConfig>(
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
|
||||||
callback: (params: { hooksConfig?: HooksConfig; App: () => JSX.Element }) => Promise<void | JSX.Element>
|
callback: (params: { hooksConfig?: HooksConfig; App: () => JSX.Element }) => Promise<void | JSX.Element>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
||||||
): void;
|
): void;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-react17/index.d.ts
vendored
5
packages/playwright-ct-react17/index.d.ts
vendored
|
|
@ -15,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject> {
|
export interface MountOptions<HooksConfig> {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,7 +27,7 @@ export interface MountResult extends Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject>(
|
mount<HooksConfig>(
|
||||||
component: JSX.Element,
|
component: JSX.Element,
|
||||||
options?: MountOptions<HooksConfig>
|
options?: MountOptions<HooksConfig>
|
||||||
): Promise<MountResult>;
|
): Promise<MountResult>;
|
||||||
|
|
|
||||||
7
packages/playwright-ct-solid/hooks.d.ts
vendored
7
packages/playwright-ct-solid/hooks.d.ts
vendored
|
|
@ -14,12 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { JSXElement } from "solid-js";
|
import { JSXElement } from 'solid-js';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
export declare function beforeMount<HooksConfig>(
|
||||||
callback: (params: { hooksConfig?: HooksConfig, App: () => JSXElement }) => Promise<void | JSXElement>
|
callback: (params: { hooksConfig?: HooksConfig, App: () => JSXElement }) => Promise<void | JSXElement>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
callback: (params: { hooksConfig?: HooksConfig }) => Promise<void>
|
||||||
): void;
|
): void;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-solid/index.d.ts
vendored
5
packages/playwright-ct-solid/index.d.ts
vendored
|
|
@ -15,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject> {
|
export interface MountOptions<HooksConfig> {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,7 +27,7 @@ export interface MountResult extends Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject>(
|
mount<HooksConfig>(
|
||||||
component: JSX.Element,
|
component: JSX.Element,
|
||||||
options?: MountOptions<HooksConfig>
|
options?: MountOptions<HooksConfig>
|
||||||
): Promise<MountResult>;
|
): Promise<MountResult>;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-svelte/hooks.d.ts
vendored
5
packages/playwright-ct-svelte/hooks.d.ts
vendored
|
|
@ -15,15 +15,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ComponentConstructorOptions, SvelteComponent } from 'svelte';
|
import type { ComponentConstructorOptions, SvelteComponent } from 'svelte';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
export declare function beforeMount<HooksConfig>(
|
||||||
callback: (params: {
|
callback: (params: {
|
||||||
hooksConfig?: HooksConfig,
|
hooksConfig?: HooksConfig,
|
||||||
App: new (options: Partial<ComponentConstructorOptions>) => SvelteComponent
|
App: new (options: Partial<ComponentConstructorOptions>) => SvelteComponent
|
||||||
}) => Promise<SvelteComponent | void>
|
}) => Promise<SvelteComponent | void>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: {
|
callback: (params: {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
svelteComponent: SvelteComponent;
|
svelteComponent: SvelteComponent;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-svelte/index.d.ts
vendored
5
packages/playwright-ct-svelte/index.d.ts
vendored
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { SvelteComponent, ComponentProps } from 'svelte/types/runtime';
|
import type { SvelteComponent, ComponentProps } from 'svelte/types/runtime';
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
|
|
@ -23,7 +22,7 @@ type ComponentSlot = string | string[];
|
||||||
type ComponentSlots = Record<string, ComponentSlot> & { default?: ComponentSlot };
|
type ComponentSlots = Record<string, ComponentSlot> & { default?: ComponentSlot };
|
||||||
type ComponentEvents = Record<string, Function>;
|
type ComponentEvents = Record<string, Function>;
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject, Component extends SvelteComponent> {
|
export interface MountOptions<HooksConfig, Component extends SvelteComponent> {
|
||||||
props?: ComponentProps<Component>;
|
props?: ComponentProps<Component>;
|
||||||
slots?: ComponentSlots;
|
slots?: ComponentSlots;
|
||||||
on?: ComponentEvents;
|
on?: ComponentEvents;
|
||||||
|
|
@ -39,7 +38,7 @@ export interface MountResult<Component extends SvelteComponent> extends Locator
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject, Component extends SvelteComponent = SvelteComponent>(
|
mount<HooksConfig, Component extends SvelteComponent = SvelteComponent>(
|
||||||
component: new (...args: any[]) => Component,
|
component: new (...args: any[]) => Component,
|
||||||
options?: MountOptions<HooksConfig, Component>
|
options?: MountOptions<HooksConfig, Component>
|
||||||
): Promise<MountResult<Component>>;
|
): Promise<MountResult<Component>>;
|
||||||
|
|
|
||||||
5
packages/playwright-ct-vue/hooks.d.ts
vendored
5
packages/playwright-ct-vue/hooks.d.ts
vendored
|
|
@ -15,12 +15,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { App, ComponentPublicInstance } from 'vue';
|
import type { App, ComponentPublicInstance } from 'vue';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
export declare function beforeMount<HooksConfig>(
|
||||||
callback: (params: { app: App; hooksConfig?: HooksConfig }) => Promise<void>
|
callback: (params: { app: App; hooksConfig?: HooksConfig }) => Promise<void>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: {
|
callback: (params: {
|
||||||
app: App;
|
app: App;
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
|
|
|
||||||
9
packages/playwright-ct-vue/index.d.ts
vendored
9
packages/playwright-ct-vue/index.d.ts
vendored
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
type ComponentSlot = string | string[];
|
type ComponentSlot = string | string[];
|
||||||
|
|
@ -29,14 +28,14 @@ type ComponentProps<T> =
|
||||||
T extends (props: infer P, ...args: any) => any ? P :
|
T extends (props: infer P, ...args: any) => any ? P :
|
||||||
{};
|
{};
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject, Component> {
|
export interface MountOptions<HooksConfig, Component> {
|
||||||
props?: ComponentProps<Component>;
|
props?: ComponentProps<Component>;
|
||||||
slots?: ComponentSlots;
|
slots?: ComponentSlots;
|
||||||
on?: ComponentEvents;
|
on?: ComponentEvents;
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MountOptionsJsx<HooksConfig extends JsonObject> {
|
export interface MountOptionsJsx<HooksConfig> {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,11 +54,11 @@ export interface MountResultJsx extends Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject>(
|
mount<HooksConfig>(
|
||||||
component: JSX.Element,
|
component: JSX.Element,
|
||||||
options: MountOptionsJsx<HooksConfig>
|
options: MountOptionsJsx<HooksConfig>
|
||||||
): Promise<MountResultJsx>;
|
): Promise<MountResultJsx>;
|
||||||
mount<HooksConfig extends JsonObject, Component = unknown>(
|
mount<HooksConfig, Component = unknown>(
|
||||||
component: Component,
|
component: Component,
|
||||||
options?: MountOptions<HooksConfig, Component>
|
options?: MountOptions<HooksConfig, Component>
|
||||||
): Promise<MountResult<Component>>;
|
): Promise<MountResult<Component>>;
|
||||||
|
|
|
||||||
15
packages/playwright-ct-vue2/hooks.d.ts
vendored
15
packages/playwright-ct-vue2/hooks.d.ts
vendored
|
|
@ -14,17 +14,16 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentOptions } from 'vue';
|
import type { ComponentOptions } from 'vue';
|
||||||
import { CombinedVueInstance, Vue, VueConstructor } from 'vue/types/vue';
|
import type { CombinedVueInstance, Vue, VueConstructor } from 'vue/types/vue';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
|
|
||||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
export declare function beforeMount<HooksConfig>(
|
||||||
callback: (params: {
|
callback: (params: {
|
||||||
hooksConfig?: HooksConfig,
|
hooksConfig?: HooksConfig,
|
||||||
Vue: VueConstructor<Vue>,
|
Vue: VueConstructor<Vue>,
|
||||||
}) => Promise<void | ComponentOptions<Vue> & Record<string, unknown>>
|
}) => Promise<void | ComponentOptions<Vue> & Record<string, unknown>>
|
||||||
): void;
|
): void;
|
||||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
export declare function afterMount<HooksConfig>(
|
||||||
callback: (params: {
|
callback: (params: {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
instance: CombinedVueInstance<
|
instance: CombinedVueInstance<
|
||||||
|
|
|
||||||
9
packages/playwright-ct-vue2/index.d.ts
vendored
9
packages/playwright-ct-vue2/index.d.ts
vendored
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Locator } from 'playwright/test';
|
import type { Locator } from 'playwright/test';
|
||||||
import type { JsonObject } from '@playwright/experimental-ct-core/types/component';
|
|
||||||
import type { TestType } from '@playwright/experimental-ct-core';
|
import type { TestType } from '@playwright/experimental-ct-core';
|
||||||
|
|
||||||
type Slot = string | string[];
|
type Slot = string | string[];
|
||||||
|
|
@ -29,14 +28,14 @@ type ComponentProps<T> =
|
||||||
T extends (props: infer P, ...args: any) => any ? P :
|
T extends (props: infer P, ...args: any) => any ? P :
|
||||||
{};
|
{};
|
||||||
|
|
||||||
export interface MountOptions<HooksConfig extends JsonObject, Component> {
|
export interface MountOptions<HooksConfig, Component> {
|
||||||
props?: ComponentProps<Component>;
|
props?: ComponentProps<Component>;
|
||||||
slots?: ComponentSlots;
|
slots?: ComponentSlots;
|
||||||
on?: ComponentEvents;
|
on?: ComponentEvents;
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MountOptionsJsx<HooksConfig extends JsonObject> {
|
export interface MountOptionsJsx<HooksConfig> {
|
||||||
hooksConfig?: HooksConfig;
|
hooksConfig?: HooksConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,11 +54,11 @@ export interface MountResultJsx extends Locator {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const test: TestType<{
|
export const test: TestType<{
|
||||||
mount<HooksConfig extends JsonObject>(
|
mount<HooksConfig>(
|
||||||
component: JSX.Element,
|
component: JSX.Element,
|
||||||
options?: MountOptionsJsx<HooksConfig>
|
options?: MountOptionsJsx<HooksConfig>
|
||||||
): Promise<MountResultJsx>;
|
): Promise<MountResultJsx>;
|
||||||
mount<HooksConfig extends JsonObject, Component = unknown>(
|
mount<HooksConfig, Component = unknown>(
|
||||||
component: Component,
|
component: Component,
|
||||||
options?: MountOptions<HooksConfig, Component>
|
options?: MountOptions<HooksConfig, Component>
|
||||||
): Promise<MountResult<Component>>;
|
): Promise<MountResult<Component>>;
|
||||||
|
|
|
||||||
|
|
@ -268,19 +268,19 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
onWillPause: () => {
|
onWillPause: () => {
|
||||||
currentTestInfo()?.setTimeout(0);
|
currentTestInfo()?.setTimeout(0);
|
||||||
},
|
},
|
||||||
onDidCreateBrowserContext: async (context: BrowserContext) => {
|
runAfterCreateBrowserContext: async (context: BrowserContext) => {
|
||||||
await artifactsRecorder?.didCreateBrowserContext(context);
|
await artifactsRecorder?.didCreateBrowserContext(context);
|
||||||
const testInfo = currentTestInfo();
|
const testInfo = currentTestInfo();
|
||||||
if (testInfo)
|
if (testInfo)
|
||||||
attachConnectedHeaderIfNeeded(testInfo, context.browser());
|
attachConnectedHeaderIfNeeded(testInfo, context.browser());
|
||||||
},
|
},
|
||||||
onDidCreateRequestContext: async (context: APIRequestContext) => {
|
runAfterCreateRequestContext: async (context: APIRequestContext) => {
|
||||||
await artifactsRecorder?.didCreateRequestContext(context);
|
await artifactsRecorder?.didCreateRequestContext(context);
|
||||||
},
|
},
|
||||||
onWillCloseBrowserContext: async (context: BrowserContext) => {
|
runBeforeCloseBrowserContext: async (context: BrowserContext) => {
|
||||||
await artifactsRecorder?.willCloseBrowserContext(context);
|
await artifactsRecorder?.willCloseBrowserContext(context);
|
||||||
},
|
},
|
||||||
onWillCloseRequestContext: async (context: APIRequestContext) => {
|
runBeforeCloseRequestContext: async (context: APIRequestContext) => {
|
||||||
await artifactsRecorder?.willCloseRequestContext(context);
|
await artifactsRecorder?.willCloseRequestContext(context);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
private _messageSink: (message: teleReceiver.JsonEvent) => void;
|
private _messageSink: (message: teleReceiver.JsonEvent) => void;
|
||||||
private _rootDir!: string;
|
private _rootDir!: string;
|
||||||
private _emitterOptions: TeleReporterEmitterOptions;
|
private _emitterOptions: TeleReporterEmitterOptions;
|
||||||
|
// In case there is blob reporter and UI mode, make sure one does override
|
||||||
|
// the id assigned by the other.
|
||||||
|
private readonly _idSymbol = Symbol('id');
|
||||||
|
|
||||||
constructor(messageSink: (message: teleReceiver.JsonEvent) => void, options: TeleReporterEmitterOptions = {}) {
|
constructor(messageSink: (message: teleReceiver.JsonEvent) => void, options: TeleReporterEmitterOptions = {}) {
|
||||||
this._messageSink = messageSink;
|
this._messageSink = messageSink;
|
||||||
|
|
@ -55,7 +58,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
onTestBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult): void {
|
onTestBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult): void {
|
||||||
(result as any)[idSymbol] = createGuid();
|
(result as any)[this._idSymbol] = createGuid();
|
||||||
this._messageSink({
|
this._messageSink({
|
||||||
method: 'onTestBegin',
|
method: 'onTestBegin',
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -82,12 +85,12 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
onStepBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult, step: reporterTypes.TestStep): void {
|
onStepBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult, step: reporterTypes.TestStep): void {
|
||||||
(step as any)[idSymbol] = createGuid();
|
(step as any)[this._idSymbol] = createGuid();
|
||||||
this._messageSink({
|
this._messageSink({
|
||||||
method: 'onStepBegin',
|
method: 'onStepBegin',
|
||||||
params: {
|
params: {
|
||||||
testId: test.id,
|
testId: test.id,
|
||||||
resultId: (result as any)[idSymbol],
|
resultId: (result as any)[this._idSymbol],
|
||||||
step: this._serializeStepStart(step)
|
step: this._serializeStepStart(step)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -98,7 +101,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
method: 'onStepEnd',
|
method: 'onStepEnd',
|
||||||
params: {
|
params: {
|
||||||
testId: test.id,
|
testId: test.id,
|
||||||
resultId: (result as any)[idSymbol],
|
resultId: (result as any)[this._idSymbol],
|
||||||
step: this._serializeStepEnd(step)
|
step: this._serializeStepEnd(step)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -126,7 +129,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
const data = isBase64 ? chunk.toString('base64') : chunk;
|
const data = isBase64 ? chunk.toString('base64') : chunk;
|
||||||
this._messageSink({
|
this._messageSink({
|
||||||
method: 'onStdIO',
|
method: 'onStdIO',
|
||||||
params: { testId: test?.id, resultId: result ? (result as any)[idSymbol] : undefined, type, data, isBase64 }
|
params: { testId: test?.id, resultId: result ? (result as any)[this._idSymbol] : undefined, type, data, isBase64 }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +217,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
|
|
||||||
private _serializeResultStart(result: reporterTypes.TestResult): teleReceiver.JsonTestResultStart {
|
private _serializeResultStart(result: reporterTypes.TestResult): teleReceiver.JsonTestResultStart {
|
||||||
return {
|
return {
|
||||||
id: (result as any)[idSymbol],
|
id: (result as any)[this._idSymbol],
|
||||||
retry: result.retry,
|
retry: result.retry,
|
||||||
workerIndex: result.workerIndex,
|
workerIndex: result.workerIndex,
|
||||||
parallelIndex: result.parallelIndex,
|
parallelIndex: result.parallelIndex,
|
||||||
|
|
@ -224,7 +227,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
|
|
||||||
private _serializeResultEnd(result: reporterTypes.TestResult): teleReceiver.JsonTestResultEnd {
|
private _serializeResultEnd(result: reporterTypes.TestResult): teleReceiver.JsonTestResultEnd {
|
||||||
return {
|
return {
|
||||||
id: (result as any)[idSymbol],
|
id: (result as any)[this._idSymbol],
|
||||||
duration: result.duration,
|
duration: result.duration,
|
||||||
status: result.status,
|
status: result.status,
|
||||||
errors: result.errors,
|
errors: result.errors,
|
||||||
|
|
@ -244,8 +247,8 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
|
|
||||||
private _serializeStepStart(step: reporterTypes.TestStep): teleReceiver.JsonTestStepStart {
|
private _serializeStepStart(step: reporterTypes.TestStep): teleReceiver.JsonTestStepStart {
|
||||||
return {
|
return {
|
||||||
id: (step as any)[idSymbol],
|
id: (step as any)[this._idSymbol],
|
||||||
parentStepId: (step.parent as any)?.[idSymbol],
|
parentStepId: (step.parent as any)?.[this._idSymbol],
|
||||||
title: step.title,
|
title: step.title,
|
||||||
category: step.category,
|
category: step.category,
|
||||||
startTime: +step.startTime,
|
startTime: +step.startTime,
|
||||||
|
|
@ -255,7 +258,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
|
|
||||||
private _serializeStepEnd(step: reporterTypes.TestStep): teleReceiver.JsonTestStepEnd {
|
private _serializeStepEnd(step: reporterTypes.TestStep): teleReceiver.JsonTestStepEnd {
|
||||||
return {
|
return {
|
||||||
id: (step as any)[idSymbol],
|
id: (step as any)[this._idSymbol],
|
||||||
duration: step.duration,
|
duration: step.duration,
|
||||||
error: step.error,
|
error: step.error,
|
||||||
};
|
};
|
||||||
|
|
@ -280,5 +283,3 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
return path.relative(this._rootDir, absolutePath);
|
return path.relative(this._rootDir, absolutePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const idSymbol = Symbol('id');
|
|
||||||
|
|
|
||||||
12
packages/playwright/types/test.d.ts
vendored
12
packages/playwright/types/test.d.ts
vendored
|
|
@ -266,8 +266,9 @@ interface TestProject<TestArgs = {}, WorkerArgs = {}> {
|
||||||
/**
|
/**
|
||||||
* Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only
|
* Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only
|
||||||
* run tests with "cart" in the title. Also available globally and in the [command line](https://playwright.dev/docs/test-cli) with the `-g`
|
* run tests with "cart" in the title. Also available globally and in the [command line](https://playwright.dev/docs/test-cli) with the `-g`
|
||||||
* option. The regular expression will be tested against the string that consists of the test file name,
|
* option. The regular expression will be tested against the string that consists of the project name, the test file
|
||||||
* `test.describe` name (if any) and the test name divided by spaces, e.g. `my-test.spec.ts my-suite my-test`.
|
* name, the `test.describe` name (if any), the test name and the test tags divided by spaces, e.g. `chromium
|
||||||
|
* my-test.spec.ts my-suite my-test`.
|
||||||
*
|
*
|
||||||
* `grep` option is also useful for [tagging tests](https://playwright.dev/docs/test-annotations#tag-tests).
|
* `grep` option is also useful for [tagging tests](https://playwright.dev/docs/test-annotations#tag-tests).
|
||||||
*/
|
*/
|
||||||
|
|
@ -1130,8 +1131,9 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
|
||||||
/**
|
/**
|
||||||
* Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only
|
* Filter to only run tests with a title matching one of the patterns. For example, passing `grep: /cart/` should only
|
||||||
* run tests with "cart" in the title. Also available in the [command line](https://playwright.dev/docs/test-cli) with the `-g` option. The
|
* run tests with "cart" in the title. Also available in the [command line](https://playwright.dev/docs/test-cli) with the `-g` option. The
|
||||||
* regular expression will be tested against the string that consists of the test file name, `test.describe` name (if
|
* regular expression will be tested against the string that consists of the project name, the test file name, the
|
||||||
* any) and the test name divided by spaces, e.g. `my-test.spec.ts my-suite my-test`.
|
* `test.describe` name (if any), the test name and the test tags divided by spaces, e.g. `chromium my-test.spec.ts
|
||||||
|
* my-suite my-test`.
|
||||||
*
|
*
|
||||||
* `grep` option is also useful for [tagging tests](https://playwright.dev/docs/test-annotations#tag-tests).
|
* `grep` option is also useful for [tagging tests](https://playwright.dev/docs/test-annotations#tag-tests).
|
||||||
*
|
*
|
||||||
|
|
@ -5088,7 +5090,7 @@ export interface PlaywrightWorkerOptions {
|
||||||
* - `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
* - `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
||||||
* - `'on-all-retries'`: Record trace only when retrying a test.
|
* - `'on-all-retries'`: Record trace only when retrying a test.
|
||||||
* - `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
|
* - `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
|
||||||
* - `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retires. When test run
|
* - `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retries. When test run
|
||||||
* passes, remove the recorded trace.
|
* passes, remove the recorded trace.
|
||||||
*
|
*
|
||||||
* For more control, pass an object that specifies `mode` and trace features to enable.
|
* For more control, pass an object that specifies `mode` and trace features to enable.
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
const traceUrl = new URL(location.href).searchParams.get('trace');
|
const traceUrl = new URL(location.href).searchParams.get('trace');
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.set('trace', traceUrl);
|
params.set('trace', traceUrl);
|
||||||
await fetch('context?' + params.toString()).then(r => r.json());
|
await fetch('contexts?' + params.toString()).then(r => r.json());
|
||||||
await location.reload();
|
await location.reload();
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,17 @@ test('android.launchServer should connect to a device', async ({ playwright }) =
|
||||||
await browserServer.close();
|
await browserServer.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('android.launchServer should work with host', async ({ playwright }) => {
|
||||||
|
const host = '0.0.0.0';
|
||||||
|
const browserServer = await playwright._android.launchServer({ host });
|
||||||
|
expect(browserServer.wsEndpoint()).toContain(String(host));
|
||||||
|
const device = await playwright._android.connect(browserServer.wsEndpoint());
|
||||||
|
const output = await device.shell('echo 123');
|
||||||
|
expect(output.toString()).toBe('123\n');
|
||||||
|
await device.close();
|
||||||
|
await browserServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
test('android.launchServer should handle close event correctly', async ({ playwright }) => {
|
test('android.launchServer should handle close event correctly', async ({ playwright }) => {
|
||||||
const receivedEvents: string[] = [];
|
const receivedEvents: string[] = [];
|
||||||
const browserServer = await playwright._android.launchServer();
|
const browserServer = await playwright._android.launchServer();
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,17 @@ import Button from '../src/components/Button.vue';
|
||||||
import '../src/assets/index.css';
|
import '../src/assets/index.css';
|
||||||
|
|
||||||
export type HooksConfig = {
|
export type HooksConfig = {
|
||||||
route?: string;
|
|
||||||
routing?: boolean;
|
routing?: boolean;
|
||||||
|
components?: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeMount<HooksConfig>(async ({ app, hooksConfig }) => {
|
beforeMount<HooksConfig>(async ({ app, hooksConfig }) => {
|
||||||
if (hooksConfig?.routing)
|
if (hooksConfig?.routing)
|
||||||
app.use(router as any); // TODO: remove any and fix the various installed conflicting Vue versions
|
app.use(router as any); // TODO: remove any and fix the various installed conflicting Vue versions
|
||||||
app.component('Button', Button);
|
|
||||||
|
for (const [name, component] of Object.entries(hooksConfig?.components || {}))
|
||||||
|
app.component(name, component);
|
||||||
|
|
||||||
console.log(`Before mount: ${JSON.stringify(hooksConfig)}, app: ${!!app}`);
|
console.log(`Before mount: ${JSON.stringify(hooksConfig)}, app: ${!!app}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import DefaultSlot from '@/components/DefaultSlot.vue';
|
import DefaultSlot from '@/components/DefaultSlot.vue';
|
||||||
import NamedSlots from '@/components/NamedSlots.vue';
|
import NamedSlots from '@/components/NamedSlots.vue';
|
||||||
|
import Button from '@/components/Button.vue';
|
||||||
|
|
||||||
test('render a default slot', async ({ mount }) => {
|
test('render a default slot', async ({ mount }) => {
|
||||||
const component = await mount(DefaultSlot, {
|
const component = await mount(DefaultSlot, {
|
||||||
|
|
@ -16,6 +17,9 @@ test('render a component as slot', async ({ mount }) => {
|
||||||
slots: {
|
slots: {
|
||||||
default: '<Button title="Submit" />', // component is registered globally in /playwright/index.ts
|
default: '<Button title="Submit" />', // component is registered globally in /playwright/index.ts
|
||||||
},
|
},
|
||||||
|
hooksConfig: {
|
||||||
|
components: { Button }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
await expect(component).toContainText('Submit');
|
await expect(component).toContainText('Submit');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import DefaultSlot from '@/components/DefaultSlot.vue';
|
import DefaultSlot from '@/components/DefaultSlot.vue';
|
||||||
import NamedSlots from '@/components/NamedSlots.vue';
|
import NamedSlots from '@/components/NamedSlots.vue';
|
||||||
|
import Button from '@/components/Button.vue';
|
||||||
|
|
||||||
test('render a default slot', async ({ mount }) => {
|
test('render a default slot', async ({ mount }) => {
|
||||||
const component = await mount(DefaultSlot, {
|
const component = await mount(DefaultSlot, {
|
||||||
|
|
@ -16,6 +17,9 @@ test('render a component as slot', async ({ mount }) => {
|
||||||
slots: {
|
slots: {
|
||||||
default: '<Button title="Submit" />', // component is registered globally in /playwright/index.ts
|
default: '<Button title="Submit" />', // component is registered globally in /playwright/index.ts
|
||||||
},
|
},
|
||||||
|
hooksConfig: {
|
||||||
|
components: { Button }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
await expect(component).toContainText('Submit');
|
await expect(component).toContainText('Submit');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,13 @@ it.describe('launch server', () => {
|
||||||
await browserServer.close();
|
await browserServer.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work with host', async ({ browserType }) => {
|
||||||
|
const host = '0.0.0.0';
|
||||||
|
const browserServer = await browserType.launchServer({ host });
|
||||||
|
expect(browserServer.wsEndpoint()).toContain(String(host));
|
||||||
|
await browserServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
it('should work with port', async ({ browserType }, testInfo) => {
|
it('should work with port', async ({ browserType }, testInfo) => {
|
||||||
const port = 8800 + testInfo.workerIndex;
|
const port = 8800 + testInfo.workerIndex;
|
||||||
const browserServer = await browserType.launchServer({ port });
|
const browserServer = await browserType.launchServer({ port });
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ test.beforeAll(async function recordTrace({ browser, browserName, browserType, s
|
||||||
|
|
||||||
// Go through instrumentation to exercise reentrant stack traces.
|
// Go through instrumentation to exercise reentrant stack traces.
|
||||||
const csi = {
|
const csi = {
|
||||||
onWillCloseBrowserContext: async () => {
|
runBeforeCloseBrowserContext: async () => {
|
||||||
await page.hover('body');
|
await page.hover('body');
|
||||||
await page.close();
|
await page.close();
|
||||||
traceFile = path.join(workerInfo.project.outputDir, String(workerInfo.workerIndex), browserName, 'trace.zip');
|
traceFile = path.join(workerInfo.project.outputDir, String(workerInfo.workerIndex), browserName, 'trace.zip');
|
||||||
|
|
@ -1207,3 +1207,20 @@ test('should remove noscript when javaScriptEnabled is set to true', async ({ br
|
||||||
await expect(frame.getByText('Always visible')).toBeVisible();
|
await expect(frame.getByText('Always visible')).toBeVisible();
|
||||||
await expect(frame.getByText('Enable JavaScript to run this app.')).toBeHidden();
|
await expect(frame.getByText('Enable JavaScript to run this app.')).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should open snapshot in new browser context', async ({ browser, page, runAndTrace, server }) => {
|
||||||
|
const traceViewer = await runAndTrace(async () => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await page.setContent('hello');
|
||||||
|
});
|
||||||
|
await traceViewer.snapshotFrame('page.setContent');
|
||||||
|
const popupPromise = traceViewer.page.context().waitForEvent('page');
|
||||||
|
await traceViewer.page.getByTitle('Open snapshot in a new tab').click();
|
||||||
|
const popup = await popupPromise;
|
||||||
|
|
||||||
|
// doesn't share sw.bundle.js
|
||||||
|
const newPage = await browser.newPage();
|
||||||
|
await newPage.goto(popup.url());
|
||||||
|
await expect(newPage.getByText('hello')).toBeVisible();
|
||||||
|
await newPage.close();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,38 @@ test('should merge blob into blob', async ({ runInlineTest, mergeReports, showRe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should produce consistent step ids', {
|
||||||
|
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31023' },
|
||||||
|
}, async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||||
|
const files = {
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
retries: 1,
|
||||||
|
reporter: [
|
||||||
|
['blob', { outputFile: 'blob-report/report-1.zip' }],
|
||||||
|
['blob', { outputFile: 'blob-report/report-2.zip' }]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.test.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('math 1', async ({}) => {
|
||||||
|
expect(1 + 1).toBe(2);
|
||||||
|
});
|
||||||
|
`
|
||||||
|
};
|
||||||
|
await runInlineTest(files);
|
||||||
|
const reportDir = test.info().outputPath('blob-report');
|
||||||
|
const reportFiles = await fs.promises.readdir(reportDir);
|
||||||
|
reportFiles.sort();
|
||||||
|
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip']);
|
||||||
|
const { exitCode } = await mergeReports(reportDir, { 'PLAYWRIGHT_HTML_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html,json'] });
|
||||||
|
expect(exitCode).toBe(0);
|
||||||
|
await showReport();
|
||||||
|
await expect(page.locator('.subnav-item:has-text("All") .counter')).toHaveText('2');
|
||||||
|
await expect(page.locator('.subnav-item:has-text("Passed") .counter')).toHaveText('2');
|
||||||
|
});
|
||||||
|
|
||||||
test('be able to merge incomplete shards', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
test('be able to merge incomplete shards', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||||
const reportDir = test.info().outputPath('blob-report');
|
const reportDir = test.info().outputPath('blob-report');
|
||||||
const files = {
|
const files = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue