mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(route): match pattern on the server side (#20410)
This avoids client-side roundtrip for requests that are not handled by any route. Fixes #19607.
This commit is contained in:
parent
ead4989947
commit
d458e84f5b
@ -22,7 +22,7 @@ import { Worker } from './worker';
|
|||||||
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 { assert, isString, headersObjectToArray } from '../utils';
|
import { assert, isString, headersObjectToArray, isRegExp } 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';
|
||||||
@ -641,8 +641,7 @@ export class NetworkRouter {
|
|||||||
|
|
||||||
async route(url: URLMatch, handler: RouteHandlerCallback, options: { times?: number } = {}): Promise<void> {
|
async route(url: URLMatch, handler: RouteHandlerCallback, options: { times?: number } = {}): Promise<void> {
|
||||||
this._routes.unshift(new RouteHandler(this._baseURL, url, handler, options.times));
|
this._routes.unshift(new RouteHandler(this._baseURL, url, handler, options.times));
|
||||||
if (this._routes.length === 1)
|
await this._updateInterception();
|
||||||
await this._owner._channel.setNetworkInterceptionEnabled({ enabled: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback' } = {}): Promise<void> {
|
async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback' } = {}): Promise<void> {
|
||||||
@ -653,8 +652,7 @@ export class NetworkRouter {
|
|||||||
|
|
||||||
async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> {
|
async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> {
|
||||||
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
||||||
if (!this._routes.length)
|
await this._updateInterception();
|
||||||
await this._disableInterception();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleRoute(route: Route) {
|
async handleRoute(route: Route) {
|
||||||
@ -666,15 +664,25 @@ export class NetworkRouter {
|
|||||||
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
||||||
const handled = await routeHandler.handle(route);
|
const handled = await routeHandler.handle(route);
|
||||||
if (!this._routes.length)
|
if (!this._routes.length)
|
||||||
this._owner._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
this._owner._wrapApiCall(() => this._updateInterception(), true).catch(() => {});
|
||||||
if (handled)
|
if (handled)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _disableInterception() {
|
private async _updateInterception() {
|
||||||
await this._owner._channel.setNetworkInterceptionEnabled({ enabled: false });
|
const patterns: channels.BrowserContextSetNetworkInterceptionPatternsParams['patterns'] = [];
|
||||||
|
let all = false;
|
||||||
|
for (const handler of this._routes) {
|
||||||
|
if (isString(handler.url))
|
||||||
|
patterns.push({ glob: handler.url });
|
||||||
|
else if (isRegExp(handler.url))
|
||||||
|
patterns.push({ regexSource: handler.url.source, regexFlags: handler.url.flags });
|
||||||
|
else
|
||||||
|
all = true;
|
||||||
|
}
|
||||||
|
await this._owner._channel.setNetworkInterceptionPatterns(all ? { patterns: [{ glob: '**/*' }] } : { patterns });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,10 +821,14 @@ scheme.BrowserContextSetHTTPCredentialsParams = tObject({
|
|||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
scheme.BrowserContextSetHTTPCredentialsResult = tOptional(tObject({}));
|
scheme.BrowserContextSetHTTPCredentialsResult = tOptional(tObject({}));
|
||||||
scheme.BrowserContextSetNetworkInterceptionEnabledParams = tObject({
|
scheme.BrowserContextSetNetworkInterceptionPatternsParams = tObject({
|
||||||
enabled: tBoolean,
|
patterns: tArray(tObject({
|
||||||
|
glob: tOptional(tString),
|
||||||
|
regexSource: tOptional(tString),
|
||||||
|
regexFlags: tOptional(tString),
|
||||||
|
})),
|
||||||
});
|
});
|
||||||
scheme.BrowserContextSetNetworkInterceptionEnabledResult = tOptional(tObject({}));
|
scheme.BrowserContextSetNetworkInterceptionPatternsResult = tOptional(tObject({}));
|
||||||
scheme.BrowserContextSetOfflineParams = tObject({
|
scheme.BrowserContextSetOfflineParams = tObject({
|
||||||
offline: tBoolean,
|
offline: tBoolean,
|
||||||
});
|
});
|
||||||
@ -1035,10 +1039,14 @@ scheme.PageSetExtraHTTPHeadersParams = tObject({
|
|||||||
headers: tArray(tType('NameValue')),
|
headers: tArray(tType('NameValue')),
|
||||||
});
|
});
|
||||||
scheme.PageSetExtraHTTPHeadersResult = tOptional(tObject({}));
|
scheme.PageSetExtraHTTPHeadersResult = tOptional(tObject({}));
|
||||||
scheme.PageSetNetworkInterceptionEnabledParams = tObject({
|
scheme.PageSetNetworkInterceptionPatternsParams = tObject({
|
||||||
enabled: tBoolean,
|
patterns: tArray(tObject({
|
||||||
|
glob: tOptional(tString),
|
||||||
|
regexSource: tOptional(tString),
|
||||||
|
regexFlags: tOptional(tString),
|
||||||
|
})),
|
||||||
});
|
});
|
||||||
scheme.PageSetNetworkInterceptionEnabledResult = tOptional(tObject({}));
|
scheme.PageSetNetworkInterceptionPatternsResult = tOptional(tObject({}));
|
||||||
scheme.PageSetViewportSizeParams = tObject({
|
scheme.PageSetViewportSizeParams = tObject({
|
||||||
viewportSize: tObject({
|
viewportSize: tObject({
|
||||||
width: tNumber,
|
width: tNumber,
|
||||||
|
@ -461,6 +461,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
const page = await this.newPage(internalMetadata);
|
const page = await this.newPage(internalMetadata);
|
||||||
await page._setServerRequestInterceptor(handler => {
|
await page._setServerRequestInterceptor(handler => {
|
||||||
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
for (const origin of this._origins) {
|
for (const origin of this._origins) {
|
||||||
const originStorage: channels.OriginStorage = { origin, localStorage: [] };
|
const originStorage: channels.OriginStorage = { origin, localStorage: [] };
|
||||||
@ -489,6 +490,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
page = page || await this.newPage(internalMetadata);
|
page = page || await this.newPage(internalMetadata);
|
||||||
await page._setServerRequestInterceptor(handler => {
|
await page._setServerRequestInterceptor(handler => {
|
||||||
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const origin of new Set([...oldOrigins, ...newOrigins.keys()])) {
|
for (const origin of new Set([...oldOrigins, ...newOrigins.keys()])) {
|
||||||
@ -523,6 +525,7 @@ export abstract class BrowserContext extends SdkObject {
|
|||||||
const page = await this.newPage(internalMetadata);
|
const page = await this.newPage(internalMetadata);
|
||||||
await page._setServerRequestInterceptor(handler => {
|
await page._setServerRequestInterceptor(handler => {
|
||||||
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
handler.fulfill({ body: '<html></html>' }).catch(() => {});
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
for (const originState of state.origins) {
|
for (const originState of state.origins) {
|
||||||
const frame = page.mainFrame();
|
const frame = page.mainFrame();
|
||||||
|
@ -112,10 +112,8 @@ export class CRServiceWorker extends Worker {
|
|||||||
this._browserContext.emit(BrowserContext.Events.Request, request);
|
this._browserContext.emit(BrowserContext.Events.Request, request);
|
||||||
if (route) {
|
if (route) {
|
||||||
const r = new network.Route(request, route);
|
const r = new network.Route(request, route);
|
||||||
if (this._browserContext._requestInterceptor) {
|
if (this._browserContext._requestInterceptor?.(r, request))
|
||||||
this._browserContext._requestInterceptor(r, request);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
r.continue();
|
r.continue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import type { Request, Response } from '../network';
|
|||||||
import { TracingDispatcher } from './tracingDispatcher';
|
import { TracingDispatcher } from './tracingDispatcher';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { createGuid } from '../../utils';
|
import { createGuid, urlMatches } from '../../utils';
|
||||||
import { WritableStreamDispatcher } from './writableStreamDispatcher';
|
import { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||||
|
|
||||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope> implements channels.BrowserContextChannel {
|
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope> implements channels.BrowserContextChannel {
|
||||||
@ -216,13 +216,18 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
|||||||
await this._context.addInitScript(params.source);
|
await this._context.addInitScript(params.source);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNetworkInterceptionEnabled(params: channels.BrowserContextSetNetworkInterceptionEnabledParams): Promise<void> {
|
async setNetworkInterceptionPatterns(params: channels.BrowserContextSetNetworkInterceptionPatternsParams): Promise<void> {
|
||||||
if (!params.enabled) {
|
if (!params.patterns.length) {
|
||||||
await this._context.setRequestInterceptor(undefined);
|
await this._context.setRequestInterceptor(undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags!) : pattern.glob!);
|
||||||
await this._context.setRequestInterceptor((route, request) => {
|
await this._context.setRequestInterceptor((route, request) => {
|
||||||
|
const matchesSome = urlMatchers.some(urlMatch => urlMatches(this._context._options.baseURL, request.url(), urlMatch));
|
||||||
|
if (!matchesSome)
|
||||||
|
return false;
|
||||||
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this, request), route) });
|
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this, request), route) });
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import type { CallMetadata } from '../instrumentation';
|
|||||||
import type { Artifact } from '../artifact';
|
import type { Artifact } from '../artifact';
|
||||||
import { ArtifactDispatcher } from './artifactDispatcher';
|
import { ArtifactDispatcher } from './artifactDispatcher';
|
||||||
import type { Download } from '../download';
|
import type { Download } from '../download';
|
||||||
import { createGuid } from '../../utils';
|
import { createGuid, urlMatches } from '../../utils';
|
||||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||||
|
|
||||||
export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, BrowserContextDispatcher> implements channels.PageChannel {
|
export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, BrowserContextDispatcher> implements channels.PageChannel {
|
||||||
@ -154,13 +154,18 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
|||||||
await this._page.addInitScript(params.source);
|
await this._page.addInitScript(params.source);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNetworkInterceptionEnabled(params: channels.PageSetNetworkInterceptionEnabledParams, metadata: CallMetadata): Promise<void> {
|
async setNetworkInterceptionPatterns(params: channels.PageSetNetworkInterceptionPatternsParams, metadata: CallMetadata): Promise<void> {
|
||||||
if (!params.enabled) {
|
if (!params.patterns.length) {
|
||||||
await this._page.setClientRequestInterceptor(undefined);
|
await this._page.setClientRequestInterceptor(undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags!) : pattern.glob!);
|
||||||
await this._page.setClientRequestInterceptor((route, request) => {
|
await this._page.setClientRequestInterceptor((route, request) => {
|
||||||
|
const matchesSome = urlMatchers.some(urlMatch => urlMatches(this._page._browserContext._options.baseURL, request.url(), urlMatch));
|
||||||
|
if (!matchesSome)
|
||||||
|
return false;
|
||||||
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this.parentScope(), request), route) });
|
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this.parentScope(), request), route) });
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,18 +304,12 @@ export class FrameManager {
|
|||||||
this._page.emitOnContext(BrowserContext.Events.Request, request);
|
this._page.emitOnContext(BrowserContext.Events.Request, request);
|
||||||
if (route) {
|
if (route) {
|
||||||
const r = new network.Route(request, route);
|
const r = new network.Route(request, route);
|
||||||
if (this._page._serverRequestInterceptor) {
|
if (this._page._serverRequestInterceptor?.(r, request))
|
||||||
this._page._serverRequestInterceptor(r, request);
|
|
||||||
return;
|
return;
|
||||||
}
|
if (this._page._clientRequestInterceptor?.(r, request))
|
||||||
if (this._page._clientRequestInterceptor) {
|
|
||||||
this._page._clientRequestInterceptor(r, request);
|
|
||||||
return;
|
return;
|
||||||
}
|
if (this._page._browserContext._requestInterceptor?.(r, request))
|
||||||
if (this._page._browserContext._requestInterceptor) {
|
|
||||||
this._page._browserContext._requestInterceptor(r, request);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
r.continue();
|
r.continue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ export class Route extends SdkObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RouteHandler = (route: Route, request: Request) => void;
|
export type RouteHandler = (route: Route, request: Request) => boolean;
|
||||||
|
|
||||||
type GetResponseBodyCallback = () => Promise<Buffer>;
|
type GetResponseBodyCallback = () => Promise<Buffer>;
|
||||||
|
|
||||||
|
@ -82,12 +82,14 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
|
|||||||
await installAppIcon(this._page);
|
await installAppIcon(this._page);
|
||||||
await syncLocalStorageWithSettings(this._page, 'recorder');
|
await syncLocalStorageWithSettings(this._page, 'recorder');
|
||||||
|
|
||||||
await this._page._setServerRequestInterceptor(async route => {
|
await this._page._setServerRequestInterceptor(route => {
|
||||||
if (route.request().url().startsWith('https://playwright/')) {
|
if (!route.request().url().startsWith('https://playwright/'))
|
||||||
|
return false;
|
||||||
|
|
||||||
const uri = route.request().url().substring('https://playwright/'.length);
|
const uri = route.request().url().substring('https://playwright/'.length);
|
||||||
const file = require.resolve('../../webpack/recorder/' + uri);
|
const file = require.resolve('../../webpack/recorder/' + uri);
|
||||||
const buffer = await fs.promises.readFile(file);
|
fs.promises.readFile(file).then(buffer => {
|
||||||
await route.fulfill({
|
route.fulfill({
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: [
|
headers: [
|
||||||
{ name: 'Content-Type', value: mime.getType(path.extname(file)) || 'application/octet-stream' }
|
{ name: 'Content-Type', value: mime.getType(path.extname(file)) || 'application/octet-stream' }
|
||||||
@ -95,9 +97,8 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
|
|||||||
body: buffer.toString('base64'),
|
body: buffer.toString('base64'),
|
||||||
isBase64: true
|
isBase64: true
|
||||||
});
|
});
|
||||||
return;
|
});
|
||||||
}
|
return true;
|
||||||
await route.continue();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await this._page.exposeBinding('dispatch', false, (_, data: any) => this.emit('event', data));
|
await this._page.exposeBinding('dispatch', false, (_, data: any) => this.emit('event', data));
|
||||||
|
@ -1371,7 +1371,7 @@ export interface BrowserContextChannel extends BrowserContextEventTarget, EventT
|
|||||||
setExtraHTTPHeaders(params: BrowserContextSetExtraHTTPHeadersParams, metadata?: Metadata): Promise<BrowserContextSetExtraHTTPHeadersResult>;
|
setExtraHTTPHeaders(params: BrowserContextSetExtraHTTPHeadersParams, metadata?: Metadata): Promise<BrowserContextSetExtraHTTPHeadersResult>;
|
||||||
setGeolocation(params: BrowserContextSetGeolocationParams, metadata?: Metadata): Promise<BrowserContextSetGeolocationResult>;
|
setGeolocation(params: BrowserContextSetGeolocationParams, metadata?: Metadata): Promise<BrowserContextSetGeolocationResult>;
|
||||||
setHTTPCredentials(params: BrowserContextSetHTTPCredentialsParams, metadata?: Metadata): Promise<BrowserContextSetHTTPCredentialsResult>;
|
setHTTPCredentials(params: BrowserContextSetHTTPCredentialsParams, metadata?: Metadata): Promise<BrowserContextSetHTTPCredentialsResult>;
|
||||||
setNetworkInterceptionEnabled(params: BrowserContextSetNetworkInterceptionEnabledParams, metadata?: Metadata): Promise<BrowserContextSetNetworkInterceptionEnabledResult>;
|
setNetworkInterceptionPatterns(params: BrowserContextSetNetworkInterceptionPatternsParams, metadata?: Metadata): Promise<BrowserContextSetNetworkInterceptionPatternsResult>;
|
||||||
setOffline(params: BrowserContextSetOfflineParams, metadata?: Metadata): Promise<BrowserContextSetOfflineResult>;
|
setOffline(params: BrowserContextSetOfflineParams, metadata?: Metadata): Promise<BrowserContextSetOfflineResult>;
|
||||||
storageState(params?: BrowserContextStorageStateParams, metadata?: Metadata): Promise<BrowserContextStorageStateResult>;
|
storageState(params?: BrowserContextStorageStateParams, metadata?: Metadata): Promise<BrowserContextStorageStateResult>;
|
||||||
pause(params?: BrowserContextPauseParams, metadata?: Metadata): Promise<BrowserContextPauseResult>;
|
pause(params?: BrowserContextPauseParams, metadata?: Metadata): Promise<BrowserContextPauseResult>;
|
||||||
@ -1523,13 +1523,17 @@ export type BrowserContextSetHTTPCredentialsOptions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export type BrowserContextSetHTTPCredentialsResult = void;
|
export type BrowserContextSetHTTPCredentialsResult = void;
|
||||||
export type BrowserContextSetNetworkInterceptionEnabledParams = {
|
export type BrowserContextSetNetworkInterceptionPatternsParams = {
|
||||||
enabled: boolean,
|
patterns: {
|
||||||
|
glob?: string,
|
||||||
|
regexSource?: string,
|
||||||
|
regexFlags?: string,
|
||||||
|
}[],
|
||||||
};
|
};
|
||||||
export type BrowserContextSetNetworkInterceptionEnabledOptions = {
|
export type BrowserContextSetNetworkInterceptionPatternsOptions = {
|
||||||
|
|
||||||
};
|
};
|
||||||
export type BrowserContextSetNetworkInterceptionEnabledResult = void;
|
export type BrowserContextSetNetworkInterceptionPatternsResult = void;
|
||||||
export type BrowserContextSetOfflineParams = {
|
export type BrowserContextSetOfflineParams = {
|
||||||
offline: boolean,
|
offline: boolean,
|
||||||
};
|
};
|
||||||
@ -1673,7 +1677,7 @@ export interface PageChannel extends PageEventTarget, EventTargetChannel {
|
|||||||
expectScreenshot(params: PageExpectScreenshotParams, metadata?: Metadata): Promise<PageExpectScreenshotResult>;
|
expectScreenshot(params: PageExpectScreenshotParams, metadata?: Metadata): Promise<PageExpectScreenshotResult>;
|
||||||
screenshot(params: PageScreenshotParams, metadata?: Metadata): Promise<PageScreenshotResult>;
|
screenshot(params: PageScreenshotParams, metadata?: Metadata): Promise<PageScreenshotResult>;
|
||||||
setExtraHTTPHeaders(params: PageSetExtraHTTPHeadersParams, metadata?: Metadata): Promise<PageSetExtraHTTPHeadersResult>;
|
setExtraHTTPHeaders(params: PageSetExtraHTTPHeadersParams, metadata?: Metadata): Promise<PageSetExtraHTTPHeadersResult>;
|
||||||
setNetworkInterceptionEnabled(params: PageSetNetworkInterceptionEnabledParams, metadata?: Metadata): Promise<PageSetNetworkInterceptionEnabledResult>;
|
setNetworkInterceptionPatterns(params: PageSetNetworkInterceptionPatternsParams, metadata?: Metadata): Promise<PageSetNetworkInterceptionPatternsResult>;
|
||||||
setViewportSize(params: PageSetViewportSizeParams, metadata?: Metadata): Promise<PageSetViewportSizeResult>;
|
setViewportSize(params: PageSetViewportSizeParams, metadata?: Metadata): Promise<PageSetViewportSizeResult>;
|
||||||
keyboardDown(params: PageKeyboardDownParams, metadata?: Metadata): Promise<PageKeyboardDownResult>;
|
keyboardDown(params: PageKeyboardDownParams, metadata?: Metadata): Promise<PageKeyboardDownResult>;
|
||||||
keyboardUp(params: PageKeyboardUpParams, metadata?: Metadata): Promise<PageKeyboardUpResult>;
|
keyboardUp(params: PageKeyboardUpParams, metadata?: Metadata): Promise<PageKeyboardUpResult>;
|
||||||
@ -1918,13 +1922,17 @@ export type PageSetExtraHTTPHeadersOptions = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
export type PageSetExtraHTTPHeadersResult = void;
|
export type PageSetExtraHTTPHeadersResult = void;
|
||||||
export type PageSetNetworkInterceptionEnabledParams = {
|
export type PageSetNetworkInterceptionPatternsParams = {
|
||||||
enabled: boolean,
|
patterns: {
|
||||||
|
glob?: string,
|
||||||
|
regexSource?: string,
|
||||||
|
regexFlags?: string,
|
||||||
|
}[],
|
||||||
};
|
};
|
||||||
export type PageSetNetworkInterceptionEnabledOptions = {
|
export type PageSetNetworkInterceptionPatternsOptions = {
|
||||||
|
|
||||||
};
|
};
|
||||||
export type PageSetNetworkInterceptionEnabledResult = void;
|
export type PageSetNetworkInterceptionPatternsResult = void;
|
||||||
export type PageSetViewportSizeParams = {
|
export type PageSetViewportSizeParams = {
|
||||||
viewportSize: {
|
viewportSize: {
|
||||||
width: number,
|
width: number,
|
||||||
|
@ -1032,9 +1032,16 @@ BrowserContext:
|
|||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
|
|
||||||
setNetworkInterceptionEnabled:
|
setNetworkInterceptionPatterns:
|
||||||
parameters:
|
parameters:
|
||||||
enabled: boolean
|
patterns:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
glob: string?
|
||||||
|
regexSource: string?
|
||||||
|
regexFlags: string?
|
||||||
|
|
||||||
setOffline:
|
setOffline:
|
||||||
parameters:
|
parameters:
|
||||||
@ -1311,9 +1318,16 @@ Page:
|
|||||||
type: array
|
type: array
|
||||||
items: NameValue
|
items: NameValue
|
||||||
|
|
||||||
setNetworkInterceptionEnabled:
|
setNetworkInterceptionPatterns:
|
||||||
parameters:
|
parameters:
|
||||||
enabled: boolean
|
patterns:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
glob: string?
|
||||||
|
regexSource: string?
|
||||||
|
regexFlags: string?
|
||||||
|
|
||||||
setViewportSize:
|
setViewportSize:
|
||||||
parameters:
|
parameters:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user