mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(har): do not expose HAR types, remove HARResponse fulfill (#14992)
This commit is contained in:
parent
eb87966441
commit
e3da3ebfa4
@ -484,9 +484,9 @@ File path to respond with. The content type will be inferred from file extension
|
|||||||
is resolved relative to the current working directory.
|
is resolved relative to the current working directory.
|
||||||
|
|
||||||
### option: Route.fulfill.response
|
### option: Route.fulfill.response
|
||||||
- `response` <[APIResponse]|[HARResponse]>
|
- `response` <[APIResponse]>
|
||||||
|
|
||||||
[APIResponse] or [HARResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be overridden using fulfill options.
|
[APIResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be overridden using fulfill options.
|
||||||
|
|
||||||
## method: Route.request
|
## method: Route.request
|
||||||
- returns: <[Request]>
|
- returns: <[Request]>
|
||||||
|
@ -21,7 +21,7 @@ import { Frame } from './frame';
|
|||||||
import type { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types';
|
import type { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { mime } from '../utilsBundle';
|
import { mime } from '../utilsBundle';
|
||||||
import { isString, headersObjectToArray, headersArrayToObject } from '../utils';
|
import { isString, headersObjectToArray } from '../utils';
|
||||||
import { ManualPromise } from '../utils/manualPromise';
|
import { ManualPromise } from '../utils/manualPromise';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import type { Page } from './page';
|
import type { Page } from './page';
|
||||||
@ -31,7 +31,6 @@ import type { HeadersArray, URLMatch } from '../common/types';
|
|||||||
import { urlMatches } from '../common/netUtils';
|
import { urlMatches } from '../common/netUtils';
|
||||||
import { MultiMap } from '../utils/multimap';
|
import { MultiMap } from '../utils/multimap';
|
||||||
import { APIResponse } from './fetch';
|
import { APIResponse } from './fetch';
|
||||||
import type { HARResponse } from '../../types/har';
|
|
||||||
|
|
||||||
export type NetworkCookie = {
|
export type NetworkCookie = {
|
||||||
name: string,
|
name: string,
|
||||||
@ -292,7 +291,7 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||||||
this._reportHandled(true);
|
this._reportHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(options: { response?: api.APIResponse | HARResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}) {
|
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}) {
|
||||||
this._checkNotHandled();
|
this._checkNotHandled();
|
||||||
await this._wrapApiCall(async () => {
|
await this._wrapApiCall(async () => {
|
||||||
await this._innerFulfill(options);
|
await this._innerFulfill(options);
|
||||||
@ -300,9 +299,9 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _innerFulfill(options: { response?: api.APIResponse | HARResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}): Promise<void> {
|
private async _innerFulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}): Promise<void> {
|
||||||
let fetchResponseUid;
|
let fetchResponseUid;
|
||||||
let { status: statusOption, headers: headersOption, body, contentType } = options;
|
let { status: statusOption, headers: headersOption, body } = options;
|
||||||
|
|
||||||
if (options.response instanceof APIResponse) {
|
if (options.response instanceof APIResponse) {
|
||||||
statusOption ??= options.response.status();
|
statusOption ??= options.response.status();
|
||||||
@ -313,16 +312,6 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||||||
else
|
else
|
||||||
body = await options.response.body();
|
body = await options.response.body();
|
||||||
}
|
}
|
||||||
} else if (options.response) {
|
|
||||||
const harResponse = options.response as HARResponse;
|
|
||||||
statusOption ??= harResponse.status;
|
|
||||||
headersOption ??= headersArrayToObject(harResponse.headers, false);
|
|
||||||
if (body === undefined && options.path === undefined) {
|
|
||||||
body = harResponse.content.text;
|
|
||||||
contentType ??= harResponse.content.mimeType;
|
|
||||||
if (body !== undefined && harResponse.content.encoding === 'base64')
|
|
||||||
body = Buffer.from(body, 'base64');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBase64 = false;
|
let isBase64 = false;
|
||||||
@ -344,8 +333,8 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
|||||||
const headers: Headers = {};
|
const headers: Headers = {};
|
||||||
for (const header of Object.keys(headersOption || {}))
|
for (const header of Object.keys(headersOption || {}))
|
||||||
headers[header.toLowerCase()] = String(headersOption![header]);
|
headers[header.toLowerCase()] = String(headersOption![header]);
|
||||||
if (contentType)
|
if (options.contentType)
|
||||||
headers['content-type'] = String(contentType);
|
headers['content-type'] = String(options.contentType);
|
||||||
else if (options.path)
|
else if (options.path)
|
||||||
headers['content-type'] = mime.getType(options.path) || 'application/octet-stream';
|
headers['content-type'] = mime.getType(options.path) || 'application/octet-stream';
|
||||||
if (length && !('content-length' in headers))
|
if (length && !('content-length' in headers))
|
||||||
|
@ -24,7 +24,7 @@ import type { DispatcherScope } from './dispatcher';
|
|||||||
import { Dispatcher } from './dispatcher';
|
import { Dispatcher } from './dispatcher';
|
||||||
import { yazl, yauzl } from '../../zipBundle';
|
import { yazl, yauzl } from '../../zipBundle';
|
||||||
import { ZipFile } from '../../utils/zipFile';
|
import { ZipFile } from '../../utils/zipFile';
|
||||||
import type { HAREntry, HARFile } from '../../../types/types';
|
import type { HAREntry, HARFile } from '../../../types/har';
|
||||||
import type { HeadersArray } from '../types';
|
import type { HeadersArray } from '../types';
|
||||||
|
|
||||||
export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.LocalUtilsChannel> implements channels.LocalUtilsChannel {
|
export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.LocalUtilsChannel> implements channels.LocalUtilsChannel {
|
||||||
|
8
packages/playwright-core/types/types.d.ts
vendored
8
packages/playwright-core/types/types.d.ts
vendored
@ -22,8 +22,6 @@ import { Readable } from 'stream';
|
|||||||
import { ReadStream } from 'fs';
|
import { ReadStream } from 'fs';
|
||||||
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from 'playwright-core/types/structs';
|
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from 'playwright-core/types/structs';
|
||||||
|
|
||||||
export * from 'playwright-core/types/har';
|
|
||||||
|
|
||||||
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
||||||
state?: 'visible'|'attached';
|
state?: 'visible'|'attached';
|
||||||
};
|
};
|
||||||
@ -15457,10 +15455,10 @@ export interface Route {
|
|||||||
path?: string;
|
path?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [APIResponse] or [HARResponse] to fulfill route's request with. Individual fields of the response (such as headers) can
|
* [APIResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be overridden
|
||||||
* be overridden using fulfill options.
|
* using fulfill options.
|
||||||
*/
|
*/
|
||||||
response?: APIResponse|HARResponse;
|
response?: APIResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response status code, defaults to `200`.
|
* Response status code, defaults to `200`.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { test as base, expect } from './pageTest';
|
import { test as base, expect } from './pageTest';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import type { HARFile } from '@playwright/test';
|
import type { HARFile, HARResponse } from 'playwright-core/types/har';
|
||||||
|
|
||||||
const it = base.extend<{
|
const it = base.extend<{
|
||||||
// We access test servers at 10.0.2.2 from inside the browser on Android,
|
// We access test servers at 10.0.2.2 from inside the browser on Android,
|
||||||
@ -330,7 +330,14 @@ it('should fulfill with har response', async ({ page, isAndroid, asset }) => {
|
|||||||
const har = JSON.parse(await fs.promises.readFile(harPath, 'utf-8')) as HARFile;
|
const har = JSON.parse(await fs.promises.readFile(harPath, 'utf-8')) as HARFile;
|
||||||
await page.route('**/*', async route => {
|
await page.route('**/*', async route => {
|
||||||
const response = findResponse(har, route.request().url());
|
const response = findResponse(har, route.request().url());
|
||||||
await route.fulfill({ response });
|
const headers = {};
|
||||||
|
for (const { name, value } of response.headers)
|
||||||
|
headers[name] = value;
|
||||||
|
await route.fulfill({
|
||||||
|
status: response.status,
|
||||||
|
headers,
|
||||||
|
body: Buffer.from(response.content.text || '', (response.content.encoding as 'base64' | undefined) || 'utf-8'),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
await page.goto('http://no.playwright/');
|
await page.goto('http://no.playwright/');
|
||||||
// HAR contains a redirect for the script.
|
// HAR contains a redirect for the script.
|
||||||
@ -339,23 +346,7 @@ it('should fulfill with har response', async ({ page, isAndroid, asset }) => {
|
|||||||
await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(0, 255, 255)');
|
await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(0, 255, 255)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should override status when fulfill with response from har', async ({ page, isAndroid, asset }) => {
|
function findResponse(har: HARFile, url: string): HARResponse {
|
||||||
it.fixme(isAndroid);
|
|
||||||
|
|
||||||
const harPath = asset('har-fulfill.har');
|
|
||||||
const har = JSON.parse(await fs.promises.readFile(harPath, 'utf-8')) as HARFile;
|
|
||||||
await page.route('**/*', async route => {
|
|
||||||
const response = findResponse(har, route.request().url());
|
|
||||||
await route.fulfill({ response, status: route.request().url().endsWith('.css') ? 404 : undefined });
|
|
||||||
});
|
|
||||||
await page.goto('http://no.playwright/');
|
|
||||||
// Script should work.
|
|
||||||
expect(await page.evaluate('window.value')).toBe('foo');
|
|
||||||
// 404 should fail the CSS and styles should not apply.
|
|
||||||
await expect(page.locator('body')).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
|
|
||||||
});
|
|
||||||
|
|
||||||
function findResponse(har: HARFile, url: string) {
|
|
||||||
let entry;
|
let entry;
|
||||||
const originalUrl = url;
|
const originalUrl = url;
|
||||||
while (url.trim()) {
|
while (url.trim()) {
|
||||||
|
2
utils/generate_types/overrides.d.ts
vendored
2
utils/generate_types/overrides.d.ts
vendored
@ -21,8 +21,6 @@ import { Readable } from 'stream';
|
|||||||
import { ReadStream } from 'fs';
|
import { ReadStream } from 'fs';
|
||||||
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from 'playwright-core/types/structs';
|
import { Serializable, EvaluationArgument, PageFunction, PageFunctionOn, SmartHandle, ElementHandleForTag, BindingSource } from 'playwright-core/types/structs';
|
||||||
|
|
||||||
export * from 'playwright-core/types/har';
|
|
||||||
|
|
||||||
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
type PageWaitForSelectorOptionsNotHidden = PageWaitForSelectorOptions & {
|
||||||
state?: 'visible'|'attached';
|
state?: 'visible'|'attached';
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user