diff --git a/packages/playwright-client/types/types.d.ts b/packages/playwright-client/types/types.d.ts index ac62bab28e515..1b92b5acb8714 100644 --- a/packages/playwright-client/types/types.d.ts +++ b/packages/playwright-client/types/types.d.ts @@ -12222,6 +12222,185 @@ export interface JSHandle { [Symbol.asyncDispose](): Promise; } +/** + * [APIResponse](https://playwright.dev/docs/api/class-apiresponse) class represents responses returned by + * [apiRequestContext.get(url[, options])](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get) + * and similar methods. + */ +export interface APIResponse { + /** + * Returns the JSON representation of response body. + * + * This method will throw if the response body is not parsable via `JSON.parse`. + */ + json(): Promise; + /** + * Returns the buffer with response body. + */ + body(): Promise; + + /** + * Disposes the body of this response. If not called then the body will stay in memory until the context closes. + */ + dispose(): Promise; + + /** + * An object with all the response HTTP headers associated with this response. + */ + headers(): { [key: string]: string; }; + + /** + * An array with all the response HTTP headers associated with this response. Header names are not lower-cased. + * Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times. + */ + headersArray(): Array<{ + /** + * Name of the header. + */ + name: string; + + /** + * Value of the header. + */ + value: string; + }>; + + /** + * Contains a boolean stating whether the response was successful (status in the range 200-299) or not. + */ + ok(): boolean; + + /** + * Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests, + * returns the information for the last request in the redirect chain. + */ + securityDetails(): Promise; + + /** + * Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For + * redirected requests, returns the information for the last request in the redirect chain. + */ + serverAddr(): Promise; + + /** + * Contains the status code of the response (e.g., 200 for a success). + */ + status(): number; + + /** + * Contains the status text of the response (e.g. usually an "OK" for a success). + */ + statusText(): string; + + /** + * Returns the text representation of response body. + */ + text(): Promise; + + /** + * Returns resource timing information for given response. For redirected requests, returns the information for the + * last request in the redirect chain. When the response is served [from the HAR file](https://playwright.dev/docs/mock#replaying-from-har), + * timing information is not available and all the values are -1. Find more information at + * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming). + */ + timing(): { + /** + * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC + */ + startTime: number; + + /** + * Time immediately before the client starts the domain name lookup for the resource. The value is given in + * milliseconds relative to `startTime`, -1 if not available. + */ + domainLookupStart: number; + + /** + * Time immediately after the client ends the domain name lookup for the resource. The value is given in milliseconds + * relative to `startTime`, -1 if not available. + */ + domainLookupEnd: number; + + /** + * Time immediately before the client starts establishing the connection to the server to retrieve the resource. The + * value is given in milliseconds relative to `startTime`, -1 if not available. + */ + connectStart: number; + + /** + * Time immediately before the client starts the handshake process to secure the current connection. The value is + * given in milliseconds relative to `startTime`, -1 if not available. + */ + secureConnectionStart: number; + + /** + * Time immediately after the client establishes the connection to the server to retrieve the resource. The value is + * given in milliseconds relative to `startTime`, -1 if not available. + */ + connectEnd: number; + + /** + * Time immediately before the client starts requesting the resource from the server, cache, or local resource. The + * value is given in milliseconds relative to `startTime`, -1 if not available. + */ + requestStart: number; + + /** + * Time immediately after the client receives the first byte of the response from the server, cache, or local + * resource. The value is given in milliseconds relative to `startTime`, -1 if not available. + */ + responseStart: number; + + /** + * Time immediately after the client receives the last byte of the resource or immediately before the transport + * connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not + * available. + */ + responseEnd: number; + }; + + /** + * Contains the URL of the response. + */ + url(): string; + + [Symbol.asyncDispose](): Promise; +} + /** * - extends: [JSHandle](https://playwright.dev/docs/api/class-jshandle) * @@ -19458,7 +19637,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - delete(url: string, options?: { + delete(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19546,7 +19725,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * All responses returned by @@ -19600,7 +19779,7 @@ export interface APIRequestContext { * @param urlOrRequest Target URL or Request to get all parameters from. * @param options */ - fetch(urlOrRequest: string|Request, options?: { + fetch(urlOrRequest: string|Request, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19694,7 +19873,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) request and returns its @@ -19729,7 +19908,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - get(url: string, options?: { + get(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19817,7 +19996,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) request and returns its @@ -19826,7 +20005,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - head(url: string, options?: { + head(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19914,7 +20093,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [PATCH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) request and returns its @@ -19923,7 +20102,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - patch(url: string, options?: { + patch(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20011,7 +20190,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) request and returns its @@ -20062,7 +20241,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - post(url: string, options?: { + post(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20150,7 +20329,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [PUT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) request and returns its @@ -20159,7 +20338,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - put(url: string, options?: { + put(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20247,7 +20426,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Returns storage state for this request context, contains current cookies and local storage snapshot if it was @@ -20305,186 +20484,6 @@ export interface APIRequestContext { [Symbol.asyncDispose](): Promise; } -/** - * [APIResponse](https://playwright.dev/docs/api/class-apiresponse) class represents responses returned by - * [apiRequestContext.get(url[, options])](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get) - * and similar methods. - */ -export interface APIResponse { - /** - * Returns the buffer with response body. - */ - body(): Promise; - - /** - * Disposes the body of this response. If not called then the body will stay in memory until the context closes. - */ - dispose(): Promise; - - /** - * An object with all the response HTTP headers associated with this response. - */ - headers(): { [key: string]: string; }; - - /** - * An array with all the response HTTP headers associated with this response. Header names are not lower-cased. - * Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times. - */ - headersArray(): Array<{ - /** - * Name of the header. - */ - name: string; - - /** - * Value of the header. - */ - value: string; - }>; - - /** - * Returns the JSON representation of response body. - * - * This method will throw if the response body is not parsable via `JSON.parse`. - */ - json(): Promise; - - /** - * Contains a boolean stating whether the response was successful (status in the range 200-299) or not. - */ - ok(): boolean; - - /** - * Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests, - * returns the information for the last request in the redirect chain. - */ - securityDetails(): Promise; - - /** - * Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For - * redirected requests, returns the information for the last request in the redirect chain. - */ - serverAddr(): Promise; - - /** - * Contains the status code of the response (e.g., 200 for a success). - */ - status(): number; - - /** - * Contains the status text of the response (e.g. usually an "OK" for a success). - */ - statusText(): string; - - /** - * Returns the text representation of response body. - */ - text(): Promise; - - /** - * Returns resource timing information for given response. For redirected requests, returns the information for the - * last request in the redirect chain. When the response is served [from the HAR file](https://playwright.dev/docs/mock#replaying-from-har), - * timing information is not available and all the values are -1. Find more information at - * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming). - */ - timing(): { - /** - * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC - */ - startTime: number; - - /** - * Time immediately before the client starts the domain name lookup for the resource. The value is given in - * milliseconds relative to `startTime`, -1 if not available. - */ - domainLookupStart: number; - - /** - * Time immediately after the client ends the domain name lookup for the resource. The value is given in milliseconds - * relative to `startTime`, -1 if not available. - */ - domainLookupEnd: number; - - /** - * Time immediately before the client starts establishing the connection to the server to retrieve the resource. The - * value is given in milliseconds relative to `startTime`, -1 if not available. - */ - connectStart: number; - - /** - * Time immediately before the client starts the handshake process to secure the current connection. The value is - * given in milliseconds relative to `startTime`, -1 if not available. - */ - secureConnectionStart: number; - - /** - * Time immediately after the client establishes the connection to the server to retrieve the resource. The value is - * given in milliseconds relative to `startTime`, -1 if not available. - */ - connectEnd: number; - - /** - * Time immediately before the client starts requesting the resource from the server, cache, or local resource. The - * value is given in milliseconds relative to `startTime`, -1 if not available. - */ - requestStart: number; - - /** - * Time immediately after the client receives the first byte of the response from the server, cache, or local - * resource. The value is given in milliseconds relative to `startTime`, -1 if not available. - */ - responseStart: number; - - /** - * Time immediately after the client receives the last byte of the resource or immediately before the transport - * connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not - * available. - */ - responseEnd: number; - }; - - /** - * Contains the URL of the response. - */ - url(): string; - - [Symbol.asyncDispose](): Promise; -} - export interface BrowserServer { /** * Emitted when the browser server closes. @@ -23352,7 +23351,7 @@ export interface Route { * instead. * @param options */ - fetch(options?: { + fetch(options?: { /** * If set changes the request HTTP headers. Header values will be converted to a string. */ @@ -23402,7 +23401,7 @@ export interface Route { * If set changes the request URL. New URL must have same protocol as original one. */ url?: string; - }): Promise; + }): Promise>; /** * Fulfills route's request with given response. diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index 54b17863a1745..cba0845ca3b62 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -389,7 +389,7 @@ export class APIResponse implements api.APIResponse { return content.toString('utf8'); } - async json(): Promise { + async json(): Promise { const content = await this.text(); return JSON.parse(content); } diff --git a/packages/playwright-core/src/server/recorder/recorderUtils.ts b/packages/playwright-core/src/server/recorder/recorderUtils.ts index eb18550169e0e..a29951ec63cf7 100644 --- a/packages/playwright-core/src/server/recorder/recorderUtils.ts +++ b/packages/playwright-core/src/server/recorder/recorderUtils.ts @@ -18,6 +18,7 @@ import { renderTitleForCall } from '@isomorphic/protocolFormatter'; import { raceAgainstDeadline } from '@isomorphic/timeoutRunner'; import { monotonicTime } from '@isomorphic/time'; import { quoteCSSAttributeValue } from '@isomorphic/stringUtils'; +import { isUnderTest } from '@utils/debug'; import { Frame } from '../frames'; import type { CallMetadata } from '../instrumentation'; @@ -28,8 +29,8 @@ function buildFullSelector(framePath: string[], selector: string) { return [...framePath, selector].join(' >> internal:control=enter-frame >> '); } -export async function buildFullSelectorForFrame(progress: Progress, frame: Frame, selector: string): Promise { - const framePath = await generateFrameSelector(progress, frame); +export async function buildFullSelectorForFrame(progress: Progress, frame: Frame, selector: string, timeout = isUnderTest() ? 10000 : 2000): Promise { + const framePath = await generateFrameSelector(progress, frame, timeout); if (!frame._page.browserContext._options.pierceFrames || !framePath.length) return buildFullSelector(framePath, selector); @@ -40,7 +41,7 @@ export async function buildFullSelectorForFrame(progress: Progress, frame: Frame if (await resolvesToFrame(progress, candidate, frame)) return candidate; } - }, monotonicTime() + 2000)); + }, monotonicTime() + timeout)); if (!result.timedOut && result.result) return result.result; @@ -83,14 +84,14 @@ export function metadataToCallLog(metadata: CallMetadata, status: CallLogStatus) } -async function generateFrameSelector(progress: Progress, frame: Frame): Promise { +async function generateFrameSelector(progress: Progress, frame: Frame, timeout: number): Promise { const selectorPromises: Promise[] = []; progress.setAllowConcurrentOrNestedRaces(true); while (frame) { const parent = frame.parentFrame(); if (!parent) break; - selectorPromises.push(generateFrameSelectorInParent(progress, parent, frame)); + selectorPromises.push(generateFrameSelectorInParent(progress, parent, frame, timeout)); frame = parent; } const result = await Promise.all(selectorPromises); @@ -98,7 +99,7 @@ async function generateFrameSelector(progress: Progress, frame: Frame): Promise< return result.reverse(); } -async function generateFrameSelectorInParent(prgoress: Progress, parent: Frame, frame: Frame): Promise { +async function generateFrameSelectorInParent(prgoress: Progress, parent: Frame, frame: Frame, timeout: number): Promise { const result = await raceAgainstDeadline(async () => { try { const frameElement = await frame.frameElement(prgoress); @@ -112,7 +113,7 @@ async function generateFrameSelectorInParent(prgoress: Progress, parent: Frame, return selector; } catch (e) { } - }, monotonicTime() + 2000); + }, monotonicTime() + timeout); if (!result.timedOut && result.result) return result.result; diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index ac62bab28e515..1b92b5acb8714 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -12222,6 +12222,185 @@ export interface JSHandle { [Symbol.asyncDispose](): Promise; } +/** + * [APIResponse](https://playwright.dev/docs/api/class-apiresponse) class represents responses returned by + * [apiRequestContext.get(url[, options])](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get) + * and similar methods. + */ +export interface APIResponse { + /** + * Returns the JSON representation of response body. + * + * This method will throw if the response body is not parsable via `JSON.parse`. + */ + json(): Promise; + /** + * Returns the buffer with response body. + */ + body(): Promise; + + /** + * Disposes the body of this response. If not called then the body will stay in memory until the context closes. + */ + dispose(): Promise; + + /** + * An object with all the response HTTP headers associated with this response. + */ + headers(): { [key: string]: string; }; + + /** + * An array with all the response HTTP headers associated with this response. Header names are not lower-cased. + * Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times. + */ + headersArray(): Array<{ + /** + * Name of the header. + */ + name: string; + + /** + * Value of the header. + */ + value: string; + }>; + + /** + * Contains a boolean stating whether the response was successful (status in the range 200-299) or not. + */ + ok(): boolean; + + /** + * Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests, + * returns the information for the last request in the redirect chain. + */ + securityDetails(): Promise; + + /** + * Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For + * redirected requests, returns the information for the last request in the redirect chain. + */ + serverAddr(): Promise; + + /** + * Contains the status code of the response (e.g., 200 for a success). + */ + status(): number; + + /** + * Contains the status text of the response (e.g. usually an "OK" for a success). + */ + statusText(): string; + + /** + * Returns the text representation of response body. + */ + text(): Promise; + + /** + * Returns resource timing information for given response. For redirected requests, returns the information for the + * last request in the redirect chain. When the response is served [from the HAR file](https://playwright.dev/docs/mock#replaying-from-har), + * timing information is not available and all the values are -1. Find more information at + * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming). + */ + timing(): { + /** + * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC + */ + startTime: number; + + /** + * Time immediately before the client starts the domain name lookup for the resource. The value is given in + * milliseconds relative to `startTime`, -1 if not available. + */ + domainLookupStart: number; + + /** + * Time immediately after the client ends the domain name lookup for the resource. The value is given in milliseconds + * relative to `startTime`, -1 if not available. + */ + domainLookupEnd: number; + + /** + * Time immediately before the client starts establishing the connection to the server to retrieve the resource. The + * value is given in milliseconds relative to `startTime`, -1 if not available. + */ + connectStart: number; + + /** + * Time immediately before the client starts the handshake process to secure the current connection. The value is + * given in milliseconds relative to `startTime`, -1 if not available. + */ + secureConnectionStart: number; + + /** + * Time immediately after the client establishes the connection to the server to retrieve the resource. The value is + * given in milliseconds relative to `startTime`, -1 if not available. + */ + connectEnd: number; + + /** + * Time immediately before the client starts requesting the resource from the server, cache, or local resource. The + * value is given in milliseconds relative to `startTime`, -1 if not available. + */ + requestStart: number; + + /** + * Time immediately after the client receives the first byte of the response from the server, cache, or local + * resource. The value is given in milliseconds relative to `startTime`, -1 if not available. + */ + responseStart: number; + + /** + * Time immediately after the client receives the last byte of the resource or immediately before the transport + * connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not + * available. + */ + responseEnd: number; + }; + + /** + * Contains the URL of the response. + */ + url(): string; + + [Symbol.asyncDispose](): Promise; +} + /** * - extends: [JSHandle](https://playwright.dev/docs/api/class-jshandle) * @@ -19458,7 +19637,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - delete(url: string, options?: { + delete(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19546,7 +19725,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * All responses returned by @@ -19600,7 +19779,7 @@ export interface APIRequestContext { * @param urlOrRequest Target URL or Request to get all parameters from. * @param options */ - fetch(urlOrRequest: string|Request, options?: { + fetch(urlOrRequest: string|Request, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19694,7 +19873,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) request and returns its @@ -19729,7 +19908,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - get(url: string, options?: { + get(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19817,7 +19996,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) request and returns its @@ -19826,7 +20005,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - head(url: string, options?: { + head(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -19914,7 +20093,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [PATCH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) request and returns its @@ -19923,7 +20102,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - patch(url: string, options?: { + patch(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20011,7 +20190,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) request and returns its @@ -20062,7 +20241,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - post(url: string, options?: { + post(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20150,7 +20329,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Sends HTTP(S) [PUT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) request and returns its @@ -20159,7 +20338,7 @@ export interface APIRequestContext { * @param url Target URL. * @param options */ - put(url: string, options?: { + put(url: string, options?: { /** * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type` @@ -20247,7 +20426,7 @@ export interface APIRequestContext { * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. */ timeout?: number; - }): Promise; + }): Promise>; /** * Returns storage state for this request context, contains current cookies and local storage snapshot if it was @@ -20305,186 +20484,6 @@ export interface APIRequestContext { [Symbol.asyncDispose](): Promise; } -/** - * [APIResponse](https://playwright.dev/docs/api/class-apiresponse) class represents responses returned by - * [apiRequestContext.get(url[, options])](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get) - * and similar methods. - */ -export interface APIResponse { - /** - * Returns the buffer with response body. - */ - body(): Promise; - - /** - * Disposes the body of this response. If not called then the body will stay in memory until the context closes. - */ - dispose(): Promise; - - /** - * An object with all the response HTTP headers associated with this response. - */ - headers(): { [key: string]: string; }; - - /** - * An array with all the response HTTP headers associated with this response. Header names are not lower-cased. - * Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times. - */ - headersArray(): Array<{ - /** - * Name of the header. - */ - name: string; - - /** - * Value of the header. - */ - value: string; - }>; - - /** - * Returns the JSON representation of response body. - * - * This method will throw if the response body is not parsable via `JSON.parse`. - */ - json(): Promise; - - /** - * Contains a boolean stating whether the response was successful (status in the range 200-299) or not. - */ - ok(): boolean; - - /** - * Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests, - * returns the information for the last request in the redirect chain. - */ - securityDetails(): Promise; - - /** - * Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For - * redirected requests, returns the information for the last request in the redirect chain. - */ - serverAddr(): Promise; - - /** - * Contains the status code of the response (e.g., 200 for a success). - */ - status(): number; - - /** - * Contains the status text of the response (e.g. usually an "OK" for a success). - */ - statusText(): string; - - /** - * Returns the text representation of response body. - */ - text(): Promise; - - /** - * Returns resource timing information for given response. For redirected requests, returns the information for the - * last request in the redirect chain. When the response is served [from the HAR file](https://playwright.dev/docs/mock#replaying-from-har), - * timing information is not available and all the values are -1. Find more information at - * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming). - */ - timing(): { - /** - * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC - */ - startTime: number; - - /** - * Time immediately before the client starts the domain name lookup for the resource. The value is given in - * milliseconds relative to `startTime`, -1 if not available. - */ - domainLookupStart: number; - - /** - * Time immediately after the client ends the domain name lookup for the resource. The value is given in milliseconds - * relative to `startTime`, -1 if not available. - */ - domainLookupEnd: number; - - /** - * Time immediately before the client starts establishing the connection to the server to retrieve the resource. The - * value is given in milliseconds relative to `startTime`, -1 if not available. - */ - connectStart: number; - - /** - * Time immediately before the client starts the handshake process to secure the current connection. The value is - * given in milliseconds relative to `startTime`, -1 if not available. - */ - secureConnectionStart: number; - - /** - * Time immediately after the client establishes the connection to the server to retrieve the resource. The value is - * given in milliseconds relative to `startTime`, -1 if not available. - */ - connectEnd: number; - - /** - * Time immediately before the client starts requesting the resource from the server, cache, or local resource. The - * value is given in milliseconds relative to `startTime`, -1 if not available. - */ - requestStart: number; - - /** - * Time immediately after the client receives the first byte of the response from the server, cache, or local - * resource. The value is given in milliseconds relative to `startTime`, -1 if not available. - */ - responseStart: number; - - /** - * Time immediately after the client receives the last byte of the resource or immediately before the transport - * connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not - * available. - */ - responseEnd: number; - }; - - /** - * Contains the URL of the response. - */ - url(): string; - - [Symbol.asyncDispose](): Promise; -} - export interface BrowserServer { /** * Emitted when the browser server closes. @@ -23352,7 +23351,7 @@ export interface Route { * instead. * @param options */ - fetch(options?: { + fetch(options?: { /** * If set changes the request HTTP headers. Header values will be converted to a string. */ @@ -23402,7 +23401,7 @@ export interface Route { * If set changes the request URL. New URL must have same protocol as original one. */ url?: string; - }): Promise; + }): Promise>; /** * Fulfills route's request with given response. diff --git a/utils/generate_types/index.js b/utils/generate_types/index.js index 1dee2fe602361..253ab30f1c9f1 100644 --- a/utils/generate_types/index.js +++ b/utils/generate_types/index.js @@ -298,14 +298,19 @@ class TypesGenerator { let type = this.stringifyComplexType(member.type, 'out', indent, [classDesc.name, member.alias]); if (member.async) type = `Promise<${type}>`; + let typeParams = ''; + if (type === 'Promise') { + typeParams = ''; + type = 'Promise>'; + } // do this late, because we still want object definitions for overridden types if (!this.hasOwnMethod(classDesc, member)) return ''; if (exportMembersAsGlobals) { - const memberType = member.kind === 'method' ? `${args} => ${type}` : type; + const memberType = member.kind === 'method' ? `${typeParams}${args} => ${type}` : type; return `${jsdoc}${exportMembersAsGlobals ? 'export const ' : ''}${member.alias}: ${memberType};` } - return `${jsdoc}${member.alias}${member.required ? '' : '?'}${args}: ${type};` + return `${jsdoc}${member.alias}${member.required ? '' : '?'}${typeParams}${args}: ${type};` }).filter(x => x).join('\n\n')); return parts.join('\n') + '\n'; } diff --git a/utils/generate_types/overrides.d.ts b/utils/generate_types/overrides.d.ts index a018af158bbb5..162db504ce6d8 100644 --- a/utils/generate_types/overrides.d.ts +++ b/utils/generate_types/overrides.d.ts @@ -166,6 +166,10 @@ export interface JSHandle { asElement(): T extends Node ? ElementHandle : null; } +export interface APIResponse { + json(): Promise; +} + export interface ElementHandle extends JSHandle { $(selector: K, options?: { strict: boolean }): Promise | null>; $(selector: string, options?: { strict: boolean }): Promise | null>; diff --git a/utils/generate_types/test/test.ts b/utils/generate_types/test/test.ts index 88d4d00665ea8..dd340a20c7a8f 100644 --- a/utils/generate_types/test/test.ts +++ b/utils/generate_types/test/test.ts @@ -1016,7 +1016,24 @@ declare function takesIsoDate(date: IsoDate): void; const browserType = {} as playwright.BrowserType; const browser = await browserType.launch(); await browser.close(); -}) +})(); + +// APIRequestContext / APIResponse generics +(async () => { + const request = {} as playwright.APIRequestContext; + interface User { id: string; name: string } + + const typed = await request.get('/api/users/42'); + const user = await typed.json(); + const name: string = user.name; + + const posted = await request.post('/api/users', { data: { name: 'x' } }); + const created: User = await posted.json(); + + const untyped = await request.get('/api/users/42'); + const body = await untyped.json(); + console.log(body, name, created); +})(); // exported types import {