From bb5e44fbc48e84ed1f740ae9209148a3ab8ebc52 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 27 Aug 2021 21:57:40 -0700 Subject: [PATCH] docs: introduce overloads, generate JSDoc for overloads (#8485) - Each overload, e.g. for `page.evaluate`, shows a nice autocomplete doc, not only the first one. - We can have multiple overloads directly on the docs page, e.g. `test.skip(title, fn)` and `test.skip(condition, description)`. These overloads are internally named `Test.skip#1` and all aliased to `test.skip`. --- docs/src/test-api/class-test.md | 142 ++- docs/src/test-api/class-testinfo.md | 4 +- docs/src/test-reporter-api/class-testcase.md | 2 +- types/test.d.ts | 1144 ++++++++++++++++- types/testReporter.d.ts | 3 +- types/types.d.ts | 1185 ++++++++++++++++++ utils/doclint/api_parser.js | 2 +- utils/doclint/documentation.js | 6 + utils/generate_types/index.js | 11 +- utils/generate_types/overrides-test.d.ts | 6 +- utils/generate_types/parseOverrides.js | 17 +- 11 files changed, 2441 insertions(+), 81 deletions(-) diff --git a/docs/src/test-api/class-test.md b/docs/src/test-api/class-test.md index e3a1aeabce..482fd140d8 100644 --- a/docs/src/test-api/class-test.md +++ b/docs/src/test-api/class-test.md @@ -599,12 +599,9 @@ Timeout in milliseconds. +## method: Test.skip#1 -## method: Test.skip - -Skips a test or a group of tests. - -Unconditionally skip a test, this is similar syntax to [`method: Test.(call)`]: +Declares a skipped test, similarly to [`method: Test.(call)`]. Skipped test is never run. ```js js-flavor=js const { test, expect } = require('@playwright/test'); @@ -622,7 +619,72 @@ test.skip('broken test', async ({ page }) => { }); ``` -Conditionally skip a test with an optional description. In this case, call `test.skip()` inside the test function: +### param: Test.skip#1.title +- `title` <[string]> + +Test title. + +### param: Test.skip#1.testFunction +- `testFunction` <[function]\([Fixtures], [TestInfo]\)> + +Test function that takes one or two arguments: an object with fixtures and optional [TestInfo]. + + + +## method: Test.skip#2 + +Unconditionally skip a test. Test is immediately aborted when you call [`method: Test.skip#2`]. + +```js js-flavor=js +const { test, expect } = require('@playwright/test'); + +test('skipped test', async ({ page }) => { + test.skip(); + // ... +}); +``` + +```js js-flavor=ts +import { test, expect } from '@playwright/test'; + +test('skipped test', async ({ page }) => { + test.skip(); + // ... +}); +``` + +Unconditionally skip all tests in a file or [`method: Test.describe`] group: + +```js js-flavor=js +const { test, expect } = require('@playwright/test'); + +test.skip(); + +test('skipped test 1', async ({ page }) => { + // ... +}); +test('skipped test 2', async ({ page }) => { + // ... +}); +``` + +```js js-flavor=ts +import { test, expect } from '@playwright/test'; + +test.skip(); + +test('skipped test 1', async ({ page }) => { + // ... +}); +test('skipped test 2', async ({ page }) => { + // ... +}); +``` + + +## method: Test.skip#3 + +Conditionally skip a test with an optional description. ```js js-flavor=js const { test, expect } = require('@playwright/test'); @@ -642,7 +704,42 @@ test('skip in WebKit', async ({ page, browserName }) => { }); ``` -Conditionally skip all tests in a file or [`method: Test.describe`] group: +Skip from [`method: Test.beforeEach`] hook: + +```js js-flavor=js +const { test, expect } = require('@playwright/test'); + +test.beforeEach(async ({ page }) => { + test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1'); + await page.goto('/settings'); +}); +``` + +```js js-flavor=ts +import { test, expect } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1'); + await page.goto('/settings'); +}); +``` + +### param: Test.skip#3.condition +- `condition` <[boolean]> + +A skip condition. Test or tests are skipped when the condition is `true`. + +### param: Test.skip#3.description +- `description` <[void]|[string]> + +An optional description that will be reflected in a test report. + + + + +## method: Test.skip#4 + +Conditionally skips all tests in a file or [`method: Test.describe`] group. ```js js-flavor=js const { test, expect } = require('@playwright/test'); @@ -670,35 +767,16 @@ test('skip in WebKit 2', async ({ page }) => { }); ``` -Skip from a hook: -```js js-flavor=js -const { test, expect } = require('@playwright/test'); +### param: Test.skip#4.condition +- `callback` <[function]\([Fixtures]\):[boolean]> -test.beforeEach(async ({ page }) => { - test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1'); - await page.goto('/settings'); -}); -``` +A function that returns whether to skip, based on test fixtures. Test or tests are skipped when the return value is `true`. -```js js-flavor=ts -import { test, expect } from '@playwright/test'; +### param: Test.skip#4.description +- `description` <[void]|[string]> -test.beforeEach(async ({ page }) => { - test.skip(process.env.APP_VERSION === 'v1', 'There are no settings in v1'); - await page.goto('/settings'); -}); -``` - -### param: Test.skip.condition -- `titleOrCondition` <[string]|[void]|[boolean]|[function]\([Fixtures]\):[boolean]> - -When used with `test.skip('test', () => {})` notation, first argument is a test title. Otherwise it is an optional skip condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are skipped when the condition is `true`. - -### param: Test.skip.description -- `testFunctionOrDescription` <[function]\([Fixtures], [TestInfo]\)|[void]|[string]> - -When used with `test.skip('test', () => {})` notation, second argument is a test function. Otherwise it is an optional description that will be reflected in a test report. +An optional description that will be reflected in a test report. diff --git a/docs/src/test-api/class-testinfo.md b/docs/src/test-api/class-testinfo.md index 3545908af1..2a1a23ece4 100644 --- a/docs/src/test-api/class-testinfo.md +++ b/docs/src/test-api/class-testinfo.md @@ -97,7 +97,7 @@ An error thrown during test execution, if any. - type: <[TestStatus]<"passed"|"failed"|"timedOut"|"skipped">> Expected status for the currently running test. This is usually `'passed'`, except for a few cases: -* `'skipped'` for skipped tests, e.g. with [`method: Test.skip`]; +* `'skipped'` for skipped tests, e.g. with [`method: Test.skip#2`]; * `'failed'` for tests marked as failed with [`method: Test.fail`]. Expected status is usually compared with the actual [`property: TestInfo.status`]: @@ -246,7 +246,7 @@ Timeout in milliseconds. ## method: TestInfo.skip -Skips the currently running test. This is similar to [`method: Test.skip`]. +Skips the currently running test. This is similar to [`method: Test.skip#2`]. ### param: TestInfo.skip.condition - `condition` <[void]|[boolean]> diff --git a/docs/src/test-reporter-api/class-testcase.md b/docs/src/test-reporter-api/class-testcase.md index c2f1c3c45c..783ec06701 100644 --- a/docs/src/test-reporter-api/class-testcase.md +++ b/docs/src/test-reporter-api/class-testcase.md @@ -18,7 +18,7 @@ Learn more about [test annotations](./test-annotations.md). - type: <[TestStatus]<"passed"|"failed"|"timedOut"|"skipped">> Expected test status. -* Tests marked as [`method: Test.skip`] or [`method: Test.fixme`] are expected to be `'skipped'`. +* Tests marked as [`method: Test.skip#1`] or [`method: Test.fixme`] are expected to be `'skipped'`. * Tests marked as [`method: Test.fail`] are expected to be `'failed'`. * Other tests are expected to be `'passed'`. diff --git a/types/test.d.ts b/types/test.d.ts index 6abcc096bf..355dbe3d19 100644 --- a/types/test.d.ts +++ b/types/test.d.ts @@ -1181,12 +1181,24 @@ export interface TestInfo { /** * Skips the currently running test. This is similar to - * [test.skip(titleOrCondition, testFunctionOrDescription)](https://playwright.dev/docs/api/class-test#test-skip). + * [test.skip()](https://playwright.dev/docs/api/class-test#test-skip-2). * @param condition Optional condition - the test is skipped when the condition is `true`. * @param description Optional description that will be reflected in a test report. */ skip(): void; + /** + * Skips the currently running test. This is similar to + * [test.skip()](https://playwright.dev/docs/api/class-test#test-skip-2). + * @param condition Optional condition - the test is skipped when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ skip(condition: boolean): void; + /** + * Skips the currently running test. This is similar to + * [test.skip()](https://playwright.dev/docs/api/class-test#test-skip-2). + * @param condition Optional condition - the test is skipped when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ skip(condition: boolean, description: string): void; /** @@ -1196,7 +1208,19 @@ export interface TestInfo { * @param description Optional description that will be reflected in a test report. */ fixme(): void; + /** + * Marks the currently running test as "fixme". The test will be skipped, but the intention is to fix it. This is similar + * to [test.fixme([condition, description])](https://playwright.dev/docs/api/class-test#test-fixme). + * @param condition Optional condition - the test is marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(condition: boolean): void; + /** + * Marks the currently running test as "fixme". The test will be skipped, but the intention is to fix it. This is similar + * to [test.fixme([condition, description])](https://playwright.dev/docs/api/class-test#test-fixme). + * @param condition Optional condition - the test is marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(condition: boolean, description: string): void; /** @@ -1206,7 +1230,19 @@ export interface TestInfo { * @param description Optional description that will be reflected in a test report. */ fail(): void; + /** + * Marks the currently running test as "should fail". Playwright Test ensures that this test is actually failing. This is + * similar to [test.fail([condition, description])](https://playwright.dev/docs/api/class-test#test-fail). + * @param condition Optional condition - the test is marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(condition: boolean): void; + /** + * Marks the currently running test as "should fail". Playwright Test ensures that this test is actually failing. This is + * similar to [test.fail([condition, description])](https://playwright.dev/docs/api/class-test#test-fail). + * @param condition Optional condition - the test is marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(condition: boolean, description: string): void; /** @@ -1216,7 +1252,19 @@ export interface TestInfo { * @param description Optional description that will be reflected in a test report. */ slow(): void; + /** + * Marks the currently running test as "slow", giving it triple the default timeout. This is similar to + * [test.slow([condition, description])](https://playwright.dev/docs/api/class-test#test-slow). + * @param condition Optional condition - the test is marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(condition: boolean): void; + /** + * Marks the currently running test as "slow", giving it triple the default timeout. This is similar to + * [test.slow([condition, description])](https://playwright.dev/docs/api/class-test#test-slow). + * @param condition Optional condition - the test is marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(condition: boolean, description: string): void; /** @@ -1248,8 +1296,7 @@ export interface TestInfo { setTimeout(timeout: number): void; /** * Expected status for the currently running test. This is usually `'passed'`, except for a few cases: - * - `'skipped'` for skipped tests, e.g. with - * [test.skip(titleOrCondition, testFunctionOrDescription)](https://playwright.dev/docs/api/class-test#test-skip); + * - `'skipped'` for skipped tests, e.g. with [test.skip()](https://playwright.dev/docs/api/class-test#test-skip-2); * - `'failed'` for tests marked as failed with * [test.fail([condition, description])](https://playwright.dev/docs/api/class-test#test-fail). * @@ -1532,10 +1579,8 @@ export interface TestType Promise | void): void; + /** + * Unconditionally skip a test. Test is immediately aborted when you call + * [test.skip()](https://playwright.dev/docs/api/class-test#test-skip-2). * * ```js js-flavor=js * const { test, expect } = require('@playwright/test'); * - * test('skip in WebKit', async ({ page, browserName }) => { - * test.skip(browserName === 'webkit', 'This feature is not implemented for Mac'); + * test('skipped test', async ({ page }) => { + * test.skip(); * // ... * }); * ``` @@ -1567,24 +1618,24 @@ export interface TestType { - * test.skip(browserName === 'webkit', 'This feature is not implemented for Mac'); + * test('skipped test', async ({ page }) => { + * test.skip(); * // ... * }); * ``` * - * Conditionally skip all tests in a file or + * Unconditionally skip all tests in a file or * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: * * ```js js-flavor=js * const { test, expect } = require('@playwright/test'); * - * test.skip(({ browserName }) => browserName === 'webkit'); + * test.skip(); * - * test('skip in WebKit 1', async ({ page }) => { + * test('skipped test 1', async ({ page }) => { * // ... * }); - * test('skip in WebKit 2', async ({ page }) => { + * test('skipped test 2', async ({ page }) => { * // ... * }); * ``` @@ -1592,17 +1643,40 @@ export interface TestType browserName === 'webkit'); + * test.skip(); * - * test('skip in WebKit 1', async ({ page }) => { + * test('skipped test 1', async ({ page }) => { * // ... * }); - * test('skip in WebKit 2', async ({ page }) => { + * test('skipped test 2', async ({ page }) => { * // ... * }); * ``` * - * Skip from a hook: + */ + skip(): void; + /** + * Conditionally skip a test with an optional description. + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('skip in WebKit', async ({ page, browserName }) => { + * test.skip(browserName === 'webkit', 'This feature is not implemented for Mac'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('skip in WebKit', async ({ page, browserName }) => { + * test.skip(browserName === 'webkit', 'This feature is not implemented for Mac'); + * // ... + * }); + * ``` + * + * Skip from [test.beforeEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-each) hook: * * ```js js-flavor=js * const { test, expect } = require('@playwright/test'); @@ -1622,16 +1696,44 @@ export interface TestType {})` notation, first argument is a test title. Otherwise it is an optional skip condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are - * skipped when the condition is `true`. - * @param testFunctionOrDescription When used with `test.skip('test', () => {})` notation, second argument is a test function. Otherwise it is an optional description that will be reflected in a test report. + * @param condition A skip condition. Test or tests are skipped when the condition is `true`. + * @param description An optional description that will be reflected in a test report. */ - skip(title: string, testFunction: (args: TestArgs, testInfo: TestInfo) => Promise | void): void; - skip(): void; - skip(condition: boolean): void; - skip(condition: boolean, description: string): void; - skip(callback: (args: TestArgs & WorkerArgs) => boolean): void; - skip(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void; + skip(condition: boolean, description?: string): void; + /** + * Conditionally skips all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group. + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.skip(({ browserName }) => browserName === 'webkit'); + * + * test('skip in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('skip in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.skip(({ browserName }) => browserName === 'webkit'); + * + * test('skip in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('skip in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param callback A function that returns whether to skip, based on test fixtures. Test or tests are skipped when the return value is `true`. + * @param description An optional description that will be reflected in a test report. + */ + skip(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; /** * Marks a test or a group of tests as "fixme". These tests will not be run, but the intention is to fix them. * @@ -1728,9 +1830,389 @@ export interface TestType { + * test.fixme(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * Conditional fixme a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fixme for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * `fixme` from a hook: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(condition: boolean): void; + /** + * Marks a test or a group of tests as "fixme". These tests will not be run, but the intention is to fix them. + * + * Unconditional fixme: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * Conditional fixme a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fixme for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * `fixme` from a hook: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(condition: boolean, description: string): void; + /** + * Marks a test or a group of tests as "fixme". These tests will not be run, but the intention is to fix them. + * + * Unconditional fixme: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * Conditional fixme a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fixme for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * `fixme` from a hook: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(callback: (args: TestArgs & WorkerArgs) => boolean): void; + /** + * Marks a test or a group of tests as "fixme". These tests will not be run, but the intention is to fix them. + * + * Unconditional fixme: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fixme(); + * // ... + * }); + * ``` + * + * Conditional fixme a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fixme in WebKit', async ({ page, browserName }) => { + * test.fixme(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fixme for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fixme(({ browserName }) => browserName === 'webkit'); + * + * test('fixme in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fixme in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * `fixme` from a hook: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }) => { + * test.fixme(process.env.APP_VERSION === 'v2', 'No settings in v2 yet'); + * await page.goto('/settings'); + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fixme(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void; /** * Marks a test or a group of tests as "should fail". Playwright Test runs these tests and ensures that they are actually @@ -1809,9 +2291,313 @@ export interface TestType { + * test.fail(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * Conditional fail a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fail for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(condition: boolean): void; + /** + * Marks a test or a group of tests as "should fail". Playwright Test runs these tests and ensures that they are actually + * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed. + * + * Unconditional fail: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * Conditional fail a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fail for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(condition: boolean, description: string): void; + /** + * Marks a test or a group of tests as "should fail". Playwright Test runs these tests and ensures that they are actually + * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed. + * + * Unconditional fail: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * Conditional fail a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fail for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(callback: (args: TestArgs & WorkerArgs) => boolean): void; + /** + * Marks a test or a group of tests as "should fail". Playwright Test runs these tests and ensures that they are actually + * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed. + * + * Unconditional fail: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('not yet ready', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * Conditional fail a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * Conditional fail for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.fail(({ browserName }) => browserName === 'webkit'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ fail(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void; /** * Marks a test or a group of tests as "slow". Slow tests will be given triple the default timeout. @@ -1889,9 +2675,309 @@ export interface TestType { + * test.slow(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * Conditional slow a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * Conditional slow for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('slow in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(condition: boolean): void; + /** + * Marks a test or a group of tests as "slow". Slow tests will be given triple the default timeout. + * + * Unconditional slow: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * Conditional slow a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * Conditional slow for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('slow in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(condition: boolean, description: string): void; + /** + * Marks a test or a group of tests as "slow". Slow tests will be given triple the default timeout. + * + * Unconditional slow: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * Conditional slow a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * Conditional slow for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('slow in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(callback: (args: TestArgs & WorkerArgs) => boolean): void; + /** + * Marks a test or a group of tests as "slow". Slow tests will be given triple the default timeout. + * + * Unconditional slow: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow test', async ({ page }) => { + * test.slow(); + * // ... + * }); + * ``` + * + * Conditional slow a test with an optional description: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test('slow in WebKit', async ({ page, browserName }) => { + * test.slow(browserName === 'webkit', 'This feature is slow on Mac'); + * // ... + * }); + * ``` + * + * Conditional slow for all tests in a file or + * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe) group: + * + * ```js js-flavor=js + * const { test, expect } = require('@playwright/test'); + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('slow in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * ```js js-flavor=ts + * import { test, expect } from '@playwright/test'; + * + * test.slow(({ browserName }) => browserName === 'webkit'); + * + * test('slow in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param condition Optional condition - either a boolean value, or a function that takes a fixtures object and returns a boolean. Test or tests are marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ slow(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void; /** * Changes the timeout for the test. diff --git a/types/testReporter.d.ts b/types/testReporter.d.ts index 4e5a61a77e..2eca0a65f1 100644 --- a/types/testReporter.d.ts +++ b/types/testReporter.d.ts @@ -113,8 +113,7 @@ export interface TestCase { titlePath(): string[]; /** * Expected test status. - * - Tests marked as - * [test.skip(titleOrCondition, testFunctionOrDescription)](https://playwright.dev/docs/api/class-test#test-skip) or + * - Tests marked as [test.skip(title, testFunction)](https://playwright.dev/docs/api/class-test#test-skip-1) or * [test.fixme([condition, description])](https://playwright.dev/docs/api/class-test#test-fixme) are expected to be * `'skipped'`. * - Tests marked as [test.fail([condition, description])](https://playwright.dev/docs/api/class-test#test-fail) are diff --git a/types/types.d.ts b/types/types.d.ts index 1807bce0df..a3a955dc70 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -119,6 +119,52 @@ export interface Page { * @param arg Optional argument to pass to `pageFunction`. */ evaluate(pageFunction: PageFunction, arg: Arg): Promise; + /** + * Returns the value of the `pageFunction` invocation. + * + * If the function passed to the + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a [Promise], then + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) would wait for the + * promise to resolve and return its value. + * + * If the function passed to the + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a + * non-[Serializable] value, then + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) resolves to `undefined`. + * Playwright also supports transferring some additional values that are not serializable by `JSON`: `-0`, `NaN`, + * `Infinity`, `-Infinity`. + * + * Passing argument to `pageFunction`: + * + * ```js + * const result = await page.evaluate(([x, y]) => { + * return Promise.resolve(x * y); + * }, [7, 8]); + * console.log(result); // prints "56" + * ``` + * + * A string can also be passed in instead of a function: + * + * ```js + * console.log(await page.evaluate('1 + 2')); // prints "3" + * const x = 10; + * console.log(await page.evaluate(`1 + ${x}`)); // prints "11" + * ``` + * + * [ElementHandle] instances can be passed as an argument to the + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate): + * + * ```js + * const bodyHandle = await page.$('body'); + * const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']); + * await bodyHandle.dispose(); + * ``` + * + * Shortcut for main frame's + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate). + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluate(pageFunction: PageFunction, arg?: any): Promise; /** @@ -161,6 +207,45 @@ export interface Page { * @param arg Optional argument to pass to `pageFunction`. */ evaluateHandle(pageFunction: PageFunction, arg: Arg): Promise>; + /** + * Returns the value of the `pageFunction` invocation as a [JSHandle]. + * + * The only difference between + * [page.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate) and + * [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) is that + * [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) returns + * [JSHandle]. + * + * If the function passed to the + * [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) returns a + * [Promise], then + * [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) would wait + * for the promise to resolve and return its value. + * + * ```js + * const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window)); + * aWindowHandle; // Handle for the window object. + * ``` + * + * A string can also be passed in instead of a function: + * + * ```js + * const aHandle = await page.evaluateHandle('document'); // Handle for the 'document' + * ``` + * + * [JSHandle] instances can be passed as an argument to the + * [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle): + * + * ```js + * const aHandle = await page.evaluateHandle(() => document.body); + * const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle); + * console.log(await resultHandle.jsonValue()); + * await resultHandle.dispose(); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluateHandle(pageFunction: PageFunction, arg?: any): Promise>; /** @@ -174,6 +259,16 @@ export interface Page { * @param options */ $(selector: K, options?: { strict: boolean }): Promise | null>; + /** + * The method finds an element matching the specified selector within the page. If no elements match the selector, the + * return value resolves to `null`. To wait for an element on the page, use + * [page.waitForSelector(selector[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-selector). + * + * Shortcut for main frame's + * [frame.$(selector[, options])](https://playwright.dev/docs/api/class-frame#frame-query-selector). + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ $(selector: string, options?: { strict: boolean }): Promise | null>; /** @@ -184,6 +279,13 @@ export interface Page { * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. */ $$(selector: K): Promise[]>; + /** + * The method finds all elements matching the specified selector within the page. If no elements match the selector, the + * return value resolves to `[]`. + * + * Shortcut for main frame's [frame.$$(selector)](https://playwright.dev/docs/api/class-frame#frame-query-selector-all). + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + */ $$(selector: string): Promise[]>; /** @@ -212,8 +314,83 @@ export interface Page { * @param options */ $eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * The method finds an element matching the specified selector within the page and passes it as a first argument to + * `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`. + * + * If `pageFunction` returns a [Promise], then + * [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await page.$eval('#search', el => el.value); + * const preloadHref = await page.$eval('link[rel=preload]', el => el.href); + * const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * // In TypeScript, this example requires an explicit type annotation (HTMLLinkElement) on el: + * const preloadHrefTS = await page.$eval('link[rel=preload]', (el: HTMLLinkElement) => el.href); + * ``` + * + * Shortcut for main frame's + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector). + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * The method finds an element matching the specified selector within the page and passes it as a first argument to + * `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`. + * + * If `pageFunction` returns a [Promise], then + * [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await page.$eval('#search', el => el.value); + * const preloadHref = await page.$eval('link[rel=preload]', el => el.href); + * const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * // In TypeScript, this example requires an explicit type annotation (HTMLLinkElement) on el: + * const preloadHrefTS = await page.$eval('link[rel=preload]', (el: HTMLLinkElement) => el.href); + * ``` + * + * Shortcut for main frame's + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector). + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * The method finds an element matching the specified selector within the page and passes it as a first argument to + * `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`. + * + * If `pageFunction` returns a [Promise], then + * [page.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await page.$eval('#search', el => el.value); + * const preloadHref = await page.$eval('link[rel=preload]', el => el.href); + * const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * // In TypeScript, this example requires an explicit type annotation (HTMLLinkElement) on el: + * const preloadHrefTS = await page.$eval('link[rel=preload]', (el: HTMLLinkElement) => el.href); + * ``` + * + * Shortcut for main frame's + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector). + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -235,8 +412,62 @@ export interface Page { * @param arg Optional argument to pass to `pageFunction`. */ $$eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * The method finds all elements matching the specified selector within the page and passes an array of matched elements as + * a first argument to `pageFunction`. Returns the result of `pageFunction` invocation. + * + * If `pageFunction` returns a [Promise], then + * [page.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector-all) would + * wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * The method finds all elements matching the specified selector within the page and passes an array of matched elements as + * a first argument to `pageFunction`. Returns the result of `pageFunction` invocation. + * + * If `pageFunction` returns a [Promise], then + * [page.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector-all) would + * wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * The method finds all elements matching the specified selector within the page and passes an array of matched elements as + * a first argument to `pageFunction`. Returns the result of `pageFunction` invocation. + * + * If `pageFunction` returns a [Promise], then + * [page.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-eval-on-selector-all) would + * wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -275,6 +506,41 @@ export interface Page { * @param options */ waitForFunction(pageFunction: PageFunction, arg: Arg, options?: PageWaitForFunctionOptions): Promise>; + /** + * Returns when the `pageFunction` returns a truthy value. It resolves to a JSHandle of the truthy value. + * + * The + * [page.waitForFunction(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-wait-for-function) + * can be used to observe viewport size change: + * + * ```js + * const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. + * + * (async () => { + * const browser = await webkit.launch(); + * const page = await browser.newPage(); + * const watchDog = page.waitForFunction(() => window.innerWidth < 100); + * await page.setViewportSize({width: 50, height: 50}); + * await watchDog; + * await browser.close(); + * })(); + * ``` + * + * To pass an argument to the predicate of + * [page.waitForFunction(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-wait-for-function) + * function: + * + * ```js + * const selector = '.foo'; + * await page.waitForFunction(selector => !!document.querySelector(selector), selector); + * ``` + * + * Shortcut for main frame's + * [frame.waitForFunction(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-wait-for-function). + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ waitForFunction(pageFunction: PageFunction, arg?: any, options?: PageWaitForFunctionOptions): Promise>; /** @@ -306,8 +572,92 @@ export interface Page { * @param options */ waitForSelector(selector: K, options?: PageWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options?: PageWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: K, options: PageWaitForSelectorOptions): Promise | null>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options: PageWaitForSelectorOptions): Promise>; /** @@ -369,6 +719,64 @@ export interface Page { * @param options */ exposeBinding(name: string, playwrightBinding: (source: BindingSource, arg: JSHandle) => any, options: { handle: true }): Promise; + /** + * The method adds a function called `name` on the `window` object of every frame in this page. When called, the function + * executes `callback` and returns a [Promise] which resolves to the return value of `callback`. If the `callback` returns + * a [Promise], it will be awaited. + * + * The first argument of the `callback` function contains information about the caller: `{ browserContext: BrowserContext, + * page: Page, frame: Frame }`. + * + * See + * [browserContext.exposeBinding(name, callback[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding) + * for the context-wide version. + * + * > NOTE: Functions installed via + * [page.exposeBinding(name, callback[, options])](https://playwright.dev/docs/api/class-page#page-expose-binding) survive + * navigations. + * + * An example of exposing page URL to all frames in a page: + * + * ```js + * const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. + * + * (async () => { + * const browser = await webkit.launch({ headless: false }); + * const context = await browser.newContext(); + * const page = await context.newPage(); + * await page.exposeBinding('pageURL', ({ page }) => page.url()); + * await page.setContent(` + * + * + *
+ * `); + * await page.click('button'); + * })(); + * ``` + * + * An example of passing an element handle: + * + * ```js + * await page.exposeBinding('clicked', async (source, element) => { + * console.log(await element.textContent()); + * }, { handle: true }); + * await page.setContent(` + * + *
Click me
+ *
Or click me
+ * `); + * ``` + * + * @param name Name of the function on the window object. + * @param callback Callback function that will be called in the Playwright's context. + * @param options + */ exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any, options?: { handle?: boolean }): Promise; /** * Emitted when the page closes. @@ -3360,6 +3768,46 @@ export interface Frame { * @param arg Optional argument to pass to `pageFunction`. */ evaluate(pageFunction: PageFunction, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * If the function passed to the + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns a [Promise], + * then [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate) would wait for + * the promise to resolve and return its value. + * + * If the function passed to the + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns a + * non-[Serializable] value, then + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns `undefined`. + * Playwright also supports transferring some additional values that are not serializable by `JSON`: `-0`, `NaN`, + * `Infinity`, `-Infinity`. + * + * ```js + * const result = await frame.evaluate(([x, y]) => { + * return Promise.resolve(x * y); + * }, [7, 8]); + * console.log(result); // prints "56" + * ``` + * + * A string can also be passed in instead of a function. + * + * ```js + * console.log(await frame.evaluate('1 + 2')); // prints "3" + * ``` + * + * [ElementHandle] instances can be passed as an argument to the + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate): + * + * ```js + * const bodyHandle = await frame.$('body'); + * const html = await frame.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']); + * await bodyHandle.dispose(); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluate(pageFunction: PageFunction, arg?: any): Promise; /** @@ -3402,6 +3850,45 @@ export interface Frame { * @param arg Optional argument to pass to `pageFunction`. */ evaluateHandle(pageFunction: PageFunction, arg: Arg): Promise>; + /** + * Returns the return value of `pageFunction` as a [JSHandle]. + * + * The only difference between + * [frame.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate) and + * [frame.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle) is that + * [frame.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle) returns + * [JSHandle]. + * + * If the function, passed to the + * [frame.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle), returns + * a [Promise], then + * [frame.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle) would + * wait for the promise to resolve and return its value. + * + * ```js + * const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window)); + * aWindowHandle; // Handle for the window object. + * ``` + * + * A string can also be passed in instead of a function. + * + * ```js + * const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'. + * ``` + * + * [JSHandle] instances can be passed as an argument to the + * [frame.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle): + * + * ```js + * const aHandle = await frame.evaluateHandle(() => document.body); + * const resultHandle = await frame.evaluateHandle(([body, suffix]) => body.innerHTML + suffix, [aHandle, 'hello']); + * console.log(await resultHandle.jsonValue()); + * await resultHandle.dispose(); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluateHandle(pageFunction: PageFunction, arg?: any): Promise>; /** @@ -3413,6 +3900,14 @@ export interface Frame { * @param options */ $(selector: K, options?: { strict: boolean }): Promise | null>; + /** + * Returns the ElementHandle pointing to the frame element. + * + * The method finds an element matching the specified selector within the frame. See + * [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns `null`. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ $(selector: string, options?: { strict: boolean }): Promise | null>; /** @@ -3423,6 +3918,13 @@ export interface Frame { * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. */ $$(selector: K): Promise[]>; + /** + * Returns the ElementHandles pointing to the frame elements. + * + * The method finds all elements matching the specified selector within the frame. See + * [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns empty array. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + */ $$(selector: string): Promise[]>; /** @@ -3450,8 +3952,80 @@ export interface Frame { * @param options */ $eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector within the frame and passes it as a first argument to + * `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, the + * method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await frame.$eval('#search', el => el.value); + * const preloadHref = await frame.$eval('link[rel=preload]', el => el.href); + * const html = await frame.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector within the frame and passes it as a first argument to + * `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, the + * method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await frame.$eval('#search', el => el.value); + * const preloadHref = await frame.$eval('link[rel=preload]', el => el.href); + * const html = await frame.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector within the frame and passes it as a first argument to + * `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, the + * method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [frame.$eval(selector, pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const searchValue = await frame.$eval('#search', el => el.value); + * const preloadHref = await frame.$eval('link[rel=preload]', el => el.href); + * const html = await frame.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ $eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -3475,8 +4049,68 @@ export interface Frame { * @param arg Optional argument to pass to `pageFunction`. */ $$eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector within the frame and passes an array of matched elements + * as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [frame.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector within the frame and passes an array of matched elements + * as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [frame.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector within the frame and passes an array of matched elements + * as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [frame.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-frame#frame-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -3511,6 +4145,37 @@ export interface Frame { * @param options */ waitForFunction(pageFunction: PageFunction, arg: Arg, options?: PageWaitForFunctionOptions): Promise>; + /** + * Returns when the `pageFunction` returns a truthy value, returns that value. + * + * The + * [frame.waitForFunction(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-wait-for-function) + * can be used to observe viewport size change: + * + * ```js + * const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. + * + * (async () => { + * const browser = await firefox.launch(); + * const page = await browser.newPage(); + * const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100'); + * page.setViewportSize({width: 50, height: 50}); + * await watchDog; + * await browser.close(); + * })(); + * ``` + * + * To pass an argument to the predicate of `frame.waitForFunction` function: + * + * ```js + * const selector = '.foo'; + * await frame.waitForFunction(selector => !!document.querySelector(selector), selector); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ waitForFunction(pageFunction: PageFunction, arg?: any, options?: PageWaitForFunctionOptions): Promise>; /** @@ -3542,8 +4207,92 @@ export interface Frame { * @param options */ waitForSelector(selector: K, options?: PageWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.mainFrame().waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options?: PageWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.mainFrame().waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: K, options: PageWaitForSelectorOptions): Promise | null>; + /** + * Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at + * the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the + * selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw. + * + * This method works across navigations: + * + * ```js + * const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. + * + * (async () => { + * const browser = await chromium.launch(); + * const page = await browser.newPage(); + * for (let currentURL of ['https://google.com', 'https://bbc.com']) { + * await page.goto(currentURL); + * const element = await page.mainFrame().waitForSelector('img'); + * console.log('Loaded image: ' + await element.getAttribute('src')); + * } + * await browser.close(); + * })(); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options: PageWaitForSelectorOptions): Promise>; /** * Returns the added tag when the script's onload fires or when the script content was injected into frame. @@ -4986,6 +5735,59 @@ export interface BrowserContext { * @param options */ exposeBinding(name: string, playwrightBinding: (source: BindingSource, arg: JSHandle) => any, options: { handle: true }): Promise; + /** + * The method adds a function called `name` on the `window` object of every frame in every page in the context. When + * called, the function executes `callback` and returns a [Promise] which resolves to the return value of `callback`. If + * the `callback` returns a [Promise], it will be awaited. + * + * The first argument of the `callback` function contains information about the caller: `{ browserContext: BrowserContext, + * page: Page, frame: Frame }`. + * + * See [page.exposeBinding(name, callback[, options])](https://playwright.dev/docs/api/class-page#page-expose-binding) for + * page-only version. + * + * An example of exposing page URL to all frames in all pages in the context: + * + * ```js + * const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. + * + * (async () => { + * const browser = await webkit.launch({ headless: false }); + * const context = await browser.newContext(); + * await context.exposeBinding('pageURL', ({ page }) => page.url()); + * const page = await context.newPage(); + * await page.setContent(` + * + * + *
+ * `); + * await page.click('button'); + * })(); + * ``` + * + * An example of passing an element handle: + * + * ```js + * await context.exposeBinding('clicked', async (source, element) => { + * console.log(await element.textContent()); + * }, { handle: true }); + * await page.setContent(` + * + *
Click me
+ *
Or click me
+ * `); + * ``` + * + * @param name Name of the function on the window object. + * @param callback Callback function that will be called in the Playwright's context. + * @param options + */ exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any, options?: { handle?: boolean }): Promise; /** * > NOTE: Only works with Chromium browser's persistent context. @@ -5837,6 +6639,23 @@ export interface Worker { * @param arg Optional argument to pass to `pageFunction`. */ evaluate(pageFunction: PageFunction, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * If the function passed to the + * [worker.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate) returns a + * [Promise], then [worker.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate) + * would wait for the promise to resolve and return its value. + * + * If the function passed to the + * [worker.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate) returns a + * non-[Serializable] value, then + * [worker.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate) returns + * `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`: `-0`, + * `NaN`, `Infinity`, `-Infinity`. + * @param pageFunction Function to be evaluated in the worker context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluate(pageFunction: PageFunction, arg?: any): Promise; /** @@ -5857,6 +6676,23 @@ export interface Worker { * @param arg Optional argument to pass to `pageFunction`. */ evaluateHandle(pageFunction: PageFunction, arg: Arg): Promise>; + /** + * Returns the return value of `pageFunction` as a [JSHandle]. + * + * The only difference between + * [worker.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate) and + * [worker.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate-handle) is + * that [worker.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate-handle) + * returns [JSHandle]. + * + * If the function passed to the + * [worker.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate-handle) + * returns a [Promise], then + * [worker.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-worker#worker-evaluate-handle) would + * wait for the promise to resolve and return its value. + * @param pageFunction Function to be evaluated in the worker context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluateHandle(pageFunction: PageFunction, arg?: any): Promise>; /** * Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated. @@ -5923,6 +6759,24 @@ export interface JSHandle { * @param arg Optional argument to pass to `pageFunction`. */ evaluate(pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * This method passes this handle as the first argument to `pageFunction`. + * + * If `pageFunction` returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its + * value. + * + * Examples: + * + * ```js + * const tweetHandle = await page.$('.tweet .retweets'); + * expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets'); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluate(pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -5942,6 +6796,22 @@ export interface JSHandle { * @param arg Optional argument to pass to `pageFunction`. */ evaluateHandle(pageFunction: PageFunctionOn, arg: Arg): Promise>; + /** + * Returns the return value of `pageFunction` as a [JSHandle]. + * + * This method passes this handle as the first argument to `pageFunction`. + * + * The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle` returns + * [JSHandle]. + * + * If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would wait + * for the promise to resolve and return its value. + * + * See [page.evaluateHandle(pageFunction[, arg])](https://playwright.dev/docs/api/class-page#page-evaluate-handle) for more + * details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluateHandle(pageFunction: PageFunctionOn, arg?: any): Promise>; /** @@ -6035,6 +6905,11 @@ export interface ElementHandle extends JSHandle { * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. */ $(selector: K, options?: { strict: boolean }): Promise | null>; + /** + * The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See + * [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns `null`. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + */ $(selector: string, options?: { strict: boolean }): Promise | null>; /** @@ -6043,6 +6918,11 @@ export interface ElementHandle extends JSHandle { * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. */ $$(selector: K): Promise[]>; + /** + * The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See + * [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the selector, returns empty array. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + */ $$(selector: string): Promise[]>; /** @@ -6069,8 +6949,77 @@ export interface ElementHandle extends JSHandle { * @param arg Optional argument to pass to `pageFunction`. */ $eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first + * argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the + * selector, the method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const tweetHandle = await page.$('.tweet'); + * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100'); + * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first + * argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the + * selector, the method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const tweetHandle = await page.$('.tweet'); + * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100'); + * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first + * argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. If no elements match the + * selector, the method throws an error. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const tweetHandle = await page.$('.tweet'); + * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100'); + * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10'); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -6102,8 +7051,92 @@ export interface ElementHandle extends JSHandle { * @param arg Optional argument to pass to `pageFunction`. */ $$eval(selector: K, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of + * matched elements as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```html + *
+ *
Hello!
+ *
Hi!
+ *
+ * ``` + * + * ```js + * const feedHandle = await page.$('.feed'); + * expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of + * matched elements as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```html + *
+ *
Hello!
+ *
Hi!
+ *
+ * ``` + * + * ```js + * const feedHandle = await page.$('.feed'); + * expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: K, pageFunction: PageFunctionOn, arg?: any): Promise; + /** + * Returns the return value of `pageFunction`. + * + * The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of + * matched elements as a first argument to `pageFunction`. See [Working with selectors](https://playwright.dev/docs/selectors) for more details. + * + * If `pageFunction` returns a [Promise], then + * [elementHandle.$$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-all) + * would wait for the promise to resolve and return its value. + * + * Examples: + * + * ```html + *
+ *
Hello!
+ *
Hi!
+ *
+ * ``` + * + * ```js + * const feedHandle = await page.$('.feed'); + * expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']); + * ``` + * + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ $$eval(selector: string, pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -6128,8 +7161,71 @@ export interface ElementHandle extends JSHandle { * @param options */ waitForSelector(selector: K, options?: ElementHandleWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns element specified by selector when it satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` relative to the element handle to satisfy `state` option (either appear/disappear from dom, or + * become visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, the method + * will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will + * throw. + * + * ```js + * await page.setContent(`
`); + * const div = await page.$('div'); + * // Waiting for the 'span' selector relative to the div. + * const span = await div.waitForSelector('span', { state: 'attached' }); + * ``` + * + * > NOTE: This method does not work across navigations, use + * [page.waitForSelector(selector[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-selector) instead. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options?: ElementHandleWaitForSelectorOptionsNotHidden): Promise>; + /** + * Returns element specified by selector when it satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` relative to the element handle to satisfy `state` option (either appear/disappear from dom, or + * become visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, the method + * will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will + * throw. + * + * ```js + * await page.setContent(`
`); + * const div = await page.$('div'); + * // Waiting for the 'span' selector relative to the div. + * const span = await div.waitForSelector('span', { state: 'attached' }); + * ``` + * + * > NOTE: This method does not work across navigations, use + * [page.waitForSelector(selector[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-selector) instead. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: K, options: ElementHandleWaitForSelectorOptions): Promise | null>; + /** + * Returns element specified by selector when it satisfies `state` option. Returns `null` if waiting for `hidden` or + * `detached`. + * + * Wait for the `selector` relative to the element handle to satisfy `state` option (either appear/disappear from dom, or + * become visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, the method + * will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will + * throw. + * + * ```js + * await page.setContent(`
`); + * const div = await page.$('div'); + * // Waiting for the 'span' selector relative to the div. + * const span = await div.waitForSelector('span', { state: 'attached' }); + * ``` + * + * > NOTE: This method does not work across navigations, use + * [page.waitForSelector(selector[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-selector) instead. + * @param selector A selector to query for. See [working with selectors](https://playwright.dev/docs/selectors) for more details. + * @param options + */ waitForSelector(selector: string, options: ElementHandleWaitForSelectorOptions): Promise>; /** * This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is @@ -7088,6 +8184,25 @@ export interface Locator { evaluate(pageFunction: PageFunctionOn, arg: Arg, options?: { timeout?: number; }): Promise; + /** + * Returns the return value of `pageFunction`. + * + * This method passes this handle as the first argument to `pageFunction`. + * + * If `pageFunction` returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its + * value. + * + * Examples: + * + * ```js + * const tweets = page.locator('.tweet .retweets'); + * expect(await tweets.evaluate(node => node.innerText)).toBe('10 retweets'); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + * @param options + */ evaluate(pageFunction: PageFunctionOn, options?: { timeout?: number; }): Promise; @@ -7110,6 +8225,24 @@ export interface Locator { * @param arg Optional argument to pass to `pageFunction`. */ evaluateAll(pageFunction: PageFunctionOn<(SVGElement | HTMLElement)[], Arg, R>, arg: Arg): Promise; + /** + * The method finds all elements matching the specified locator and passes an array of matched elements as a first argument + * to `pageFunction`. Returns the result of `pageFunction` invocation. + * + * If `pageFunction` returns a [Promise], then + * [locator.evaluateAll(pageFunction[, arg])](https://playwright.dev/docs/api/class-locator#locator-evaluate-all) would + * wait for the promise to resolve and return its value. + * + * Examples: + * + * ```js + * const elements = page.locator('div'); + * const divCounts = await elements.evaluateAll((divs, min) => divs.length >= min, 10); + * ``` + * + * @param pageFunction Function to be evaluated in the page context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluateAll(pageFunction: PageFunctionOn<(SVGElement | HTMLElement)[], void, R>): Promise; /** * Resolves given locator to the first matching DOM element. If no elements matching the query are visible, waits for them @@ -8191,6 +9324,16 @@ export interface BrowserType { * Option `wsEndpoint` is deprecated. Instead use `endpointURL`. * @deprecated */ + /** + * This methods attaches Playwright to an existing browser instance using the Chrome DevTools Protocol. + * + * The default browser context is accessible via + * [browser.contexts()](https://playwright.dev/docs/api/class-browser#browser-contexts). + * + * > NOTE: Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers. + * @param endpointURL A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`. + * @param options + */ connectOverCDP(options: ConnectOverCDPOptions & { wsEndpoint?: string }): Promise; /** * This methods attaches Playwright to an existing browser instance. @@ -8204,6 +9347,11 @@ export interface BrowserType { * @param options * @deprecated */ + /** + * This methods attaches Playwright to an existing browser instance. + * @param wsEndpoint A browser websocket endpoint to connect to. + * @param options + */ connect(options: ConnectOptions & { wsEndpoint?: string }): Promise; /** * A path where Playwright expects to find a bundled browser executable. @@ -9003,6 +10151,24 @@ export interface ElectronApplication { * @param arg Optional argument to pass to `pageFunction`. */ evaluate(pageFunction: PageFunctionOn, arg: Arg): Promise; + /** + * Returns the return value of `pageFunction`. + * + * If the function passed to the + * [electronApplication.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate) + * returns a [Promise], then + * [electronApplication.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate) + * would wait for the promise to resolve and return its value. + * + * If the function passed to the + * [electronApplication.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate) + * returns a non-[Serializable] value, then + * [electronApplication.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate) + * returns `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`: + * `-0`, `NaN`, `Infinity`, `-Infinity`. + * @param pageFunction Function to be evaluated in the worker context. + * @param arg Optional argument to pass to `pageFunction`. + */ evaluate(pageFunction: PageFunctionOn, arg?: any): Promise; /** @@ -9025,6 +10191,25 @@ export interface ElectronApplication { * @param arg */ evaluateHandle(pageFunction: PageFunctionOn, arg: Arg): Promise>; + /** + * Returns the return value of `pageFunction` as a [JSHandle]. + * + * The only difference between + * [electronApplication.evaluate(pageFunction[, arg])](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate) + * and + * [electronApplication.evaluateHandle(pageFunction, arg)](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate-handle) + * is that + * [electronApplication.evaluateHandle(pageFunction, arg)](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate-handle) + * returns [JSHandle]. + * + * If the function passed to the + * [electronApplication.evaluateHandle(pageFunction, arg)](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate-handle) + * returns a [Promise], then + * [electronApplication.evaluateHandle(pageFunction, arg)](https://playwright.dev/docs/api/class-electronapplication#electron-application-evaluate-handle) + * would wait for the promise to resolve and return its value. + * @param pageFunction Function to be evaluated in the worker context. + * @param arg + */ evaluateHandle(pageFunction: PageFunctionOn, arg?: any): Promise>; /** * This event is issued when the application closes. diff --git a/utils/doclint/api_parser.js b/utils/doclint/api_parser.js index 8dbf0b51c3..a05faee9eb 100644 --- a/utils/doclint/api_parser.js +++ b/utils/doclint/api_parser.js @@ -136,7 +136,7 @@ class ApiParser { const clazz = this.classes.get(className); if (!clazz) throw new Error('Invalid class ' + className); - const method = clazz.membersArray.find(m => m.kind === 'method' && m.alias === methodName); + const method = clazz.membersArray.find(m => m.kind === 'method' && m.name === methodName); if (!method) throw new Error(`Invalid method ${className}.${methodName} when parsing: ${match[0]}`); if (!name) diff --git a/utils/doclint/documentation.js b/utils/doclint/documentation.js index 2b5eef1e07..d32e313d7b 100644 --- a/utils/doclint/documentation.js +++ b/utils/doclint/documentation.js @@ -312,6 +312,12 @@ Documentation.Member = class { }; this.async = false; this.alias = name; + this.overloadIndex = 0; + if (name.includes('#')) { + const match = name.match(/(.*)#(.*)/); + this.alias = match[1]; + this.overloadIndex = (+match[2]) - 1; + } /** * Param is true and option false * @type {Boolean} diff --git a/utils/generate_types/index.js b/utils/generate_types/index.js index 13cf5fe638..ba939d332a 100644 --- a/utils/generate_types/index.js +++ b/utils/generate_types/index.js @@ -87,9 +87,14 @@ class TypesGenerator { return ''; handledClasses.add(className); return this.writeComment(docClass.comment) + '\n'; - }, (className, methodName) => { + }, (className, methodName, overloadIndex) => { const docClass = this.docClassForName(className, docsOnlyClassMapping); - const method = docClass ? docClass.membersArray.find(m => m.alias === methodName) : undefined; + let method; + if (docClass) { + const methods = docClass.membersArray.filter(m => m.alias === methodName && m.kind !== 'event').sort((a, b) => a.overloadIndex - b.overloadIndex); + // Use the last overload when not enough overloads are defined in docs. + method = methods.find(m => m.overloadIndex === overloadIndex) || methods[methods.length - 1]; + } if (docsOnlyClassMapping && !method) return ''; this.handledMethods.add(`${className}.${methodName}`); @@ -381,7 +386,7 @@ class TypesGenerator { argsFromMember(member, indent, ...namespace) { if (member.kind === 'property') return ''; - return '(' + member.argsArray.map(arg => `${this.nameForProperty(arg)}: ${this.stringifyComplexType(arg.type, indent, ...namespace, member.name, arg.name)}`).join(', ') + ')'; + return '(' + member.argsArray.map(arg => `${this.nameForProperty(arg)}: ${this.stringifyComplexType(arg.type, indent, ...namespace, member.alias, arg.alias)}`).join(', ') + ')'; } /** diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index db49461b58..f23ac97424 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -229,10 +229,8 @@ export interface TestType Promise | void): void; skip(): void; - skip(condition: boolean): void; - skip(condition: boolean, description: string): void; - skip(callback: (args: TestArgs & WorkerArgs) => boolean): void; - skip(callback: (args: TestArgs & WorkerArgs) => boolean, description: string): void; + skip(condition: boolean, description?: string): void; + skip(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; fixme(): void; fixme(condition: boolean): void; fixme(condition: boolean, description: string): void; diff --git a/utils/generate_types/parseOverrides.js b/utils/generate_types/parseOverrides.js index a64fd14b18..9d229541fd 100644 --- a/utils/generate_types/parseOverrides.js +++ b/utils/generate_types/parseOverrides.js @@ -20,7 +20,7 @@ const ts = require('typescript'); /** * @param {string} filePath * @param {(className: string) => string} commentForClass - * @param {(className: string, methodName: string) => string} commentForMethod + * @param {(className: string, methodName: string, overloadIndex: number) => string} commentForMethod * @param {(className: string) => string} extraForClass */ async function parseOverrides(filePath, commentForClass, commentForMethod, extraForClass) { @@ -76,13 +76,16 @@ async function parseOverrides(filePath, commentForClass, commentForMethod, extra for (const [name, member] of symbol.members || []) { if (member.flags & ts.SymbolFlags.TypeParameter) continue; - if (!member.valueDeclaration) + if (!member.declarations) continue; - const pos = member.valueDeclaration.getStart(file, false); - replacers.push({ - pos, - text: commentForMethod(className, name), - }); + for (let index = 0; index < member.declarations.length; index++) { + const declaration = member.declarations[index]; + const pos = declaration.getStart(file, false); + replacers.push({ + pos, + text: commentForMethod(className, name, index), + }); + } } replacers.push({ pos: node.getEnd(file) - 1,