From 2deabefa71d3c7123a3f704ba2302716bd7ccd94 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 14 Aug 2023 18:27:25 +0200 Subject: [PATCH] fix: Locator.evaluateHandle types (#26469) Fixes https://github.com/microsoft/playwright/issues/26449 --- packages/playwright-core/types/types.d.ts | 93 ++++++++++++++--------- utils/generate_types/overrides.d.ts | 2 + utils/generate_types/test/test.ts | 54 +++++++++++++ 3 files changed, 112 insertions(+), 37 deletions(-) diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 77010035b4..96740f6966 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -10420,6 +10420,62 @@ export interface Locator { evaluate(pageFunction: PageFunctionOn, options?: { timeout?: number; }): Promise; + /** + * Execute JavaScript code in the page, taking the matching element as an argument, and return a {@link JSHandle} with + * the result. + * + * **Details** + * + * Returns the return value of `pageFunction` as a{@link JSHandle}, called with the matching element as a first + * argument, and `arg` as a second argument. + * + * The only difference between + * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate) + * and + * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) + * is that + * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) + * returns {@link JSHandle}. + * + * If `pageFunction` returns a [Promise], this method will wait for the promise to resolve and return its value. + * + * If `pageFunction` throws or rejects, this method throws. + * + * 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`. + * @param options + */ + evaluateHandle(pageFunction: PageFunctionOn, arg: Arg): Promise>; + /** + * Execute JavaScript code in the page, taking the matching element as an argument, and return a {@link JSHandle} with + * the result. + * + * **Details** + * + * Returns the return value of `pageFunction` as a{@link JSHandle}, called with the matching element as a first + * argument, and `arg` as a second argument. + * + * The only difference between + * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate) + * and + * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) + * is that + * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) + * returns {@link JSHandle}. + * + * If `pageFunction` returns a [Promise], this method will wait for the promise to resolve and return its value. + * + * If `pageFunction` throws or rejects, this method throws. + * + * 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`. + * @param options + */ + evaluateHandle(pageFunction: PageFunctionOn): Promise>; /** * Execute JavaScript code in the page, taking all matching elements as an argument. * @@ -11028,43 +11084,6 @@ export interface Locator { */ elementHandles(): Promise>; - /** - * Execute JavaScript code in the page, taking the matching element as an argument, and return a {@link JSHandle} with - * the result. - * - * **Details** - * - * Returns the return value of `pageFunction` as a{@link JSHandle}, called with the matching element as a first - * argument, and `arg` as a second argument. - * - * The only difference between - * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate) - * and - * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) - * is that - * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle) - * returns {@link JSHandle}. - * - * If `pageFunction` returns a [Promise], this method will wait for the promise to resolve and return its value. - * - * If `pageFunction` throws or rejects, this method throws. - * - * 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`. - * @param options - */ - evaluateHandle(pageFunction: Function|string, arg?: EvaluationArgument, options?: { - /** - * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` - * option in the config, or by using the - * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) - * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. - */ - timeout?: number; - }): Promise; - /** * Set a value to the input field. * diff --git a/utils/generate_types/overrides.d.ts b/utils/generate_types/overrides.d.ts index c85a05234c..203bd34ad6 100644 --- a/utils/generate_types/overrides.d.ts +++ b/utils/generate_types/overrides.d.ts @@ -152,6 +152,8 @@ export interface Locator { evaluate(pageFunction: PageFunctionOn, options?: { timeout?: number; }): Promise; + evaluateHandle(pageFunction: PageFunctionOn, arg: Arg): Promise>; + evaluateHandle(pageFunction: PageFunctionOn): Promise>; evaluateAll(pageFunction: PageFunctionOn, arg: Arg): Promise; evaluateAll(pageFunction: PageFunctionOn): Promise; elementHandle(options?: { diff --git a/utils/generate_types/test/test.ts b/utils/generate_types/test/test.ts index 37729f29d8..0bffaab281 100644 --- a/utils/generate_types/test/test.ts +++ b/utils/generate_types/test/test.ts @@ -498,6 +498,60 @@ playwright.chromium.launch().then(async browser => { const assertion: AssertType<{a: number, b: string, c: boolean, d: number}, typeof value> = true; } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluate(h => h[1].a); + const assertion: AssertType = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluate((h, p) => ({ a: h[1].a, p}), 123); + const assertion: AssertType<{a: string, p: number}, typeof value> = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluate((h: ({a: string, b: number})[]) => h[1].b); + const assertion: AssertType = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluate((h: ({a: string, b: number})[], prop) => h[1][prop], 'b' as const); + const assertion: AssertType = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluateHandle(h => h[1].a); + const assertion: AssertType, typeof value> = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluateHandle((h, p) => ({ a: h[1].a, p}), 123); + const assertion: AssertType, typeof value> = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => ([{a: '123'}])); + const value = await handle.evaluateHandle((h: ({a: string, b: number})[]) => h[1].b); + const assertion: AssertType, typeof value> = true; + } + { + const handle = await page.locator('body').evaluateHandle(e => { + const assertion1: AssertType = true; + const assertion2: AssertType = true; + return e.nodeName; + }); + const value = await handle.evaluate(e => e); + const assertion: AssertType = true; + }{ + const handle = await page.locator('body').evaluateHandle(() => 3); + const value = await page.evaluate(([a, b, c, d]) => ({a, b, c, d}), wrap(handle)); + const assertion: AssertType<{a: number, b: string, c: boolean, d: number}, typeof value> = true; + } + { + const handle = await page.locator('body').evaluateHandle(() => 3); + const h = await page.locator('body').evaluateHandle((_, [a, b, c, d]) => ({a, b, c, d}), wrap(handle)); + const value = await h.evaluate(h => h); + const assertion: AssertType<{a: number, b: string, c: boolean, d: number}, typeof value> = true; + } { const handle = await page.evaluateHandle(() => ([{a: '123'}])); const value = await handle.evaluate(h => h[1].a);