inject page info
This commit is contained in:
parent
f2cba29b85
commit
f3e0c20f75
|
|
@ -228,7 +228,13 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
await route._innerContinue(true /* isFallback */).catch(() => {});
|
await route._innerContinue(true /* isFallback */).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onRouteListener = (route: network.Route) => this._onRoute(route);
|
private _onRouteListener = ({ route, browserRequest }: { route: network.Route, browserRequest: network.Route }) => {
|
||||||
|
const page = browserRequest.request()._safePage();
|
||||||
|
if (page)
|
||||||
|
page._onRoute(route);
|
||||||
|
else
|
||||||
|
this._onRoute(route);
|
||||||
|
};
|
||||||
|
|
||||||
async _onWebSocketRoute(webSocketRoute: network.WebSocketRoute) {
|
async _onWebSocketRoute(webSocketRoute: network.WebSocketRoute) {
|
||||||
const routeHandler = this._webSocketRoutes.find(route => route.matches(webSocketRoute.url()));
|
const routeHandler = this._webSocketRoutes.find(route => route.matches(webSocketRoute.url()));
|
||||||
|
|
@ -245,11 +251,12 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
await bindingCall.call(func);
|
await bindingCall.call(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
_subscribeToMockingProxy(mockingProxy: MockingProxy) {
|
async _subscribeToMockingProxy(mockingProxy: MockingProxy) {
|
||||||
if (this._mockingProxy)
|
if (this._mockingProxy)
|
||||||
throw new Error('Multiple mocking proxies are not supported');
|
throw new Error('Multiple mocking proxies are not supported');
|
||||||
this._mockingProxy = mockingProxy;
|
this._mockingProxy = mockingProxy;
|
||||||
this._mockingProxy.on(Events.MockingProxy.Route, this._onRouteListener);
|
this._mockingProxy.on(Events.MockingProxy.Route, this._onRouteListener);
|
||||||
|
await this.route('**', (route: network.Route) => this._mockingProxy!.instrumentBrowserRequest(route));
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultNavigationTimeout(timeout: number | undefined) {
|
setDefaultNavigationTimeout(timeout: number | undefined) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { Events } from './events';
|
||||||
|
|
||||||
export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
private _port: number;
|
private _port: number;
|
||||||
|
private _browserRequests = new Map<string, network.Route>();
|
||||||
|
|
||||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.MockingProxyInitializer) {
|
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.MockingProxyInitializer) {
|
||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
|
|
@ -28,10 +29,13 @@ export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
this._port = initializer.port;
|
this._port = initializer.port;
|
||||||
const requestContext = APIRequestContext.from(initializer.requestContext);
|
const requestContext = APIRequestContext.from(initializer.requestContext);
|
||||||
|
|
||||||
this._channel.on('route', (params: channels.MockingProxyRouteEvent) => {
|
this._channel.on('route', async (params: channels.MockingProxyRouteEvent) => {
|
||||||
|
const browserRequest = params.browserRequestRoute ? this._browserRequests.get(params.browserRequestRoute) : undefined;
|
||||||
|
if (params.browserRequestRoute)
|
||||||
|
this._browserRequests.delete(params.browserRequestRoute);
|
||||||
const route = network.Route.from(params.route);
|
const route = network.Route.from(params.route);
|
||||||
route._context = requestContext;
|
route._context = requestContext;
|
||||||
this.emit(Events.MockingProxy.Route, route);
|
this.emit(Events.MockingProxy.Route, { route, browserRequest });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +43,17 @@ export class MockingProxy extends ChannelOwner<channels.MockingProxyChannel> {
|
||||||
await this._channel.setInterceptionPatterns(params);
|
await this._channel.setInterceptionPatterns(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async instrumentBrowserRequest(route: network.Route) {
|
||||||
|
const isSimpleCORS = false; // TODO: implement simple CORS
|
||||||
|
if (isSimpleCORS)
|
||||||
|
return await route.continue();
|
||||||
|
|
||||||
|
this._browserRequests.set(route._guid, route);
|
||||||
|
const proxyUrl = `http://localhost:${this.port()}/pw_meta:${route._guid}/`;
|
||||||
|
|
||||||
|
await route.continue({ headers: { 'x-playwright-proxy': encodeURIComponent(proxyUrl) } });
|
||||||
|
}
|
||||||
|
|
||||||
port(): number {
|
port(): number {
|
||||||
return this._port;
|
return this._port;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,7 @@ scheme.MockingProxyInitializer = tObject({
|
||||||
});
|
});
|
||||||
scheme.MockingProxyRouteEvent = tObject({
|
scheme.MockingProxyRouteEvent = tObject({
|
||||||
route: tChannel(['Route']),
|
route: tChannel(['Route']),
|
||||||
|
browserRequestRoute: tOptional(tString),
|
||||||
});
|
});
|
||||||
scheme.MockingProxySetInterceptionPatternsParams = tObject({
|
scheme.MockingProxySetInterceptionPatternsParams = tObject({
|
||||||
patterns: tArray(tObject({
|
patterns: tArray(tObject({
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ export class MockingProxyDispatcher extends Dispatcher<MockingProxy, channels.Mo
|
||||||
requestContext: APIRequestContextDispatcher.from(scope, mockingProxy.fetchRequest),
|
requestContext: APIRequestContextDispatcher.from(scope, mockingProxy.fetchRequest),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addObjectListener(MockingProxy.Events.Route, (route: Route) => {
|
this.addObjectListener(MockingProxy.Events.Route, ({ route, browserRequestRoute }: {route: Route, browserRequestRoute?: string }) => {
|
||||||
const requestDispatcher = RequestDispatcher.from(this as any, route.request());
|
const requestDispatcher = RequestDispatcher.from(this as any, route.request());
|
||||||
this._dispatchEvent('route', { route: RouteDispatcher.from(requestDispatcher, route) });
|
this._dispatchEvent('route', { route: RouteDispatcher.from(requestDispatcher, route), browserRequestRoute });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,12 @@ export class MockingProxy extends SdkObject implements RequestContext {
|
||||||
if (req.url?.startsWith('/'))
|
if (req.url?.startsWith('/'))
|
||||||
req.url = req.url.substring(1);
|
req.url = req.url.substring(1);
|
||||||
|
|
||||||
|
let browserRequestRoute: string | undefined;
|
||||||
|
if (req.url?.startsWith('pw_meta:')) {
|
||||||
|
browserRequestRoute = req.url.substring('pw_meta:'.length, req.url.indexOf('/'));
|
||||||
|
req.url = req.url.substring(req.url.indexOf('/') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Java URL likes removing double slashes from the pathname.
|
// Java URL likes removing double slashes from the pathname.
|
||||||
if (req.url?.startsWith('http:/') && !req.url?.startsWith('http://'))
|
if (req.url?.startsWith('http:/') && !req.url?.startsWith('http://'))
|
||||||
req.url = req.url.replace('http:/', 'http://');
|
req.url = req.url.replace('http:/', 'http://');
|
||||||
|
|
@ -203,7 +209,7 @@ export class MockingProxy extends SdkObject implements RequestContext {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this._matches?.(req.url!))
|
if (this._matches?.(req.url!))
|
||||||
this.emit(MockingProxy.Events.Route, route);
|
this.emit(MockingProxy.Events.Route, { route, browserRequestRoute });
|
||||||
else
|
else
|
||||||
await route.continue({ isFallback: false });
|
await route.continue({ isFallback: false });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -238,8 +238,6 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
options.baseURL = baseURL;
|
options.baseURL = baseURL;
|
||||||
if (serviceWorkers !== undefined)
|
if (serviceWorkers !== undefined)
|
||||||
options.serviceWorkers = serviceWorkers;
|
options.serviceWorkers = serviceWorkers;
|
||||||
if (_mockingProxy)
|
|
||||||
options.extraHTTPHeaders = { ...options.extraHTTPHeaders, 'x-playwright-proxy': encodeURIComponent(`http://localhost:${_mockingProxy.port()}/`) };
|
|
||||||
await use({
|
await use({
|
||||||
...contextOptions,
|
...contextOptions,
|
||||||
...options,
|
...options,
|
||||||
|
|
@ -372,7 +370,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
} : {};
|
} : {};
|
||||||
const context = await browser.newContext({ ...videoOptions, ...options }) as BrowserContextImpl;
|
const context = await browser.newContext({ ...videoOptions, ...options }) as BrowserContextImpl;
|
||||||
if (_mockingProxy)
|
if (_mockingProxy)
|
||||||
context._subscribeToMockingProxy(_mockingProxy);
|
await context._subscribeToMockingProxy(_mockingProxy);
|
||||||
const contextData: { pagesWithVideo: Page[] } = { pagesWithVideo: [] };
|
const contextData: { pagesWithVideo: Page[] } = { pagesWithVideo: [] };
|
||||||
contexts.set(context, contextData);
|
contexts.set(context, contextData);
|
||||||
if (captureVideo)
|
if (captureVideo)
|
||||||
|
|
|
||||||
1
packages/protocol/src/channels.d.ts
vendored
1
packages/protocol/src/channels.d.ts
vendored
|
|
@ -593,6 +593,7 @@ export interface MockingProxyChannel extends MockingProxyEventTarget, EventTarge
|
||||||
}
|
}
|
||||||
export type MockingProxyRouteEvent = {
|
export type MockingProxyRouteEvent = {
|
||||||
route: RouteChannel,
|
route: RouteChannel,
|
||||||
|
browserRequestRoute?: string,
|
||||||
};
|
};
|
||||||
export type MockingProxySetInterceptionPatternsParams = {
|
export type MockingProxySetInterceptionPatternsParams = {
|
||||||
patterns: {
|
patterns: {
|
||||||
|
|
|
||||||
|
|
@ -700,6 +700,7 @@ MockingProxy:
|
||||||
route:
|
route:
|
||||||
parameters:
|
parameters:
|
||||||
route: Route
|
route: Route
|
||||||
|
browserRequestRoute: string?
|
||||||
|
|
||||||
Root:
|
Root:
|
||||||
type: interface
|
type: interface
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,9 @@ test('inject mode', async ({ runInlineTest, server }) => {
|
||||||
`,
|
`,
|
||||||
'a.test.ts': `
|
'a.test.ts': `
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
test('foo', async ({ page, request }) => {
|
test('foo', async ({ page }) => {
|
||||||
await page.goto('${server.PREFIX}/page');
|
await page.goto('${server.PREFIX}/page');
|
||||||
expect(await page.textContent('body')).toEqual('proxy url injected');
|
expect(await page.textContent('body')).toEqual('proxy url injected');
|
||||||
const response = await request.get('${server.PREFIX}/page');
|
|
||||||
expect(await response.text()).toEqual('proxy url injected');
|
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
}, { workers: 1 });
|
}, { workers: 1 });
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue