chore(rpc): pass more network tests (#2762)
This commit is contained in:
parent
0963c1979e
commit
3a7d629c61
|
|
@ -361,14 +361,12 @@ class InterceptableRequest implements network.RouteDelegate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(response: types.FulfillResponse) {
|
async fulfill(response: types.NormalizedFulfillResponse) {
|
||||||
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
|
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
|
||||||
|
|
||||||
const responseHeaders: { [s: string]: string; } = {};
|
const responseHeaders: { [s: string]: string; } = {};
|
||||||
if (response.headers) {
|
for (const header of Object.keys(response.headers))
|
||||||
for (const header of Object.keys(response.headers))
|
responseHeaders[header.toLowerCase()] = response.headers[header];
|
||||||
responseHeaders[header.toLowerCase()] = response.headers[header];
|
|
||||||
}
|
|
||||||
if (response.contentType)
|
if (response.contentType)
|
||||||
responseHeaders['content-type'] = response.contentType;
|
responseHeaders['content-type'] = response.contentType;
|
||||||
if (responseBody && !('content-length' in responseHeaders))
|
if (responseBody && !('content-length' in responseHeaders))
|
||||||
|
|
@ -378,8 +376,8 @@ class InterceptableRequest implements network.RouteDelegate {
|
||||||
// or the page was closed. We should tolerate these errors.
|
// or the page was closed. We should tolerate these errors.
|
||||||
await this._client._sendMayFail('Fetch.fulfillRequest', {
|
await this._client._sendMayFail('Fetch.fulfillRequest', {
|
||||||
requestId: this._interceptionId!,
|
requestId: this._interceptionId!,
|
||||||
responseCode: response.status || 200,
|
responseCode: response.status,
|
||||||
responsePhrase: network.STATUS_TEXTS[String(response.status || 200)],
|
responsePhrase: network.STATUS_TEXTS[String(response.status)],
|
||||||
responseHeaders: headersArray(responseHeaders),
|
responseHeaders: headersArray(responseHeaders),
|
||||||
body: responseBody ? responseBody.toString('base64') : undefined,
|
body: responseBody ? responseBody.toString('base64') : undefined,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -172,14 +172,12 @@ class InterceptableRequest implements network.RouteDelegate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(response: types.FulfillResponse) {
|
async fulfill(response: types.NormalizedFulfillResponse) {
|
||||||
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
|
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
|
||||||
|
|
||||||
const responseHeaders: { [s: string]: string; } = {};
|
const responseHeaders: { [s: string]: string; } = {};
|
||||||
if (response.headers) {
|
for (const header of Object.keys(response.headers))
|
||||||
for (const header of Object.keys(response.headers))
|
responseHeaders[header.toLowerCase()] = response.headers[header];
|
||||||
responseHeaders[header.toLowerCase()] = response.headers[header];
|
|
||||||
}
|
|
||||||
if (response.contentType)
|
if (response.contentType)
|
||||||
responseHeaders['content-type'] = response.contentType;
|
responseHeaders['content-type'] = response.contentType;
|
||||||
if (responseBody && !('content-length' in responseHeaders))
|
if (responseBody && !('content-length' in responseHeaders))
|
||||||
|
|
@ -187,8 +185,8 @@ class InterceptableRequest implements network.RouteDelegate {
|
||||||
|
|
||||||
await this._session.sendMayFail('Network.fulfillInterceptedRequest', {
|
await this._session.sendMayFail('Network.fulfillInterceptedRequest', {
|
||||||
requestId: this._id,
|
requestId: this._id,
|
||||||
status: response.status || 200,
|
status: response.status,
|
||||||
statusText: network.STATUS_TEXTS[String(response.status || 200)] || '',
|
statusText: network.STATUS_TEXTS[String(response.status)] || '',
|
||||||
headers: headersArray(responseHeaders),
|
headers: headersArray(responseHeaders),
|
||||||
base64body: responseBody ? responseBody.toString('base64') : undefined,
|
base64body: responseBody ? responseBody.toString('base64') : undefined,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as mime from 'mime';
|
|
||||||
import * as util from 'util';
|
|
||||||
import * as frames from './frames';
|
import * as frames from './frames';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import { assert, helper } from './helper';
|
import { assert, helper } from './helper';
|
||||||
import { URLSearchParams } from 'url';
|
import { URLSearchParams } from 'url';
|
||||||
|
import { normalizeFulfillParameters } from './rpc/serializers';
|
||||||
|
|
||||||
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
|
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
|
||||||
const parsedURLs = urls.map(s => new URL(s));
|
const parsedURLs = urls.map(s => new URL(s));
|
||||||
|
|
@ -220,15 +218,7 @@ export class Route {
|
||||||
async fulfill(response: types.FulfillResponse & { path?: string }) {
|
async fulfill(response: types.FulfillResponse & { path?: string }) {
|
||||||
assert(!this._handled, 'Route is already handled!');
|
assert(!this._handled, 'Route is already handled!');
|
||||||
this._handled = true;
|
this._handled = true;
|
||||||
if (response.path) {
|
await this._delegate.fulfill(await normalizeFulfillParameters(response));
|
||||||
response = {
|
|
||||||
status: response.status,
|
|
||||||
headers: response.headers,
|
|
||||||
contentType: mime.getType(response.path) || 'application/octet-stream',
|
|
||||||
body: await util.promisify(fs.readFile)(response.path)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
await this._delegate.fulfill(response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
|
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
|
||||||
|
|
@ -325,7 +315,7 @@ export class Response {
|
||||||
|
|
||||||
export interface RouteDelegate {
|
export interface RouteDelegate {
|
||||||
abort(errorCode: string): Promise<void>;
|
abort(errorCode: string): Promise<void>;
|
||||||
fulfill(response: types.FulfillResponse): Promise<void>;
|
fulfill(response: types.NormalizedFulfillResponse): Promise<void>;
|
||||||
continue(overrides: { method?: string; headers?: types.Headers; postData?: string; }): Promise<void>;
|
continue(overrides: { method?: string; headers?: types.Headers; postData?: string; }): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
|
|
||||||
|
export type Binary = string;
|
||||||
|
|
||||||
export interface Channel extends EventEmitter {
|
export interface Channel extends EventEmitter {
|
||||||
_type: string;
|
_type: string;
|
||||||
_guid: string;
|
_guid: string;
|
||||||
|
|
@ -101,7 +103,7 @@ export interface PageChannel extends Channel {
|
||||||
goForward(params: { options?: types.NavigateOptions }): Promise<ResponseChannel | null>;
|
goForward(params: { options?: types.NavigateOptions }): Promise<ResponseChannel | null>;
|
||||||
opener(): Promise<PageChannel | null>;
|
opener(): Promise<PageChannel | null>;
|
||||||
reload(params: { options?: types.NavigateOptions }): Promise<ResponseChannel | null>;
|
reload(params: { options?: types.NavigateOptions }): Promise<ResponseChannel | null>;
|
||||||
screenshot(params: { options?: types.ScreenshotOptions }): Promise<string>;
|
screenshot(params: { options?: types.ScreenshotOptions }): Promise<Binary>;
|
||||||
setExtraHTTPHeaders(params: { headers: types.Headers }): Promise<void>;
|
setExtraHTTPHeaders(params: { headers: types.Headers }): Promise<void>;
|
||||||
setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise<void>;
|
setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise<void>;
|
||||||
setViewportSize(params: { viewportSize: types.Size }): Promise<void>;
|
setViewportSize(params: { viewportSize: types.Size }): Promise<void>;
|
||||||
|
|
@ -199,7 +201,7 @@ export interface ElementHandleChannel extends JSHandleChannel {
|
||||||
press(params: { key: string; options?: { delay?: number } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise<void>;
|
press(params: { key: string; options?: { delay?: number } & types.TimeoutOptions & { noWaitAfter?: boolean } }): Promise<void>;
|
||||||
querySelector(params: { selector: string }): Promise<ElementHandleChannel | null>;
|
querySelector(params: { selector: string }): Promise<ElementHandleChannel | null>;
|
||||||
querySelectorAll(params: { selector: string }): Promise<ElementHandleChannel[]>;
|
querySelectorAll(params: { selector: string }): Promise<ElementHandleChannel[]>;
|
||||||
screenshot(params: { options?: types.ElementScreenshotOptions }): Promise<string>;
|
screenshot(params: { options?: types.ElementScreenshotOptions }): Promise<Binary>;
|
||||||
scrollIntoViewIfNeeded(params: { options?: types.TimeoutOptions }): Promise<void>;
|
scrollIntoViewIfNeeded(params: { options?: types.TimeoutOptions }): Promise<void>;
|
||||||
selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null; options?: types.NavigatingActionWaitOptions }): string[] | Promise<string[]>;
|
selectOption(params: { values: string | ElementHandleChannel | types.SelectOption | string[] | ElementHandleChannel[] | types.SelectOption[] | null; options?: types.NavigatingActionWaitOptions }): string[] | Promise<string[]>;
|
||||||
selectText(params: { options?: types.TimeoutOptions }): Promise<void>;
|
selectText(params: { options?: types.TimeoutOptions }): Promise<void>;
|
||||||
|
|
@ -228,7 +230,14 @@ export type RequestInitializer = {
|
||||||
export interface RouteChannel extends Channel {
|
export interface RouteChannel extends Channel {
|
||||||
abort(params: { errorCode: string }): Promise<void>;
|
abort(params: { errorCode: string }): Promise<void>;
|
||||||
continue(params: { overrides: { method?: string, headers?: types.Headers, postData?: string } }): Promise<void>;
|
continue(params: { overrides: { method?: string, headers?: types.Headers, postData?: string } }): Promise<void>;
|
||||||
fulfill(params: { response: types.FulfillResponse & { path?: string } }): Promise<void>;
|
fulfill(params: {
|
||||||
|
response: {
|
||||||
|
status?: number,
|
||||||
|
headers?: types.Headers,
|
||||||
|
contentType?: string,
|
||||||
|
body: Binary,
|
||||||
|
}
|
||||||
|
}): Promise<void>;
|
||||||
}
|
}
|
||||||
export type RouteInitializer = {
|
export type RouteInitializer = {
|
||||||
request: RequestChannel,
|
request: RequestChannel,
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
||||||
const context = await this.newContext(options);
|
const context = await this.newContext(options);
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
page._ownedContext = context;
|
page._ownedContext = context;
|
||||||
|
context._ownerPage = page;
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||||
readonly _bindings = new Map<string, frames.FunctionWithSource>();
|
readonly _bindings = new Map<string, frames.FunctionWithSource>();
|
||||||
private _pendingWaitForEvents = new Map<(error: Error) => void, string>();
|
private _pendingWaitForEvents = new Map<(error: Error) => void, string>();
|
||||||
_timeoutSettings = new TimeoutSettings();
|
_timeoutSettings = new TimeoutSettings();
|
||||||
|
_ownerPage: Page | undefined;
|
||||||
|
|
||||||
static from(context: BrowserContextChannel): BrowserContext {
|
static from(context: BrowserContextChannel): BrowserContext {
|
||||||
return context._object;
|
return context._object;
|
||||||
|
|
@ -91,6 +92,8 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||||
}
|
}
|
||||||
|
|
||||||
async newPage(): Promise<Page> {
|
async newPage(): Promise<Page> {
|
||||||
|
if (this._ownerPage)
|
||||||
|
throw new Error('Please use browser.newContext()');
|
||||||
return Page.from(await this._channel.newPage());
|
return Page.from(await this._channel.newPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleIni
|
||||||
}
|
}
|
||||||
|
|
||||||
async jsonValue(): Promise<T> {
|
async jsonValue(): Promise<T> {
|
||||||
return await this._channel.jsonValue();
|
return parseResult(await this._channel.jsonValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement(): ElementHandle | null {
|
asElement(): ElementHandle | null {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import { RequestChannel, ResponseChannel, RouteChannel, RequestInitializer, Resp
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { Frame } from './frame';
|
import { Frame } from './frame';
|
||||||
import { Connection } from '../connection';
|
import { Connection } from '../connection';
|
||||||
|
import { normalizeFulfillParameters } from '../serializers';
|
||||||
|
|
||||||
export type NetworkCookie = {
|
export type NetworkCookie = {
|
||||||
name: string,
|
name: string,
|
||||||
|
|
@ -150,7 +151,13 @@ export class Route extends ChannelOwner<RouteChannel, RouteInitializer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(response: types.FulfillResponse & { path?: string }) {
|
async fulfill(response: types.FulfillResponse & { path?: string }) {
|
||||||
await this._channel.fulfill({ response });
|
const normalized = await normalizeFulfillParameters(response);
|
||||||
|
await this._channel.fulfill({ response: {
|
||||||
|
status: normalized.status,
|
||||||
|
headers: normalized.headers,
|
||||||
|
contentType: normalized.contentType,
|
||||||
|
body: (typeof normalized.body === 'string' ? Buffer.from(normalized.body) : normalized.body).toString('base64')
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
|
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setViewportSize(viewportSize: types.Size) {
|
async setViewportSize(viewportSize: types.Size) {
|
||||||
|
this._viewportSize = viewportSize;
|
||||||
await this._channel.setViewportSize({ viewportSize });
|
await this._channel.setViewportSize({ viewportSize });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,3 +62,20 @@ export async function normalizeFilePayloads(files: string | types.FilePayload |
|
||||||
}
|
}
|
||||||
return filePayloads;
|
return filePayloads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function normalizeFulfillParameters(params: types.FulfillResponse & { path?: string }): Promise<types.NormalizedFulfillResponse> {
|
||||||
|
if (params.path) {
|
||||||
|
return {
|
||||||
|
status: params.status || 200,
|
||||||
|
headers: params.headers || {},
|
||||||
|
contentType: mime.getType(params.path) || 'application/octet-stream',
|
||||||
|
body: await util.promisify(fs.readFile)(params.path)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: params.status || 200,
|
||||||
|
headers: params.headers || {},
|
||||||
|
contentType: params.contentType,
|
||||||
|
body: params.body || ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
|
||||||
}
|
}
|
||||||
|
|
||||||
async jsonValue(): Promise<any> {
|
async jsonValue(): Promise<any> {
|
||||||
return this._object.jsonValue();
|
return serializeResult(await this._object.jsonValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispose() {
|
async dispose() {
|
||||||
|
|
@ -55,7 +55,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseArgument(arg: { value: any, guids: JSHandleDispatcher[] }): any {
|
export function parseArgument(arg: { value: any, guids: JSHandleDispatcher[] }): any {
|
||||||
return convertDispatchersToObjects(parseEvaluationResultValue(arg.value, arg.guids));
|
return parseEvaluationResultValue(arg.value, convertDispatchersToObjects(arg.guids));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serializeResult(arg: any): any {
|
export function serializeResult(arg: any): any {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import { Request, Response, Route } from '../../network';
|
import { Request, Response, Route } from '../../network';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
import { RequestChannel, ResponseChannel, RouteChannel, ResponseInitializer, RequestInitializer, RouteInitializer } from '../channels';
|
import { RequestChannel, ResponseChannel, RouteChannel, ResponseInitializer, RequestInitializer, RouteInitializer, Binary } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { FrameDispatcher } from './frameDispatcher';
|
import { FrameDispatcher } from './frameDispatcher';
|
||||||
|
|
||||||
|
|
@ -102,8 +102,14 @@ export class RouteDispatcher extends Dispatcher<Route, RouteInitializer> impleme
|
||||||
await this._object.continue(params.overrides);
|
await this._object.continue(params.overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(params: { response: types.FulfillResponse & { path?: string } }): Promise<void> {
|
async fulfill(params: { response: { status?: number, headers?: types.Headers, contentType?: string, body: Binary } }): Promise<void> {
|
||||||
await this._object.fulfill(params.response);
|
const { response } = params;
|
||||||
|
await this._object.fulfill({
|
||||||
|
status: response.status,
|
||||||
|
headers: response.headers,
|
||||||
|
contentType: response.contentType,
|
||||||
|
body: Buffer.from(response.body, 'base64'),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async abort(params: { errorCode: string }): Promise<void> {
|
async abort(params: { errorCode: string }): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,13 @@ export type FulfillResponse = {
|
||||||
body?: string | Buffer,
|
body?: string | Buffer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type NormalizedFulfillResponse = {
|
||||||
|
status: number,
|
||||||
|
headers: Headers,
|
||||||
|
contentType?: string,
|
||||||
|
body: string | Buffer,
|
||||||
|
};
|
||||||
|
|
||||||
export type NetworkCookie = {
|
export type NetworkCookie = {
|
||||||
name: string,
|
name: string,
|
||||||
value: string,
|
value: string,
|
||||||
|
|
|
||||||
|
|
@ -66,17 +66,15 @@ export class WKInterceptableRequest implements network.RouteDelegate {
|
||||||
await this._session.sendMayFail('Network.interceptRequestWithError', { requestId: this._requestId, errorType });
|
await this._session.sendMayFail('Network.interceptRequestWithError', { requestId: this._requestId, errorType });
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(response: types.FulfillResponse) {
|
async fulfill(response: types.NormalizedFulfillResponse) {
|
||||||
await this._interceptedPromise;
|
await this._interceptedPromise;
|
||||||
|
|
||||||
const base64Encoded = !!response.body && !helper.isString(response.body);
|
const base64Encoded = !!response.body && !helper.isString(response.body);
|
||||||
const responseBody = response.body ? (base64Encoded ? response.body.toString('base64') : response.body as string) : '';
|
const responseBody = response.body ? (base64Encoded ? response.body.toString('base64') : response.body as string) : '';
|
||||||
|
|
||||||
const responseHeaders: { [s: string]: string; } = {};
|
const responseHeaders: { [s: string]: string; } = {};
|
||||||
if (response.headers) {
|
for (const header of Object.keys(response.headers))
|
||||||
for (const header of Object.keys(response.headers))
|
responseHeaders[header.toLowerCase()] = String(response.headers[header]);
|
||||||
responseHeaders[header.toLowerCase()] = String(response.headers[header]);
|
|
||||||
}
|
|
||||||
let mimeType = base64Encoded ? 'application/octet-stream' : 'text/plain';
|
let mimeType = base64Encoded ? 'application/octet-stream' : 'text/plain';
|
||||||
if (response.contentType) {
|
if (response.contentType) {
|
||||||
responseHeaders['content-type'] = response.contentType;
|
responseHeaders['content-type'] = response.contentType;
|
||||||
|
|
@ -93,8 +91,8 @@ export class WKInterceptableRequest implements network.RouteDelegate {
|
||||||
// or the page was closed. We should tolerate these errors.
|
// or the page was closed. We should tolerate these errors.
|
||||||
await this._session.sendMayFail('Network.interceptRequestWithResponse', {
|
await this._session.sendMayFail('Network.interceptRequestWithResponse', {
|
||||||
requestId: this._requestId,
|
requestId: this._requestId,
|
||||||
status: response.status || 200,
|
status: response.status,
|
||||||
statusText: network.STATUS_TEXTS[String(response.status || 200)],
|
statusText: network.STATUS_TEXTS[String(response.status)],
|
||||||
mimeType,
|
mimeType,
|
||||||
headers: responseHeaders,
|
headers: responseHeaders,
|
||||||
base64Encoded,
|
base64Encoded,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue