chore(rpc): pass more network tests (#2762)

This commit is contained in:
Pavel Feldman 2020-06-29 16:37:38 -07:00 committed by GitHub
parent 0963c1979e
commit 3a7d629c61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 79 additions and 44 deletions

View file

@ -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 responseHeaders: { [s: string]: string; } = {};
if (response.headers) {
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = response.headers[header];
}
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = response.headers[header];
if (response.contentType)
responseHeaders['content-type'] = response.contentType;
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.
await this._client._sendMayFail('Fetch.fulfillRequest', {
requestId: this._interceptionId!,
responseCode: response.status || 200,
responsePhrase: network.STATUS_TEXTS[String(response.status || 200)],
responseCode: response.status,
responsePhrase: network.STATUS_TEXTS[String(response.status)],
responseHeaders: headersArray(responseHeaders),
body: responseBody ? responseBody.toString('base64') : undefined,
});

View file

@ -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 responseHeaders: { [s: string]: string; } = {};
if (response.headers) {
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = response.headers[header];
}
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = response.headers[header];
if (response.contentType)
responseHeaders['content-type'] = response.contentType;
if (responseBody && !('content-length' in responseHeaders))
@ -187,8 +185,8 @@ class InterceptableRequest implements network.RouteDelegate {
await this._session.sendMayFail('Network.fulfillInterceptedRequest', {
requestId: this._id,
status: response.status || 200,
statusText: network.STATUS_TEXTS[String(response.status || 200)] || '',
status: response.status,
statusText: network.STATUS_TEXTS[String(response.status)] || '',
headers: headersArray(responseHeaders),
base64body: responseBody ? responseBody.toString('base64') : undefined,
});

View file

@ -14,13 +14,11 @@
* 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 types from './types';
import { assert, helper } from './helper';
import { URLSearchParams } from 'url';
import { normalizeFulfillParameters } from './rpc/serializers';
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
const parsedURLs = urls.map(s => new URL(s));
@ -220,15 +218,7 @@ export class Route {
async fulfill(response: types.FulfillResponse & { path?: string }) {
assert(!this._handled, 'Route is already handled!');
this._handled = true;
if (response.path) {
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);
await this._delegate.fulfill(await normalizeFulfillParameters(response));
}
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
@ -325,7 +315,7 @@ export class Response {
export interface RouteDelegate {
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>;
}

View file

@ -17,6 +17,8 @@
import { EventEmitter } from 'events';
import * as types from '../types';
export type Binary = string;
export interface Channel extends EventEmitter {
_type: string;
_guid: string;
@ -101,7 +103,7 @@ export interface PageChannel extends Channel {
goForward(params: { options?: types.NavigateOptions }): Promise<ResponseChannel | null>;
opener(): Promise<PageChannel | 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>;
setNetworkInterceptionEnabled(params: { enabled: boolean }): 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>;
querySelector(params: { selector: string }): Promise<ElementHandleChannel | null>;
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>;
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>;
@ -228,7 +230,14 @@ export type RequestInitializer = {
export interface RouteChannel extends Channel {
abort(params: { errorCode: 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 = {
request: RequestChannel,

View file

@ -55,6 +55,7 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
const context = await this.newContext(options);
const page = await context.newPage();
page._ownedContext = context;
context._ownerPage = page;
return page;
}

View file

@ -34,6 +34,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
readonly _bindings = new Map<string, frames.FunctionWithSource>();
private _pendingWaitForEvents = new Map<(error: Error) => void, string>();
_timeoutSettings = new TimeoutSettings();
_ownerPage: Page | undefined;
static from(context: BrowserContextChannel): BrowserContext {
return context._object;
@ -91,6 +92,8 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
}
async newPage(): Promise<Page> {
if (this._ownerPage)
throw new Error('Please use browser.newContext()');
return Page.from(await this._channel.newPage());
}

View file

@ -82,7 +82,7 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleIni
}
async jsonValue(): Promise<T> {
return await this._channel.jsonValue();
return parseResult(await this._channel.jsonValue());
}
asElement(): ElementHandle | null {

View file

@ -20,6 +20,7 @@ import { RequestChannel, ResponseChannel, RouteChannel, RequestInitializer, Resp
import { ChannelOwner } from './channelOwner';
import { Frame } from './frame';
import { Connection } from '../connection';
import { normalizeFulfillParameters } from '../serializers';
export type NetworkCookie = {
name: string,
@ -150,7 +151,13 @@ export class Route extends ChannelOwner<RouteChannel, RouteInitializer> {
}
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 } = {}) {

View file

@ -334,6 +334,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
}
async setViewportSize(viewportSize: types.Size) {
this._viewportSize = viewportSize;
await this._channel.setViewportSize({ viewportSize });
}

View file

@ -62,3 +62,20 @@ export async function normalizeFilePayloads(files: string | types.FilePayload |
}
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 || ''
};
}

View file

@ -46,7 +46,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
}
async jsonValue(): Promise<any> {
return this._object.jsonValue();
return serializeResult(await this._object.jsonValue());
}
async dispose() {
@ -55,7 +55,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
}
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 {

View file

@ -16,7 +16,7 @@
import { Request, Response, Route } from '../../network';
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 { FrameDispatcher } from './frameDispatcher';
@ -102,8 +102,14 @@ export class RouteDispatcher extends Dispatcher<Route, RouteInitializer> impleme
await this._object.continue(params.overrides);
}
async fulfill(params: { response: types.FulfillResponse & { path?: string } }): Promise<void> {
await this._object.fulfill(params.response);
async fulfill(params: { response: { status?: number, headers?: types.Headers, contentType?: string, body: Binary } }): Promise<void> {
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> {

View file

@ -196,6 +196,13 @@ export type FulfillResponse = {
body?: string | Buffer,
};
export type NormalizedFulfillResponse = {
status: number,
headers: Headers,
contentType?: string,
body: string | Buffer,
};
export type NetworkCookie = {
name: string,
value: string,

View file

@ -66,17 +66,15 @@ export class WKInterceptableRequest implements network.RouteDelegate {
await this._session.sendMayFail('Network.interceptRequestWithError', { requestId: this._requestId, errorType });
}
async fulfill(response: types.FulfillResponse) {
async fulfill(response: types.NormalizedFulfillResponse) {
await this._interceptedPromise;
const base64Encoded = !!response.body && !helper.isString(response.body);
const responseBody = response.body ? (base64Encoded ? response.body.toString('base64') : response.body as string) : '';
const responseHeaders: { [s: string]: string; } = {};
if (response.headers) {
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = String(response.headers[header]);
}
for (const header of Object.keys(response.headers))
responseHeaders[header.toLowerCase()] = String(response.headers[header]);
let mimeType = base64Encoded ? 'application/octet-stream' : 'text/plain';
if (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.
await this._session.sendMayFail('Network.interceptRequestWithResponse', {
requestId: this._requestId,
status: response.status || 200,
statusText: network.STATUS_TEXTS[String(response.status || 200)],
status: response.status,
statusText: network.STATUS_TEXTS[String(response.status)],
mimeType,
headers: responseHeaders,
base64Encoded,