Skip to content

Commit ed35447

Browse files
Merge pull request microsoft#1 from microsoft/main
Sync with source
2 parents f2d57b8 + 1aee48f commit ed35447

25 files changed

+578
-367
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# 🎭 Playwright
22

3-
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-120.0.6099.5-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-119.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
3+
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-120.0.6099.18-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-119.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
44

55
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
66

77
Playwright is a framework for Web Testing and Automation. It allows testing [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**.
88

99
| | Linux | macOS | Windows |
1010
| :--- | :---: | :---: | :---: |
11-
| Chromium <!-- GEN:chromium-version -->120.0.6099.5<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
11+
| Chromium <!-- GEN:chromium-version -->120.0.6099.18<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1212
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1313
| Firefox <!-- GEN:firefox-version -->119.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
1414

docs/src/release-notes-js.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ test('pass', async ({ page }) => {
3030
});
3131
```
3232

33-
See the documentation [for a full example](./test-configuration.md#add-custom-matchers-using-expectextend).
33+
See the documentation [for a full example](./test-assertions.md#add-custom-matchers-using-expectextend).
3434

3535
### Merge test fixtures
3636

docs/src/test-assertions-js.md

+86-3
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Prefer [auto-retrying](#auto-retrying-assertions) assertions whenever possible.
9494
| [`method: GenericAssertions.stringContaining`] | String contains a substring |
9595
| [`method: GenericAssertions.stringMatching`] | String matches a regular expression |
9696

97-
## Negating Matchers
97+
## Negating matchers
9898

9999
In general, we can expect the opposite to be true by adding a `.not` to the front
100100
of the matchers:
@@ -104,7 +104,7 @@ expect(value).not.toEqual(0);
104104
await expect(locator).not.toContainText('some text');
105105
```
106106

107-
## Soft Assertions
107+
## Soft assertions
108108

109109
By default, failed assertion will terminate test execution. Playwright also
110110
supports *soft assertions*: failed soft assertions **do not** terminate test execution,
@@ -134,7 +134,7 @@ expect(test.info().errors).toHaveLength(0);
134134

135135
Note that soft assertions only work with Playwright test runner.
136136

137-
## Custom Expect Message
137+
## Custom expect message
138138

139139
You can specify a custom error message as a second argument to the `expect` function, for example:
140140

@@ -236,3 +236,86 @@ await expect(async () => {
236236
timeout: 60_000
237237
});
238238
```
239+
240+
## Add custom matchers using expect.extend
241+
242+
You can extend Playwright assertions by providing custom matchers. These matchers will be available on the `expect` object.
243+
244+
In this example we add a custom `toHaveAmount` function. Custom matcher should return a `message` callback and a `pass` flag indicating whether the assertion passed.
245+
246+
```js title="fixtures.ts"
247+
import { expect as baseExpect } from '@playwright/test';
248+
import type { Page, Locator } from '@playwright/test';
249+
250+
export { test } from '@playwright/test';
251+
252+
export const expect = baseExpect.extend({
253+
async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
254+
const assertionName = 'toHaveAmount';
255+
let pass: boolean;
256+
let matcherResult: any;
257+
try {
258+
await baseExpect(locator).toHaveAttribute('data-amount', String(expected), options);
259+
pass = true;
260+
} catch (e: any) {
261+
matcherResult = e.matcherResult;
262+
pass = false;
263+
}
264+
265+
const message = pass
266+
? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
267+
'\n\n' +
268+
`Locator: ${locator}\n` +
269+
`Expected: ${this.isNot ? 'not' : ''}${this.utils.printExpected(expected)}\n` +
270+
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '')
271+
: () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
272+
'\n\n' +
273+
`Locator: ${locator}\n` +
274+
`Expected: ${this.utils.printExpected(expected)}\n` +
275+
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '');
276+
277+
return {
278+
message,
279+
pass,
280+
name: assertionName,
281+
expected,
282+
actual: matcherResult?.actual,
283+
};
284+
},
285+
});
286+
```
287+
288+
Now we can use `toHaveAmount` in the test.
289+
290+
```js title="example.spec.ts"
291+
import { test, expect } from './fixtures';
292+
293+
test('amount', async () => {
294+
await expect(page.locator('.cart')).toHaveAmount(4);
295+
});
296+
```
297+
298+
:::note
299+
Do not confuse Playwright's `expect` with the [`expect` library](https://jestjs.io/docs/expect). The latter is not fully integrated with Playwright test runner, so make sure to use Playwright's own `expect`.
300+
:::
301+
302+
### Combine custom matchers from multiple modules
303+
304+
You can combine custom matchers from multiple files or modules.
305+
306+
```js title="fixtures.ts"
307+
import { mergeTests, mergeExpects } from '@playwright/test';
308+
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
309+
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
310+
311+
export const expect = mergeExpects(dbExpect, a11yExpect);
312+
export const test = mergeTests(dbTest, a11yTest);
313+
```
314+
315+
```js title="test.spec.ts"
316+
import { test, expect } from './fixtures';
317+
318+
test('passes', async ({ database }) => {
319+
await expect(database).toHaveDatabaseUser('admin');
320+
});
321+
```

docs/src/test-configuration-js.md

-83
Original file line numberDiff line numberDiff line change
@@ -150,86 +150,3 @@ export default defineConfig({
150150
| [`method: PageAssertions.toHaveScreenshot#1`] | Configuration for the `expect(locator).toHaveScreeshot()` method. |
151151
| [`method: SnapshotAssertions.toMatchSnapshot#1`]| Configuration for the `expect(locator).toMatchSnapshot()` method.|
152152

153-
154-
### Add custom matchers using expect.extend
155-
156-
You can extend Playwright assertions by providing custom matchers. These matchers will be available on the `expect` object.
157-
158-
In this example we add a custom `toHaveAmount` function. Custom matcher should return a `message` callback and a `pass` flag indicating whether the assertion passed.
159-
160-
```js title="fixtures.ts"
161-
import { expect as baseExpect } from '@playwright/test';
162-
import type { Page, Locator } from '@playwright/test';
163-
164-
export { test } from '@playwright/test';
165-
166-
export const expect = baseExpect.extend({
167-
async toHaveAmount(locator: Locator, expected: number, options?: { timeout?: number }) {
168-
const assertionName = 'toHaveAmount';
169-
let pass: boolean;
170-
let matcherResult: any;
171-
try {
172-
await baseExpect(locator).toHaveAttribute('data-amount', String(expected), options);
173-
pass = true;
174-
} catch (e: any) {
175-
matcherResult = e.matcherResult;
176-
pass = false;
177-
}
178-
179-
const message = pass
180-
? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
181-
'\n\n' +
182-
`Locator: ${locator}\n` +
183-
`Expected: ${this.isNot ? 'not' : ''}${this.utils.printExpected(expected)}\n` +
184-
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '')
185-
: () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) +
186-
'\n\n' +
187-
`Locator: ${locator}\n` +
188-
`Expected: ${this.utils.printExpected(expected)}\n` +
189-
(matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '');
190-
191-
return {
192-
message,
193-
pass,
194-
name: assertionName,
195-
expected,
196-
actual: matcherResult?.actual,
197-
};
198-
},
199-
});
200-
```
201-
202-
Now we can use `toHaveAmount` in the test.
203-
204-
```js title="example.spec.ts"
205-
import { test, expect } from './fixtures';
206-
207-
test('amount', async () => {
208-
await expect(page.locator('.cart')).toHaveAmount(4);
209-
});
210-
```
211-
212-
:::note
213-
Do not confuse Playwright's `expect` with the [`expect` library](https://jestjs.io/docs/expect). The latter is not fully integrated with Playwright test runner, so make sure to use Playwright's own `expect`.
214-
:::
215-
216-
### Combine custom matchers from multiple modules
217-
218-
You can combine custom matchers from multiple files or modules.
219-
220-
```js title="fixtures.ts"
221-
import { mergeTests, mergeExpects } from '@playwright/test';
222-
import { test as dbTest, expect as dbExpect } from 'database-test-utils';
223-
import { test as a11yTest, expect as a11yExpect } from 'a11y-test-utils';
224-
225-
export const expect = mergeExpects(dbExpect, a11yExpect);
226-
export const test = mergeTests(dbTest, a11yTest);
227-
```
228-
229-
```js title="test.spec.ts"
230-
import { test, expect } from './fixtures';
231-
232-
test('passes', async ({ database }) => {
233-
await expect(database).toHaveDatabaseUser('admin');
234-
});
235-
```

packages/playwright-core/browsers.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
"browsers": [
44
{
55
"name": "chromium",
6-
"revision": "1089",
6+
"revision": "1090",
77
"installByDefault": true,
8-
"browserVersion": "120.0.6099.5"
8+
"browserVersion": "120.0.6099.18"
99
},
1010
{
1111
"name": "chromium-with-symbols",
12-
"revision": "1089",
12+
"revision": "1090",
1313
"installByDefault": false,
14-
"browserVersion": "120.0.6099.5"
14+
"browserVersion": "120.0.6099.18"
1515
},
1616
{
1717
"name": "chromium-tip-of-tree",
18-
"revision": "1166",
18+
"revision": "1167",
1919
"installByDefault": false,
20-
"browserVersion": "121.0.6113.0"
20+
"browserVersion": "121.0.6117.0"
2121
},
2222
{
2323
"name": "firefox",
@@ -39,7 +39,7 @@
3939
},
4040
{
4141
"name": "webkit",
42-
"revision": "1932",
42+
"revision": "1942",
4343
"installByDefault": true,
4444
"revisionOverrides": {
4545
"mac10.14": "1446",

packages/playwright-core/src/client/android.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,10 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
274274

275275
async launchBrowser(options: types.BrowserContextOptions & { pkg?: string } = {}): Promise<BrowserContext> {
276276
const contextOptions = await prepareBrowserContextParams(options);
277-
const { context } = await this._channel.launchBrowser(contextOptions);
278-
return BrowserContext.from(context) as BrowserContext;
277+
const result = await this._channel.launchBrowser(contextOptions);
278+
const context = BrowserContext.from(result.context) as BrowserContext;
279+
context._setOptions(contextOptions, {});
280+
return context;
279281
}
280282

281283
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {

packages/playwright-core/src/client/page.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { Keyboard, Mouse, Touchscreen } from './input';
4242
import { assertMaxArguments, JSHandle, parseResult, serializeArgument } from './jsHandle';
4343
import type { FrameLocator, Locator, LocatorOptions } from './locator';
4444
import type { ByRoleOptions } from '../utils/isomorphic/locatorUtils';
45+
import { trimStringWithEllipsis } from '../utils/isomorphic/stringUtils';
4546
import { type RouteHandlerCallback, type Request, Response, Route, RouteHandler, validateHeaders, WebSocket } from './network';
4647
import type { FilePayload, Headers, LifecycleEvent, SelectOption, SelectOptionOptions, Size, URLMatch, WaitForEventOptions, WaitForFunctionOptions } from './types';
4748
import { Video } from './video';
@@ -751,15 +752,9 @@ export class BindingCall extends ChannelOwner<channels.BindingCallChannel> {
751752
}
752753
}
753754

754-
function trimEnd(s: string): string {
755-
if (s.length > 50)
756-
s = s.substring(0, 50) + '\u2026';
757-
return s;
758-
}
759-
760755
function trimUrl(param: any): string | undefined {
761756
if (isRegExp(param))
762-
return `/${trimEnd(param.source)}/${param.flags}`;
757+
return `/${trimStringWithEllipsis(param.source, 50)}/${param.flags}`;
763758
if (isString(param))
764-
return `"${trimEnd(param)}"`;
759+
return `"${trimStringWithEllipsis(param, 50)}"`;
765760
}

packages/playwright-core/src/server/chromium/protocol.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ Should be updated alongside RequestIdTokenStatus in
878878
third_party/blink/public/mojom/devtools/inspector_issue.mojom to include
879879
all cases except for success.
880880
*/
881-
export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"DisabledInSettings"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp";
881+
export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"DisabledInSettings"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp";
882882
export interface FederatedAuthUserInfoRequestIssueDetails {
883883
federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason;
884884
}

0 commit comments

Comments
 (0)