Compare commits

...

6 commits

Author SHA1 Message Date
Playwright Service 2ee3aaa0f5
cherry-pick(#27667): docs: make test-timeouts AAA compliant (#27676)
This PR cherry-picks the following commits:

- a005064cc8

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-18 08:28:43 +02:00
Playwright Service 0594783ed6
cherry-pick(#27630): fix: merge{Tests,Expects} via ESM imports (#27641)
This PR cherry-picks the following commits:

- fd2fbe9d2f

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-17 22:43:45 +02:00
Playwright Service a115439b47
cherry-pick(#27559): docs: Fixing a release version of a method toHaveAttribute (#27560)
This PR cherry-picks the following commits:

- 117f3f1298

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-12 08:54:35 +02:00
Pavel Feldman 3049d99bc8 cherry-pick(#27555): chore: composed->merge 2023-10-11 13:58:19 -07:00
Dmitry Gozman ae31f58b43
chore: mark 1.39.0 (#27550) 2023-10-11 11:20:29 -07:00
Dmitry Gozman 5313514995 cherry-pick(#27549): docs: update release notes for 1.39 2023-10-11 10:59:10 -07:00
38 changed files with 209 additions and 145 deletions

View file

@ -1152,7 +1152,7 @@ Expected attribute value.
* since: v1.18 * since: v1.18
## async method: LocatorAssertions.toHaveAttribute#2 ## async method: LocatorAssertions.toHaveAttribute#2
* since: v1.40 * since: v1.39
* langs: js * langs: js
Ensures the [Locator] points to an element with given attribute. The method will assert attribute Ensures the [Locator] points to an element with given attribute. The method will assert attribute
@ -1166,13 +1166,13 @@ await expect(locator).not.toHaveAttribute('open');
``` ```
### param: LocatorAssertions.toHaveAttribute#2.name ### param: LocatorAssertions.toHaveAttribute#2.name
* since: v1.40 * since: v1.39
- `name` <[string]> - `name` <[string]>
Attribute name. Attribute name.
### option: LocatorAssertions.toHaveAttribute#2.timeout = %%-js-assertions-timeout-%% ### option: LocatorAssertions.toHaveAttribute#2.timeout = %%-js-assertions-timeout-%%
* since: v1.40 * since: v1.39
## async method: LocatorAssertions.toHaveClass ## async method: LocatorAssertions.toHaveClass
* since: v1.20 * since: v1.20

View file

@ -6,7 +6,7 @@ toc_max_heading_level: 2
## Version 1.39 ## Version 1.39
Maintenance release. Evergreen browsers update.
### Browser Versions ### Browser Versions

View file

@ -6,7 +6,7 @@ toc_max_heading_level: 2
## Version 1.39 ## Version 1.39
Maintenance release. Evergreen browsers update.
### Browser Versions ### Browser Versions

View file

@ -8,46 +8,68 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
## Version 1.39 ## Version 1.39
### Extending expect with custom matchers ### Add custom matchers to your expect
You can extend Playwright assertions by providing custom matchers. These matchers will be available on the expect object. You can extend Playwright assertions by providing custom matchers. These matchers will be available on the expect object.
```js title=fixtures.ts ```js title="test.spec.ts"
import { expect as baseExpect } from '@playwright/test'; import { expect as baseExpect } from '@playwright/test';
export const expect = baseExpect.extend({ export const expect = baseExpect.extend({
async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) { async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
// Note: this matcher never passes, see the documentation for a full example. // ... see documentation for how to write matchers.
// Return a "pass" flag and a message getter.
return { pass: false, message: () => `Expected ${expected} amount` };
}, },
}); });
test('pass', async ({ page }) => {
await expect(page.getByTestId('cart')).toHaveAmount(5);
});
``` ```
See the documentation [for a full example](./test-configuration.md#add-custom-matchers-using-expectextend). See the documentation [for a full example](./test-configuration.md#add-custom-matchers-using-expectextend).
### Merging fixtures and expect matchers ### Merge test fixtures
You can combine fixtures and custom expect matchers from multiple files or modules. You can now merge test fixtures from multiple files or modules:
```js title="fixtures.ts" ```js title="fixtures.ts"
import { composedTest, composedExpect } from '@playwright/test'; import { mergeTests } from '@playwright/test';
import { test as dbTest } from 'database-test-utils';
import { test as a11yTest } from 'a11y-test-utils';
export const test = mergeTests(dbTest, a11yTest);
```
```js title="test.spec.ts"
import { test } from './fixtures';
test('passes', async ({ database, page, a11y }) => {
// use database and a11y fixtures.
});
```
### Merge custom expect matchers
You can now merge custom expect matchers from multiple files or modules:
```js title="fixtures.ts"
import { mergeTests, mergeExpects } from '@playwright/test';
import { test as dbTest, expect as dbExpect } from 'database-test-utils'; import { test as dbTest, expect as dbExpect } from 'database-test-utils';
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils'; import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
export const expect = composedExpect(dbExpect, a11yExpect); export const test = mergeTests(dbTest, a11yTest);
export const test = composedTest(dbTest, a11yTest); export const expect = mergeExpects(dbExpect, a11yExpect);
``` ```
```js title="test.spec.ts" ```js title="test.spec.ts"
import { test, expect } from './fixtures'; import { test, expect } from './fixtures';
test('passes', async ({ database, page }) => { test('passes', async ({ page, database }) => {
await expect(database).toHaveDatabaseUser('admin'); await expect(database).toHaveDatabaseUser('admin');
await expect(page).toPassA11yAudit(); await expect(page).toPassA11yAudit();
}); });
``` ```
### Boxed test steps ### Hide implementation details: box test steps
You can mark a [`method: Test.step`] as "boxed" so that errors inside it point to the step call site. You can mark a [`method: Test.step`] as "boxed" so that errors inside it point to the step call site.

View file

@ -6,7 +6,7 @@ toc_max_heading_level: 2
## Version 1.39 ## Version 1.39
Maintenance release. Evergreen browsers update.
### Browser Versions ### Browser Versions

View file

@ -217,12 +217,12 @@ Do not confuse Playwright's `expect` with the [`expect` library](https://jestjs.
You can combine custom matchers from multiple files or modules. You can combine custom matchers from multiple files or modules.
```js title="fixtures.ts" ```js title="fixtures.ts"
import { composedTest, composedExpect } from '@playwright/test'; import { mergeTests, mergeExpects } from '@playwright/test';
import { test as dbTest, expect as dbExpect } from 'database-test-utils'; import { test as dbTest, expect as dbExpect } from 'database-test-utils';
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils'; import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
export const expect = composedExpect(dbExpect, a11yExpect); export const expect = mergeExpects(dbExpect, a11yExpect);
export const test = composedTest(dbTest, a11yTest); export const test = mergeTests(dbTest, a11yTest);
``` ```
```js title="test.spec.ts" ```js title="test.spec.ts"

View file

@ -9,8 +9,8 @@ Playwright Test has multiple configurable timeouts for various tasks.
|Timeout |Default |Description | |Timeout |Default |Description |
|:----------|:----------------|:--------------------------------| |:----------|:----------------|:--------------------------------|
|Test timeout|30000 ms|Timeout for each test, includes test, hooks and fixtures:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { timeout: 60000 }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`test.setTimeout(120000)` | |Test timeout|30000 ms|Timeout for each test, includes test, hooks and fixtures:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set default</span><br/><code>{`config = { timeout: 60000 }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.7'}}>Override</span><br/>`test.setTimeout(120000)` |
|Expect timeout|5000 ms|Timeout for each assertion:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { expect: { timeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`expect(locator).toBeVisible({ timeout: 10000 })` | |Expect timeout|5000 ms|Timeout for each assertion:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set default</span><br/><code>{`config = { expect: { timeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.7'}}>Override</span><br/>`expect(locator).toBeVisible({ timeout: 10000 })` |
## Test timeout ## Test timeout
@ -144,11 +144,11 @@ If you happen to be in this section because your test are flaky, it is very like
|Timeout |Default |Description | |Timeout |Default |Description |
|:----------|:----------------|:--------------------------------| |:----------|:----------------|:--------------------------------|
|Action timeout| no timeout |Timeout for each action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { actionTimeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`locator.click({ timeout: 10000 })` | |Action timeout| no timeout |Timeout for each action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set default</span><br/><code>{`config = { use: { actionTimeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.7'}}>Override</span><br/>`locator.click({ timeout: 10000 })` |
|Navigation timeout| no timeout |Timeout for each navigation action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { navigationTimeout: 30000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`page.goto('/', { timeout: 30000 })` | |Navigation timeout| no timeout |Timeout for each navigation action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set default</span><br/><code>{`config = { use: { navigationTimeout: 30000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.7'}}>Override</span><br/>`page.goto('/', { timeout: 30000 })` |
|Global timeout|no timeout |Global timeout for the whole test run:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in config</span><br/>`config = { globalTimeout: 60*60*1000 }`<br/> | |Global timeout|no timeout |Global timeout for the whole test run:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set in config</span><br/>`config = { globalTimeout: 60*60*1000 }`<br/> |
|`beforeAll`/`afterAll` timeout|30000 ms|Timeout for the hook:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in hook</span><br/>`test.setTimeout(60000)`<br/> | |`beforeAll`/`afterAll` timeout|30000 ms|Timeout for the hook:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set in hook</span><br/>`test.setTimeout(60000)`<br/> |
|Fixture timeout|no timeout |Timeout for an individual fixture:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in fixture</span><br/>`{ scope: 'test', timeout: 30000 }`<br/> | |Fixture timeout|no timeout |Timeout for an individual fixture:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.7'}}>Set in fixture</span><br/>`{ scope: 'test', timeout: 30000 }`<br/> |
### Set timeout for a single assertion ### Set timeout for a single assertion

100
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.39.0-next", "version": "1.39.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
@ -7054,10 +7054,10 @@
} }
}, },
"packages/playwright": { "packages/playwright": {
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -7071,11 +7071,11 @@
}, },
"packages/playwright-browser-chromium": { "packages/playwright-browser-chromium": {
"name": "@playwright/browser-chromium", "name": "@playwright/browser-chromium",
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
@ -7083,11 +7083,11 @@
}, },
"packages/playwright-browser-firefox": { "packages/playwright-browser-firefox": {
"name": "@playwright/browser-firefox", "name": "@playwright/browser-firefox",
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
@ -7095,22 +7095,22 @@
}, },
"packages/playwright-browser-webkit": { "packages/playwright-browser-webkit": {
"name": "@playwright/browser-webkit", "name": "@playwright/browser-webkit",
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
} }
}, },
"packages/playwright-chromium": { "packages/playwright-chromium": {
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -7120,7 +7120,7 @@
} }
}, },
"packages/playwright-core": { "packages/playwright-core": {
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
@ -7131,11 +7131,11 @@
}, },
"packages/playwright-ct-core": { "packages/playwright-ct-core": {
"name": "@playwright/experimental-ct-core", "name": "@playwright/experimental-ct-core",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.39.0-next", "playwright": "1.39.0",
"playwright-core": "1.39.0-next", "playwright-core": "1.39.0",
"vite": "^4.4.10" "vite": "^4.4.10"
}, },
"bin": { "bin": {
@ -7147,10 +7147,10 @@
}, },
"packages/playwright-ct-react": { "packages/playwright-ct-react": {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"bin": { "bin": {
@ -7179,10 +7179,10 @@
}, },
"packages/playwright-ct-react17": { "packages/playwright-ct-react17": {
"name": "@playwright/experimental-ct-react17", "name": "@playwright/experimental-ct-react17",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"bin": { "bin": {
@ -7211,10 +7211,10 @@
}, },
"packages/playwright-ct-solid": { "packages/playwright-ct-solid": {
"name": "@playwright/experimental-ct-solid", "name": "@playwright/experimental-ct-solid",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"vite-plugin-solid": "^2.7.0" "vite-plugin-solid": "^2.7.0"
}, },
"bin": { "bin": {
@ -7229,10 +7229,10 @@
}, },
"packages/playwright-ct-svelte": { "packages/playwright-ct-svelte": {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@sveltejs/vite-plugin-svelte": "^2.1.1" "@sveltejs/vite-plugin-svelte": "^2.1.1"
}, },
"bin": { "bin": {
@ -7247,10 +7247,10 @@
}, },
"packages/playwright-ct-vue": { "packages/playwright-ct-vue": {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue": "^4.2.1" "@vitejs/plugin-vue": "^4.2.1"
}, },
"bin": { "bin": {
@ -7298,10 +7298,10 @@
}, },
"packages/playwright-ct-vue2": { "packages/playwright-ct-vue2": {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue2": "^2.2.0" "@vitejs/plugin-vue2": "^2.2.0"
}, },
"bin": { "bin": {
@ -7315,11 +7315,11 @@
} }
}, },
"packages/playwright-firefox": { "packages/playwright-firefox": {
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -7353,10 +7353,10 @@
}, },
"packages/playwright-test": { "packages/playwright-test": {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.39.0-next", "version": "1.39.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.39.0-next" "playwright": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -7366,11 +7366,11 @@
} }
}, },
"packages/playwright-webkit": { "packages/playwright-webkit": {
"version": "1.39.0-next", "version": "1.39.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8089,33 +8089,33 @@
"@playwright/browser-chromium": { "@playwright/browser-chromium": {
"version": "file:packages/playwright-browser-chromium", "version": "file:packages/playwright-browser-chromium",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"@playwright/browser-firefox": { "@playwright/browser-firefox": {
"version": "file:packages/playwright-browser-firefox", "version": "file:packages/playwright-browser-firefox",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"@playwright/browser-webkit": { "@playwright/browser-webkit": {
"version": "file:packages/playwright-browser-webkit", "version": "file:packages/playwright-browser-webkit",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"@playwright/experimental-ct-core": { "@playwright/experimental-ct-core": {
"version": "file:packages/playwright-ct-core", "version": "file:packages/playwright-ct-core",
"requires": { "requires": {
"playwright": "1.39.0-next", "playwright": "1.39.0",
"playwright-core": "1.39.0-next", "playwright-core": "1.39.0",
"vite": "^4.4.10" "vite": "^4.4.10"
} }
}, },
"@playwright/experimental-ct-react": { "@playwright/experimental-ct-react": {
"version": "file:packages/playwright-ct-react", "version": "file:packages/playwright-ct-react",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"dependencies": { "dependencies": {
@ -8135,7 +8135,7 @@
"@playwright/experimental-ct-react17": { "@playwright/experimental-ct-react17": {
"version": "file:packages/playwright-ct-react17", "version": "file:packages/playwright-ct-react17",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"dependencies": { "dependencies": {
@ -8155,7 +8155,7 @@
"@playwright/experimental-ct-solid": { "@playwright/experimental-ct-solid": {
"version": "file:packages/playwright-ct-solid", "version": "file:packages/playwright-ct-solid",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"solid-js": "^1.7.0", "solid-js": "^1.7.0",
"vite-plugin-solid": "^2.7.0" "vite-plugin-solid": "^2.7.0"
} }
@ -8163,7 +8163,7 @@
"@playwright/experimental-ct-svelte": { "@playwright/experimental-ct-svelte": {
"version": "file:packages/playwright-ct-svelte", "version": "file:packages/playwright-ct-svelte",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@sveltejs/vite-plugin-svelte": "^2.1.1", "@sveltejs/vite-plugin-svelte": "^2.1.1",
"svelte": "^3.55.1" "svelte": "^3.55.1"
} }
@ -8171,7 +8171,7 @@
"@playwright/experimental-ct-vue": { "@playwright/experimental-ct-vue": {
"version": "file:packages/playwright-ct-vue", "version": "file:packages/playwright-ct-vue",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue": "^4.2.1" "@vitejs/plugin-vue": "^4.2.1"
}, },
"dependencies": { "dependencies": {
@ -8205,7 +8205,7 @@
"@playwright/experimental-ct-vue2": { "@playwright/experimental-ct-vue2": {
"version": "file:packages/playwright-ct-vue2", "version": "file:packages/playwright-ct-vue2",
"requires": { "requires": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue2": "^2.2.0", "@vitejs/plugin-vue2": "^2.2.0",
"vue": "^2.7.14" "vue": "^2.7.14"
} }
@ -8213,7 +8213,7 @@
"@playwright/test": { "@playwright/test": {
"version": "file:packages/playwright-test", "version": "file:packages/playwright-test",
"requires": { "requires": {
"playwright": "1.39.0-next" "playwright": "1.39.0"
} }
}, },
"@sindresorhus/is": { "@sindresorhus/is": {
@ -11081,13 +11081,13 @@
"version": "file:packages/playwright", "version": "file:packages/playwright",
"requires": { "requires": {
"fsevents": "2.3.2", "fsevents": "2.3.2",
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"playwright-chromium": { "playwright-chromium": {
"version": "file:packages/playwright-chromium", "version": "file:packages/playwright-chromium",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"playwright-core": { "playwright-core": {
@ -11096,13 +11096,13 @@
"playwright-firefox": { "playwright-firefox": {
"version": "file:packages/playwright-firefox", "version": "file:packages/playwright-firefox",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"playwright-webkit": { "playwright-webkit": {
"version": "file:packages/playwright-webkit", "version": "file:packages/playwright-webkit",
"requires": { "requires": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
}, },
"postcss": { "postcss": {

View file

@ -1,7 +1,7 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"private": true, "private": true,
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-chromium", "name": "@playwright/browser-chromium",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright package that automatically installs Chromium", "description": "Playwright package that automatically installs Chromium",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-firefox", "name": "@playwright/browser-firefox",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright package that automatically installs Firefox", "description": "Playwright package that automatically installs Firefox",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-webkit", "name": "@playwright/browser-webkit",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright package that automatically installs WebKit", "description": "Playwright package that automatically installs WebKit",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-chromium", "name": "playwright-chromium",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate Chromium", "description": "A high-level API to automate Chromium",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-core", "name": "playwright-core",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-core", "name": "@playwright/experimental-ct-core",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing Helpers", "description": "Playwright Component Testing Helpers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,9 +27,9 @@
} }
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next", "playwright-core": "1.39.0",
"vite": "^4.4.10", "vite": "^4.4.10",
"playwright": "1.39.0-next" "playwright": "1.39.0"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for React", "description": "Playwright Component Testing for React",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-react17", "name": "@playwright/experimental-ct-react17",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for React", "description": "Playwright Component Testing for React",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-react": "^4.0.0" "@vitejs/plugin-react": "^4.0.0"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-solid", "name": "@playwright/experimental-ct-solid",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for Solid", "description": "Playwright Component Testing for Solid",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"vite-plugin-solid": "^2.7.0" "vite-plugin-solid": "^2.7.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for Svelte", "description": "Playwright Component Testing for Svelte",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@sveltejs/vite-plugin-svelte": "^2.1.1" "@sveltejs/vite-plugin-svelte": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for Vue", "description": "Playwright Component Testing for Vue",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue": "^4.2.1" "@vitejs/plugin-vue": "^4.2.1"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.39.0-next", "version": "1.39.0",
"description": "Playwright Component Testing for Vue2", "description": "Playwright Component Testing for Vue2",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.39.0-next", "@playwright/experimental-ct-core": "1.39.0",
"@vitejs/plugin-vue2": "^2.2.0" "@vitejs/plugin-vue2": "^2.2.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-firefox", "name": "playwright-firefox",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate Firefox", "description": "A high-level API to automate Firefox",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
}, },
"scripts": {}, "scripts": {},
"dependencies": { "dependencies": {
"playwright": "1.39.0-next" "playwright": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-webkit", "name": "playwright-webkit",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate WebKit", "description": "A high-level API to automate WebKit",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright", "name": "playwright",
"version": "1.39.0-next", "version": "1.39.0",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -54,7 +54,7 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.39.0-next" "playwright-core": "1.39.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"fsevents": "2.3.2" "fsevents": "2.3.2"

View file

@ -230,7 +230,7 @@ export class TestTypeImpl {
private _extend(location: Location, fixtures: Fixtures) { private _extend(location: Location, fixtures: Fixtures) {
if ((fixtures as any)[testTypeSymbol]) if ((fixtures as any)[testTypeSymbol])
throw new Error(`test.extend() accepts fixtures object, not a test object.\nDid you mean to call composedTest()?`); throw new Error(`test.extend() accepts fixtures object, not a test object.\nDid you mean to call mergeTests()?`);
const fixturesWithLocation: FixturesWithLocation = { fixtures, location }; const fixturesWithLocation: FixturesWithLocation = { fixtures, location };
return new TestTypeImpl([...this.fixtures, fixturesWithLocation]).test; return new TestTypeImpl([...this.fixtures, fixturesWithLocation]).test;
} }
@ -249,12 +249,12 @@ function throwIfRunningInsideJest() {
export const rootTestType = new TestTypeImpl([]); export const rootTestType = new TestTypeImpl([]);
export function composedTest(...tests: TestType<any, any>[]) { export function mergeTests(...tests: TestType<any, any>[]) {
let result = rootTestType; let result = rootTestType;
for (const t of tests) { for (const t of tests) {
const testTypeImpl = (t as any)[testTypeSymbol] as TestTypeImpl; const testTypeImpl = (t as any)[testTypeSymbol] as TestTypeImpl;
if (!testTypeImpl) if (!testTypeImpl)
throw new Error(`composedTest() accepts "test" functions as parameters.\nDid you mean to call test.extend() with fixtures instead?`); throw new Error(`mergeTests() accepts "test" functions as parameters.\nDid you mean to call test.extend() with fixtures instead?`);
// Filter out common ancestor fixtures. // Filter out common ancestor fixtures.
const newFixtures = testTypeImpl.fixtures.filter(theirs => !result.fixtures.find(ours => ours.fixtures === theirs.fixtures)); const newFixtures = testTypeImpl.fixtures.filter(theirs => !result.fixtures.find(ours => ours.fixtures === theirs.fixtures));
result = new TestTypeImpl([...result.fixtures, ...newFixtures]); result = new TestTypeImpl([...result.fixtures, ...newFixtures]);

View file

@ -744,7 +744,7 @@ function renderApiCall(apiName: string, params: any) {
export const test = _baseTest.extend<TestFixtures, WorkerFixtures>(playwrightFixtures); export const test = _baseTest.extend<TestFixtures, WorkerFixtures>(playwrightFixtures);
export { defineConfig } from './common/configLoader'; export { defineConfig } from './common/configLoader';
export { composedTest } from './common/testType'; export { mergeTests } from './common/testType';
export { composedExpect } from './matchers/expect'; export { mergeExpects } from './matchers/expect';
export default test; export default test;

View file

@ -338,6 +338,6 @@ function computeArgsSuffix(matcherName: string, args: any[]) {
expectLibrary.extend(customMatchers); expectLibrary.extend(customMatchers);
export function composedExpect(...expects: any[]) { export function mergeExpects(...expects: any[]) {
return expect; return expect;
} }

View file

@ -28,4 +28,6 @@ export const _android = playwright._android;
export const test = playwright.test; export const test = playwright.test;
export const expect = playwright.expect; export const expect = playwright.expect;
export const defineConfig = playwright.defineConfig; export const defineConfig = playwright.defineConfig;
export const mergeTests = playwright.mergeTests;
export const mergeExpects = playwright.mergeExpects;
export default playwright.test; export default playwright.test;

View file

@ -5328,7 +5328,7 @@ type MergedTestType<List> = TestType<MergedT<List>, MergedW<List>>;
/** /**
* Merges fixtures * Merges fixtures
*/ */
export function composedTest<List extends any[]>(...tests: List): MergedTestType<List>; export function mergeTests<List extends any[]>(...tests: List): MergedTestType<List>;
type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {}; type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {};
type MergedExpect<List> = Expect<MergedExpectMatchers<List>>; type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
@ -5336,7 +5336,7 @@ type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
/** /**
* Merges expects * Merges expects
*/ */
export function composedExpect<List extends any[]>(...expects: List): MergedExpect<List>; export function mergeExpects<List extends any[]>(...expects: List): MergedExpect<List>;
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459 // This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
export {}; export {};

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { composedTest } from '@playwright/test'; import { mergeTests } from '@playwright/test';
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import type { CommonFixtures, CommonWorkerFixtures } from './commonFixtures'; import type { CommonFixtures, CommonWorkerFixtures } from './commonFixtures';
import { commonFixtures } from './commonFixtures'; import { commonFixtures } from './commonFixtures';
@ -26,7 +26,7 @@ import { testModeTest } from './testModeFixtures';
export const base = test; export const base = test;
export const baseTest = composedTest(base, coverageTest, platformTest, testModeTest) export const baseTest = mergeTests(base, coverageTest, platformTest, testModeTest)
.extend<CommonFixtures, CommonWorkerFixtures>(commonFixtures) .extend<CommonFixtures, CommonWorkerFixtures>(commonFixtures)
.extend<ServerFixtures, ServerWorkerOptions>(serverFixtures); .extend<ServerFixtures, ServerWorkerOptions>(serverFixtures);

View file

@ -1,9 +1,9 @@
import { test as test1, expect as expect1, composedTest, composedExpect } from '@playwright/test'; import { test as test1, expect as expect1, mergeTests, mergeExpects } from '@playwright/test';
import type { Page } from '@playwright/test'; import type { Page } from '@playwright/test';
import { test as test2, expect as expect2 } from 'playwright-test-plugin'; import { test as test2, expect as expect2 } from 'playwright-test-plugin';
const test = composedTest(test1, test2); const test = mergeTests(test1, test2);
const expect = composedExpect(expect1, expect2); const expect = mergeExpects(expect1, expect2);
test('sample test', async ({ page, plugin }) => { test('sample test', async ({ page, plugin }) => {
type IsPage = (typeof page) extends Page ? true : never; type IsPage = (typeof page) extends Page ? true : never;

View file

@ -1,8 +1,8 @@
import { test as test1, expect as expect1, composedTest, composedExpect } from '@playwright/test'; import { test as test1, expect as expect1, mergeTests, mergeExpects } from '@playwright/test';
import { test as test2, expect as expect2 } from 'playwright-test-plugin'; import { test as test2, expect as expect2 } from 'playwright-test-plugin';
const test = composedTest(test1, test2); const test = mergeTests(test1, test2);
const expect = composedExpect(expect1, expect2); const expect = mergeExpects(expect1, expect2);
test('sample test', async ({ page, plugin }) => { test('sample test', async ({ page, plugin }) => {
await page.setContent(`<div>hello</div><span>world</span>`); await page.setContent(`<div>hello</div><span>world</span>`);

View file

@ -632,3 +632,43 @@ test('should be able to use use execSync with a Node.js file inside a spec', asy
'fork: hello from hellofork.js', 'fork: hello from hellofork.js',
]); ]);
}); });
test('should be able to use mergeTests/mergeExpect', async ({ runInlineTest }) => {
const result = await runInlineTest({
'a.test.mjs': `
import { test as base, expect as baseExpect, mergeTests, mergeExpects } from '@playwright/test';
const test = mergeTests(
base.extend({
myFixture1: '1',
}),
base.extend({
myFixture2: '2',
}),
);
const expect = mergeExpects(
baseExpect.extend({
async toBeFoo1(page, x) {
return { pass: true, message: () => '' };
}
}),
baseExpect.extend({
async toBeFoo2(page, x) {
return { pass: true, message: () => '' };
}
}),
);
test('merged', async ({ myFixture1, myFixture2 }) => {
console.log('%%myFixture1: ' + myFixture1);
console.log('%%myFixture2: ' + myFixture2);
await expect(1).toBeFoo1();
await expect(1).toBeFoo2();
});
`,
});
expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1);
expect(result.outputLines).toContain('myFixture1: 1');
expect(result.outputLines).toContain('myFixture2: 2');
});

View file

@ -879,10 +879,10 @@ test('should suppport toHaveAttribute without optional value', async ({ runTSC }
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
}); });
test('should support composedExpect (TSC)', async ({ runTSC }) => { test('should support mergeExpects (TSC)', async ({ runTSC }) => {
const result = await runTSC({ const result = await runTSC({
'a.spec.ts': ` 'a.spec.ts': `
import { test, composedExpect, expect as baseExpect } from '@playwright/test'; import { test, mergeExpects, expect as baseExpect } from '@playwright/test';
import type { Page } from '@playwright/test'; import type { Page } from '@playwright/test';
const expect1 = baseExpect.extend({ const expect1 = baseExpect.extend({
@ -897,7 +897,7 @@ test('should support composedExpect (TSC)', async ({ runTSC }) => {
} }
}); });
const expect = composedExpect(expect1, expect2); const expect = mergeExpects(expect1, expect2);
test('custom matchers', async ({ page }) => { test('custom matchers', async ({ page }) => {
await expect(page).toBeAGoodPage(123); await expect(page).toBeAGoodPage(123);
@ -914,10 +914,10 @@ test('should support composedExpect (TSC)', async ({ runTSC }) => {
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
}); });
test('should support composedExpect', async ({ runInlineTest }) => { test('should support mergeExpects', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
'a.spec.ts': ` 'a.spec.ts': `
import { test, composedExpect, expect as baseExpect } from '@playwright/test'; import { test, mergeExpects, expect as baseExpect } from '@playwright/test';
import type { Page } from '@playwright/test'; import type { Page } from '@playwright/test';
const expect1 = baseExpect.extend({ const expect1 = baseExpect.extend({
@ -932,7 +932,7 @@ test('should support composedExpect', async ({ runInlineTest }) => {
} }
}); });
const expect = composedExpect(expect1, expect2); const expect = mergeExpects(expect1, expect2);
test('custom matchers', async ({ page }) => { test('custom matchers', async ({ page }) => {
await expect(page).toBeAGoodPage(123); await expect(page).toBeAGoodPage(123);

View file

@ -160,7 +160,7 @@ test('config should override options but not fixtures', async ({ runInlineTest }
expect(result.output).toContain('fixture-config-fixture'); expect(result.output).toContain('fixture-config-fixture');
}); });
test('composedTest should be able to merge', async ({ runInlineTest }) => { test('mergeTests should be able to merge', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
'playwright.config.ts': ` 'playwright.config.ts': `
module.exports = { module.exports = {
@ -168,7 +168,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
}; };
`, `,
'a.test.ts': ` 'a.test.ts': `
import { test, expect, composedTest } from '@playwright/test'; import { test, expect, mergeTests } from '@playwright/test';
const base = test.extend({ const base = test.extend({
myFixture: 'abc', myFixture: 'abc',
}); });
@ -184,7 +184,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
fixture2: ({}, use) => use('fixture2'), fixture2: ({}, use) => use('fixture2'),
}); });
const test3 = composedTest(test1, test2); const test3 = mergeTests(test1, test2);
test3('merged', async ({ param, fixture1, myFixture, fixture2 }) => { test3('merged', async ({ param, fixture1, myFixture, fixture2 }) => {
console.log('param-' + param); console.log('param-' + param);
@ -202,7 +202,7 @@ test('composedTest should be able to merge', async ({ runInlineTest }) => {
expect(result.output).toContain('fixture2-fixture2'); expect(result.output).toContain('fixture2-fixture2');
}); });
test('test.extend should print nice message when used as composedTest', async ({ runInlineTest }) => { test('test.extend should print nice message when used as mergeTests', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
'a.test.ts': ` 'a.test.ts': `
import { test as base, expect } from '@playwright/test'; import { test as base, expect } from '@playwright/test';
@ -215,14 +215,14 @@ test('test.extend should print nice message when used as composedTest', async ({
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0); expect(result.passed).toBe(0);
expect(result.output).toContain('Did you mean to call composedTest()?'); expect(result.output).toContain('Did you mean to call mergeTests()?');
}); });
test('composedTest should print nice message when used as extend', async ({ runInlineTest }) => { test('mergeTests should print nice message when used as extend', async ({ runInlineTest }) => {
const result = await runInlineTest({ const result = await runInlineTest({
'a.test.ts': ` 'a.test.ts': `
import { test as base, expect, composedTest } from '@playwright/test'; import { test as base, expect, mergeTests } from '@playwright/test';
const test3 = composedTest(base, {}); const test3 = mergeTests(base, {});
test3('test', () => {}); test3('test', () => {});
`, `,
}); });

View file

@ -84,7 +84,7 @@ test('can return anything from hooks', async ({ runTSC }) => {
test('test.extend options should check types', async ({ runTSC }) => { test('test.extend options should check types', async ({ runTSC }) => {
const result = await runTSC({ const result = await runTSC({
'helper.ts': ` 'helper.ts': `
import { test as base, expect, composedTest } from '@playwright/test'; import { test as base, expect, mergeTests } from '@playwright/test';
export type Params = { foo: string }; export type Params = { foo: string };
export const test = base; export const test = base;
export const test1 = test.extend<Params>({ foo: [ 'foo', { option: true } ] }); export const test1 = test.extend<Params>({ foo: [ 'foo', { option: true } ] });
@ -100,7 +100,7 @@ test('test.extend options should check types', async ({ runTSC }) => {
// @ts-expect-error // @ts-expect-error
bar: async ({ baz }, run) => { await run(42); } bar: async ({ baz }, run) => { await run(42); }
}); });
export const test4 = composedTest(test1, testW); export const test4 = mergeTests(test1, testW);
const test5 = test4.extend<{}, { hey: string, hey2: string }>({ const test5 = test4.extend<{}, { hey: string, hey2: string }>({
// @ts-expect-error // @ts-expect-error
hey: [async ({ foo }, use) => { hey: [async ({ foo }, use) => {

View file

@ -462,7 +462,7 @@ type MergedTestType<List> = TestType<MergedT<List>, MergedW<List>>;
/** /**
* Merges fixtures * Merges fixtures
*/ */
export function composedTest<List extends any[]>(...tests: List): MergedTestType<List>; export function mergeTests<List extends any[]>(...tests: List): MergedTestType<List>;
type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {}; type MergedExpectMatchers<List> = List extends [Expect<infer M>, ...(infer Rest)] ? M & MergedExpectMatchers<Rest> : {};
type MergedExpect<List> = Expect<MergedExpectMatchers<List>>; type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
@ -470,7 +470,7 @@ type MergedExpect<List> = Expect<MergedExpectMatchers<List>>;
/** /**
* Merges expects * Merges expects
*/ */
export function composedExpect<List extends any[]>(...expects: List): MergedExpect<List>; export function mergeExpects<List extends any[]>(...expects: List): MergedExpect<List>;
// This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459 // This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459
export {}; export {};