implement first pass
This commit is contained in:
parent
8712024f3a
commit
aa2aef146d
|
|
@ -70,7 +70,6 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
_closeWasCalled = false;
|
_closeWasCalled = false;
|
||||||
private _closeReason: string | undefined;
|
private _closeReason: string | undefined;
|
||||||
private _harRouters: HarRouter[] = [];
|
private _harRouters: HarRouter[] = [];
|
||||||
private _registeredListeners: RegisteredListener[] = [];
|
|
||||||
_mockingProxy?: MockingProxy;
|
_mockingProxy?: MockingProxy;
|
||||||
|
|
||||||
static from(context: channels.BrowserContextChannel): BrowserContext {
|
static from(context: channels.BrowserContextChannel): BrowserContext {
|
||||||
|
|
@ -96,7 +95,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
this._channel.on('page', ({ page }) => this._onPage(Page.from(page)));
|
this._channel.on('page', ({ page }) => this._onPage(Page.from(page)));
|
||||||
this._channel.on('route', params => {
|
this._channel.on('route', params => {
|
||||||
const route = network.Route.from(params.route);
|
const route = network.Route.from(params.route);
|
||||||
route._context = this.request;
|
route._apiRequestContext = this.request;
|
||||||
this._onRoute(route);
|
this._onRoute(route);
|
||||||
});
|
});
|
||||||
this._channel.on('webSocketRoute', ({ webSocketRoute }) => this._onWebSocketRoute(network.WebSocketRoute.from(webSocketRoute)));
|
this._channel.on('webSocketRoute', ({ webSocketRoute }) => this._onWebSocketRoute(network.WebSocketRoute.from(webSocketRoute)));
|
||||||
|
|
@ -467,7 +466,6 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
this._disposeHarRouters();
|
this._disposeHarRouters();
|
||||||
this.tracing._resetStackCounter();
|
this.tracing._resetStackCounter();
|
||||||
this.emit(Events.BrowserContext.Close, this);
|
this.emit(Events.BrowserContext.Close, this);
|
||||||
eventsHelper.removeEventListeners(this._registeredListeners);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async [Symbol.asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import { ChannelOwner } from './channelOwner';
|
||||||
import { APIRequestContext } from './fetch';
|
import { APIRequestContext } from './fetch';
|
||||||
import { assert } from '../utils';
|
import { assert } from '../utils';
|
||||||
import type { Page } from './page';
|
import type { Page } from './page';
|
||||||
|
import { Events } from './events';
|
||||||
|
|
||||||
export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
private _pages = new Map<string, Page>();
|
private _pages = new Map<string, Page>();
|
||||||
|
|
@ -29,8 +30,8 @@ export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
const requestContext = APIRequestContext.from(initializer.requestContext);
|
const requestContext = APIRequestContext.from(initializer.requestContext);
|
||||||
this._channel.on('route', async (params: channels.MockingProxyRouteEvent) => {
|
this._channel.on('route', async (params: channels.MockingProxyRouteEvent) => {
|
||||||
const route = network.Route.from(params.route);
|
const route = network.Route.from(params.route);
|
||||||
route._context = requestContext;
|
route._apiRequestContext = requestContext;
|
||||||
const page = route.request()._safePage()!;
|
const page = route.request()._pageForMockingProxy!;
|
||||||
await page._onRoute(route);
|
await page._onRoute(route);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -44,7 +45,7 @@ export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
|
|
||||||
this._channel.on('requestFailed', async (params: channels.MockingProxyRequestFailedEvent) => {
|
this._channel.on('requestFailed', async (params: channels.MockingProxyRequestFailedEvent) => {
|
||||||
const request = network.Request.from(params.request);
|
const request = network.Request.from(params.request);
|
||||||
const page = request._safePage()!;
|
const page = request._pageForMockingProxy!;
|
||||||
page.context()._onRequestFailed(request, params.responseEndTiming, params.failureText, page);
|
page.context()._onRequestFailed(request, params.responseEndTiming, params.failureText, page);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -52,20 +53,27 @@ export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
const { responseEndTiming } = params;
|
const { responseEndTiming } = params;
|
||||||
const request = network.Request.from(params.request);
|
const request = network.Request.from(params.request);
|
||||||
const response = network.Response.fromNullable(params.response);
|
const response = network.Response.fromNullable(params.response);
|
||||||
const page = request._safePage()!;
|
const page = request._pageForMockingProxy!;
|
||||||
page.context()._onRequestFinished(request, response, page, responseEndTiming);
|
page.context()._onRequestFinished(request, response, page, responseEndTiming);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._channel.on('response', async (params: channels.MockingProxyResponseEvent) => {
|
this._channel.on('response', async (params: channels.MockingProxyResponseEvent) => {
|
||||||
const response = network.Response.from(params.response);
|
const response = network.Response.from(params.response);
|
||||||
const page = response.request()._safePage()!;
|
const page = response.request()._pageForMockingProxy!;
|
||||||
page.context()._onResponse(response, page);
|
page.context()._onResponse(response, page);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static from(channel: channels.MockingProxyChannel): MockingProxy {
|
||||||
|
return (channel as any)._object;
|
||||||
|
}
|
||||||
|
|
||||||
async instrumentPage(page: Page) {
|
async instrumentPage(page: Page) {
|
||||||
const correlation = page._guid.split('@')[1];
|
const correlation = page._guid.split('@')[1];
|
||||||
this._pages.set(correlation, page);
|
this._pages.set(correlation, page);
|
||||||
|
page.on(Events.Page.Close, () => {
|
||||||
|
this._pages.delete(correlation);
|
||||||
|
});
|
||||||
const proxyUrl = `http://localhost:${this._initializer.port}/pw_meta:${correlation}/`;
|
const proxyUrl = `http://localhost:${this._initializer.port}/pw_meta:${correlation}/`;
|
||||||
await page.setExtraHTTPHeaders({
|
await page.setExtraHTTPHeaders({
|
||||||
'x-playwright-proxy': encodeURIComponent(proxyUrl)
|
'x-playwright-proxy': encodeURIComponent(proxyUrl)
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
|
||||||
}
|
}
|
||||||
|
|
||||||
_safePage(): Page | null {
|
_safePage(): Page | null {
|
||||||
return this._pageForMockingProxy ?? Frame.fromNullable(this._initializer.frame)?._page ?? null;
|
return Frame.fromNullable(this._initializer.frame)?._page ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceWorker(): Worker | null {
|
serviceWorker(): Worker | null {
|
||||||
|
|
@ -294,7 +294,7 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
|
||||||
|
|
||||||
export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route {
|
export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route {
|
||||||
private _handlingPromise: ManualPromise<boolean> | null = null;
|
private _handlingPromise: ManualPromise<boolean> | null = null;
|
||||||
_context!: APIRequestContext;
|
_apiRequestContext!: APIRequestContext;
|
||||||
_didThrow: boolean = false;
|
_didThrow: boolean = false;
|
||||||
|
|
||||||
static from(route: channels.RouteChannel): Route {
|
static from(route: channels.RouteChannel): Route {
|
||||||
|
|
@ -342,7 +342,7 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
||||||
|
|
||||||
async fetch(options: FallbackOverrides & { maxRedirects?: number, maxRetries?: number, timeout?: number } = {}): Promise<APIResponse> {
|
async fetch(options: FallbackOverrides & { maxRedirects?: number, maxRetries?: number, timeout?: number } = {}): Promise<APIResponse> {
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
return await this._context._innerFetch({ request: this.request(), data: options.postData, ...options });
|
return await this._apiRequestContext._innerFetch({ request: this.request(), data: options.postData, ...options });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||||
this._channel.on('locatorHandlerTriggered', ({ uid }) => this._onLocatorHandlerTriggered(uid));
|
this._channel.on('locatorHandlerTriggered', ({ uid }) => this._onLocatorHandlerTriggered(uid));
|
||||||
this._channel.on('route', params => {
|
this._channel.on('route', params => {
|
||||||
const route = Route.from(params.route);
|
const route = Route.from(params.route);
|
||||||
route._context = this.context().request;
|
route._apiRequestContext = this.context().request;
|
||||||
this._onRoute(route);
|
this._onRoute(route);
|
||||||
});
|
});
|
||||||
this._channel.on('webSocketRoute', ({ webSocketRoute }) => this._onWebSocketRoute(WebSocketRoute.from(webSocketRoute)));
|
this._channel.on('webSocketRoute', ({ webSocketRoute }) => this._onWebSocketRoute(WebSocketRoute.from(webSocketRoute)));
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,9 @@ import { Android } from './android';
|
||||||
import { BrowserType } from './browserType';
|
import { BrowserType } from './browserType';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { Electron } from './electron';
|
import { Electron } from './electron';
|
||||||
import { APIRequest, type NewContextOptions } from './fetch';
|
import { APIRequest } from './fetch';
|
||||||
import { Selectors, SelectorsOwner } from './selectors';
|
import { Selectors, SelectorsOwner } from './selectors';
|
||||||
|
import { MockingProxy } from './mockingProxy';
|
||||||
|
|
||||||
export class Playwright extends ChannelOwner<channels.PlaywrightChannel> {
|
export class Playwright extends ChannelOwner<channels.PlaywrightChannel> {
|
||||||
readonly _android: Android;
|
readonly _android: Android;
|
||||||
|
|
@ -77,6 +78,6 @@ export class Playwright extends ChannelOwner<channels.PlaywrightChannel> {
|
||||||
async _startMockingProxy() {
|
async _startMockingProxy() {
|
||||||
const requestContext = await this.request._newContext(undefined, this._connection.localUtils()._channel);
|
const requestContext = await this.request._newContext(undefined, this._connection.localUtils()._channel);
|
||||||
const { mockingProxy } = await this._connection.localUtils()._channel.newMockingProxy({ requestContext: requestContext._channel });
|
const { mockingProxy } = await this._connection.localUtils()._channel.newMockingProxy({ requestContext: requestContext._channel });
|
||||||
return (mockingProxy as any)._object;
|
return MockingProxy.from(mockingProxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export class MockingProxyDispatcher extends Dispatcher<MockingProxy, channels.Mo
|
||||||
|
|
||||||
private constructor(scope: RootDispatcher, mockingProxy: MockingProxy) {
|
private constructor(scope: RootDispatcher, mockingProxy: MockingProxy) {
|
||||||
super(scope, mockingProxy, 'MockingProxy', {
|
super(scope, mockingProxy, 'MockingProxy', {
|
||||||
port: mockingProxy.port,
|
port: mockingProxy.port(),
|
||||||
requestContext: APIRequestContextDispatcher.from(scope, mockingProxy.fetchRequest),
|
requestContext: APIRequestContextDispatcher.from(scope, mockingProxy.fetchRequest),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -56,4 +56,8 @@ export class MockingProxyDispatcher extends Dispatcher<MockingProxy, channels.Mo
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override _onDispose(): void {
|
||||||
|
this._object.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@ export class MockingProxy extends SdkObject implements RequestContext {
|
||||||
await this._httpServer.start();
|
await this._httpServer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
get port() {
|
async stop() {
|
||||||
|
await this._httpServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
port() {
|
||||||
return this._httpServer.port();
|
return this._httpServer.port();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,7 +249,7 @@ async function collectBody(req: http.IncomingMessage) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WorkerHttpServer extends HttpServer {
|
class WorkerHttpServer extends HttpServer {
|
||||||
override handleCORS(request: http.IncomingMessage, response: http.ServerResponse): boolean {
|
override handleCORS(request: http.IncomingMessage, response: http.ServerResponse): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue