Rewrote to use lower fidelity but easier URL updating mechanism
This commit is contained in:
parent
c6644f92bd
commit
2c707ded45
|
|
@ -32,7 +32,7 @@ import type * as actions from '@recorder/actions';
|
||||||
import { stringifySelector } from '../utils/isomorphic/selectorParser';
|
import { stringifySelector } from '../utils/isomorphic/selectorParser';
|
||||||
import type { Frame } from './frames';
|
import type { Frame } from './frames';
|
||||||
import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
|
import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
|
||||||
import { Page } from './page';
|
import type { Page } from './page';
|
||||||
|
|
||||||
const recorderSymbol = Symbol('recorderSymbol');
|
const recorderSymbol = Symbol('recorderSymbol');
|
||||||
|
|
||||||
|
|
@ -150,30 +150,6 @@ export class Recorder implements InstrumentationListener, IRecorder {
|
||||||
this._recorderApp?.close().catch(() => {});
|
this._recorderApp?.close().catch(() => {});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Report the URL of the first page in the context
|
|
||||||
let primaryPage: Page | undefined;
|
|
||||||
const registerNavigationListener = (page: Page) => {
|
|
||||||
if (primaryPage === undefined) {
|
|
||||||
primaryPage = page;
|
|
||||||
recorderApp.setBasePageURL(page.mainFrame().url());
|
|
||||||
}
|
|
||||||
|
|
||||||
page.on(Page.Events.InternalFrameNavigatedToNewDocument, (frame: Frame) => {
|
|
||||||
if (page === primaryPage && page.mainFrame() === frame)
|
|
||||||
recorderApp.setBasePageURL(frame.url());
|
|
||||||
});
|
|
||||||
page.on(Page.Events.Close, () => {
|
|
||||||
if (page === primaryPage) {
|
|
||||||
primaryPage = this._context.pages()[0];
|
|
||||||
if (primaryPage)
|
|
||||||
recorderApp.setBasePageURL(primaryPage.mainFrame().url());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
for (const page of this._context.pages())
|
|
||||||
registerNavigationListener(page);
|
|
||||||
this._context.on(BrowserContext.Events.Page, registerNavigationListener);
|
|
||||||
|
|
||||||
this._contextRecorder.on(ContextRecorder.Events.Change, (data: { sources: Source[], actions: actions.ActionInContext[] }) => {
|
this._contextRecorder.on(ContextRecorder.Events.Change, (data: { sources: Source[], actions: actions.ActionInContext[] }) => {
|
||||||
this._recorderSources = data.sources;
|
this._recorderSources = data.sources;
|
||||||
recorderApp.setActions(data.actions, data.sources);
|
recorderApp.setActions(data.actions, data.sources);
|
||||||
|
|
@ -372,7 +348,8 @@ export class Recorder implements InstrumentationListener, IRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _pushAllSources() {
|
private _pushAllSources() {
|
||||||
this._recorderApp?.setSources([...this._recorderSources, ...this._userSources.values()]);
|
const primaryPage: Page | undefined = this._context.pages()[0];
|
||||||
|
this._recorderApp?.setSources([...this._recorderSources, ...this._userSources.values()], primaryPage?.mainFrame().url());
|
||||||
}
|
}
|
||||||
|
|
||||||
async onBeforeInputAction(sdkObject: SdkObject, metadata: CallMetadata) {
|
async onBeforeInputAction(sdkObject: SdkObject, metadata: CallMetadata) {
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,8 @@ export class EmptyRecorderApp extends EventEmitter implements IRecorderApp {
|
||||||
async setRunningFile(file: string | undefined): Promise<void> {}
|
async setRunningFile(file: string | undefined): Promise<void> {}
|
||||||
async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void> {}
|
async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void> {}
|
||||||
async updateCallLogs(callLogs: CallLog[]): Promise<void> {}
|
async updateCallLogs(callLogs: CallLog[]): Promise<void> {}
|
||||||
async setSources(sources: Source[]): Promise<void> {}
|
async setSources(sources: Source[], primaryPageURL: string | undefined): Promise<void> {}
|
||||||
async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void> {}
|
async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void> {}
|
||||||
async setBasePageURL(url: string): Promise<void> {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RecorderApp extends EventEmitter implements IRecorderApp {
|
export class RecorderApp extends EventEmitter implements IRecorderApp {
|
||||||
|
|
@ -144,10 +143,10 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
|
||||||
}).toString(), { isFunction: true }, paused).catch(() => {});
|
}).toString(), { isFunction: true }, paused).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSources(sources: Source[]): Promise<void> {
|
async setSources(sources: Source[], primaryPageURL: string | undefined): Promise<void> {
|
||||||
await this._page.mainFrame().evaluateExpression(((sources: Source[]) => {
|
await this._page.mainFrame().evaluateExpression((({ sources, primaryPageURL }: { sources: Source[], primaryPageURL: string | undefined }) => {
|
||||||
window.playwrightSetSources(sources);
|
window.playwrightSetSources(sources, primaryPageURL);
|
||||||
}).toString(), { isFunction: true }, sources).catch(() => {});
|
}).toString(), { isFunction: true }, { sources, primaryPageURL }).catch(() => {});
|
||||||
|
|
||||||
// Testing harness for runCLI mode.
|
// Testing harness for runCLI mode.
|
||||||
if (process.env.PWTEST_CLI_IS_UNDER_TEST && sources.length) {
|
if (process.env.PWTEST_CLI_IS_UNDER_TEST && sources.length) {
|
||||||
|
|
@ -159,12 +158,6 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
|
||||||
async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void> {
|
async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setBasePageURL(url: string): Promise<void> {
|
|
||||||
await this._page.mainFrame().evaluateExpression(((url: string) => {
|
|
||||||
window.playwrightSetBasePageURL(url);
|
|
||||||
}).toString(), { isFunction: true }, url).catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void> {
|
async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void> {
|
||||||
if (userGesture)
|
if (userGesture)
|
||||||
this._page.bringToFront();
|
this._page.bringToFront();
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,8 @@ export interface IRecorderApp extends EventEmitter {
|
||||||
setRunningFile(file: string | undefined): Promise<void>;
|
setRunningFile(file: string | undefined): Promise<void>;
|
||||||
elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void>;
|
elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise<void>;
|
||||||
updateCallLogs(callLogs: CallLog[]): Promise<void>;
|
updateCallLogs(callLogs: CallLog[]): Promise<void>;
|
||||||
setSources(sources: Source[]): Promise<void>;
|
setSources(sources: Source[], primaryPageURL: string | undefined): Promise<void>;
|
||||||
setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void>;
|
setActions(actions: actions.ActionInContext[], sources: Source[]): Promise<void>;
|
||||||
setBasePageURL(url: string): Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IRecorderAppFactory = (recorder: IRecorder) => Promise<IRecorderApp>;
|
export type IRecorderAppFactory = (recorder: IRecorder) => Promise<IRecorderApp>;
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@ import * as React from 'react';
|
||||||
import { Recorder } from './recorder';
|
import { Recorder } from './recorder';
|
||||||
import './recorder.css';
|
import './recorder.css';
|
||||||
|
|
||||||
export const Main: React.FC = ({
|
export const Main: React.FC = ({}) => {
|
||||||
}) => {
|
|
||||||
const [sources, setSources] = React.useState<Source[]>([]);
|
const [sources, setSources] = React.useState<Source[]>([]);
|
||||||
const [paused, setPaused] = React.useState(false);
|
const [paused, setPaused] = React.useState(false);
|
||||||
const [log, setLog] = React.useState(new Map<string, CallLog>());
|
const [log, setLog] = React.useState(new Map<string, CallLog>());
|
||||||
|
|
@ -28,9 +27,12 @@ export const Main: React.FC = ({
|
||||||
|
|
||||||
React.useLayoutEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
window.playwrightSetMode = setMode;
|
window.playwrightSetMode = setMode;
|
||||||
window.playwrightSetSources = (sources: Source[]) => {
|
window.playwrightSetSources = (sources, primaryPageURL) => {
|
||||||
setSources(sources);
|
setSources(sources);
|
||||||
window.playwrightSourcesEchoForTest = sources;
|
window.playwrightSourcesEchoForTest = sources;
|
||||||
|
document.title = primaryPageURL
|
||||||
|
? `Playwright Inspector - ${primaryPageURL}`
|
||||||
|
: `Playwright Inspector`;
|
||||||
};
|
};
|
||||||
window.playwrightSetPaused = setPaused;
|
window.playwrightSetPaused = setPaused;
|
||||||
window.playwrightUpdateLogs = callLogs => {
|
window.playwrightUpdateLogs = callLogs => {
|
||||||
|
|
@ -43,14 +45,7 @@ export const Main: React.FC = ({
|
||||||
return newLog;
|
return newLog;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
window.playwrightSetBasePageURL = (url: string) => {
|
|
||||||
if (url)
|
|
||||||
document.title = `Playwright Inspector - ${url}`;
|
|
||||||
else
|
|
||||||
document.title = `Playwright Inspector`;
|
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return <Recorder sources={sources} paused={paused} log={log} mode={mode} />;
|
return <Recorder sources={sources} paused={paused} log={log} mode={mode} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
3
packages/recorder/src/recorderTypes.d.ts
vendored
3
packages/recorder/src/recorderTypes.d.ts
vendored
|
|
@ -101,9 +101,8 @@ declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
playwrightSetMode: (mode: Mode) => void;
|
playwrightSetMode: (mode: Mode) => void;
|
||||||
playwrightSetPaused: (paused: boolean) => void;
|
playwrightSetPaused: (paused: boolean) => void;
|
||||||
playwrightSetSources: (sources: Source[]) => void;
|
playwrightSetSources: (sources: Source[], primaryPageURL: string | undefined) => void;
|
||||||
playwrightSetOverlayVisible: (visible: boolean) => void;
|
playwrightSetOverlayVisible: (visible: boolean) => void;
|
||||||
playwrightSetBasePageURL: (url: string) => void;
|
|
||||||
playwrightUpdateLogs: (callLogs: CallLog[]) => void;
|
playwrightUpdateLogs: (callLogs: CallLog[]) => void;
|
||||||
playwrightSetRunningFile: (file: string | undefined) => void;
|
playwrightSetRunningFile: (file: string | undefined) => void;
|
||||||
playwrightElementPicked: (elementInfo: ElementInfo, userGesture?: boolean) => void;
|
playwrightElementPicked: (elementInfo: ElementInfo, userGesture?: boolean) => void;
|
||||||
|
|
|
||||||
|
|
@ -16,38 +16,68 @@
|
||||||
|
|
||||||
import { test, expect } from './inspectorTest';
|
import { test, expect } from './inspectorTest';
|
||||||
|
|
||||||
test('should reflect formatted URL of the page', async ({ openRecorder, server }) => {
|
test('should reflect formatted URL of the page', async ({
|
||||||
|
openRecorder,
|
||||||
|
server,
|
||||||
|
}) => {
|
||||||
const { recorder } = await openRecorder();
|
const { recorder } = await openRecorder();
|
||||||
await recorder.setContentAndWait('');
|
await recorder.setContentAndWait('');
|
||||||
await expect(await recorder.recorderPage.title()).toBe('Playwright Inspector - about:blank');
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
'Playwright Inspector - about:blank',
|
||||||
|
);
|
||||||
|
|
||||||
await recorder.setContentAndWait('', server.EMPTY_PAGE);
|
await recorder.setContentAndWait('', server.EMPTY_PAGE);
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.EMPTY_PAGE}`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.EMPTY_PAGE}`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should update primary page URL when original primary closes', async ({ context, openRecorder, server }) => {
|
test('should update primary page URL when original primary closes', async ({
|
||||||
|
context,
|
||||||
|
openRecorder,
|
||||||
|
server,
|
||||||
|
}) => {
|
||||||
const { recorder } = await openRecorder();
|
const { recorder } = await openRecorder();
|
||||||
await recorder.setContentAndWait('', `${server.PREFIX}/background-color.html`);
|
await recorder.setContentAndWait(
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/background-color.html`);
|
'',
|
||||||
|
`${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
|
||||||
const page2 = await context.newPage();
|
const page2 = await context.newPage();
|
||||||
await page2.goto(`${server.PREFIX}/empty.html`);
|
await page2.goto(`${server.PREFIX}/empty.html`);
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/background-color.html`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
|
||||||
const page3 = await context.newPage();
|
const page3 = await context.newPage();
|
||||||
await page3.goto(`${server.PREFIX}/dom.html`);
|
await page3.goto(`${server.PREFIX}/dom.html`);
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/background-color.html`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
|
||||||
const page4 = await context.newPage();
|
const page4 = await context.newPage();
|
||||||
await page4.goto(`${server.PREFIX}/grid.html`);
|
await page4.goto(`${server.PREFIX}/grid.html`);
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/background-color.html`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
|
||||||
await page2.close();
|
await page2.close();
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/background-color.html`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
|
||||||
|
);
|
||||||
|
|
||||||
await recorder.page.close();
|
await recorder.page.close();
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/dom.html`);
|
// URL will not update without performing some action
|
||||||
|
await page3.getByRole('checkbox').click();
|
||||||
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/dom.html`,
|
||||||
|
);
|
||||||
|
|
||||||
await page3.close();
|
await page3.close();
|
||||||
await expect(await recorder.recorderPage.title()).toBe(`Playwright Inspector - ${server.PREFIX}/grid.html`);
|
await expect(recorder.recorderPage).toHaveTitle(
|
||||||
|
`Playwright Inspector - ${server.PREFIX}/grid.html`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue