Skip to content

Commit

Permalink
feat(recorder): display primary page URL in recorder title (#34637)
Browse files Browse the repository at this point in the history
  • Loading branch information
agg23 authored Feb 7, 2025
1 parent 893e7bb commit 4bc8cf0
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 25 deletions.
5 changes: 4 additions & 1 deletion packages/playwright-core/src/server/recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type * as actions from '@recorder/actions';
import { stringifySelector } from '../utils/isomorphic/selectorParser';
import type { Frame } from './frames';
import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
import type { Page } from './page';

const recorderSymbol = Symbol('recorderSymbol');

Expand Down Expand Up @@ -148,6 +149,7 @@ export class Recorder implements InstrumentationListener, IRecorder {
this._context.instrumentation.removeListener(this);
this._recorderApp?.close().catch(() => {});
});

this._contextRecorder.on(ContextRecorder.Events.Change, (data: { sources: Source[], actions: actions.ActionInContext[] }) => {
this._recorderSources = data.sources;
recorderApp.setActions(data.actions, data.sources);
Expand Down Expand Up @@ -346,7 +348,8 @@ export class Recorder implements InstrumentationListener, IRecorder {
}

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) {
Expand Down
10 changes: 5 additions & 5 deletions packages/playwright-core/src/server/recorder/recorderApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class EmptyRecorderApp extends EventEmitter implements IRecorderApp {
async setRunningFile(file: string | undefined): Promise<void> {}
async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): 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> {}
}

Expand Down Expand Up @@ -143,10 +143,10 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
}).toString(), { isFunction: true }, paused).catch(() => {});
}

async setSources(sources: Source[]): Promise<void> {
await this._page.mainFrame().evaluateExpression(((sources: Source[]) => {
window.playwrightSetSources(sources);
}).toString(), { isFunction: true }, sources).catch(() => {});
async setSources(sources: Source[], primaryPageURL: string | undefined): Promise<void> {
await this._page.mainFrame().evaluateExpression((({ sources, primaryPageURL }: { sources: Source[], primaryPageURL: string | undefined }) => {
window.playwrightSetSources(sources, primaryPageURL);
}).toString(), { isFunction: true }, { sources, primaryPageURL }).catch(() => {});

// Testing harness for runCLI mode.
if (process.env.PWTEST_CLI_IS_UNDER_TEST && sources.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface IRecorderApp extends EventEmitter {
setRunningFile(file: string | undefined): Promise<void>;
elementPicked(elementInfo: ElementInfo, userGesture?: boolean): 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>;
}

Expand Down
38 changes: 21 additions & 17 deletions packages/recorder/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,33 @@ import * as React from 'react';
import { Recorder } from './recorder';
import './recorder.css';

export const Main: React.FC = ({
}) => {
export const Main: React.FC = ({}) => {
const [sources, setSources] = React.useState<Source[]>([]);
const [paused, setPaused] = React.useState(false);
const [log, setLog] = React.useState(new Map<string, CallLog>());
const [mode, setMode] = React.useState<Mode>('none');

window.playwrightSetMode = setMode;
window.playwrightSetSources = React.useCallback((sources: Source[]) => {
setSources(sources);
window.playwrightSourcesEchoForTest = sources;
React.useLayoutEffect(() => {
window.playwrightSetMode = setMode;
window.playwrightSetSources = (sources, primaryPageURL) => {
setSources(sources);
window.playwrightSourcesEchoForTest = sources;
document.title = primaryPageURL
? `Playwright Inspector - ${primaryPageURL}`
: `Playwright Inspector`;
};
window.playwrightSetPaused = setPaused;
window.playwrightUpdateLogs = callLogs => {
setLog(log => {
const newLog = new Map<string, CallLog>(log);
for (const callLog of callLogs) {
callLog.reveal = !log.has(callLog.id);
newLog.set(callLog.id, callLog);
}
return newLog;
});
};
}, []);
window.playwrightSetPaused = setPaused;
window.playwrightUpdateLogs = callLogs => {
setLog(log => {
const newLog = new Map<string, CallLog>(log);
for (const callLog of callLogs) {
callLog.reveal = !log.has(callLog.id);
newLog.set(callLog.id, callLog);
}
return newLog;
});
};

return <Recorder sources={sources} paused={paused} log={log} mode={mode} />;
};
2 changes: 1 addition & 1 deletion packages/recorder/src/recorderTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ declare global {
interface Window {
playwrightSetMode: (mode: Mode) => void;
playwrightSetPaused: (paused: boolean) => void;
playwrightSetSources: (sources: Source[]) => void;
playwrightSetSources: (sources: Source[], primaryPageURL: string | undefined) => void;
playwrightSetOverlayVisible: (visible: boolean) => void;
playwrightUpdateLogs: (callLogs: CallLog[]) => void;
playwrightSetRunningFile: (file: string | undefined) => void;
Expand Down
83 changes: 83 additions & 0 deletions tests/library/inspector/title.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { test, expect } from './inspectorTest';

test('should reflect formatted URL of the page', async ({
openRecorder,
server,
}) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait('');
await expect(recorder.recorderPage).toHaveTitle(
'Playwright Inspector - about:blank',
);

await recorder.setContentAndWait('', 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,
}) => {
const { recorder } = await openRecorder();
await recorder.setContentAndWait(
'',
`${server.PREFIX}/background-color.html`,
);
await expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
);

const page2 = await context.newPage();
await page2.goto(`${server.PREFIX}/empty.html`);
await expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
);

const page3 = await context.newPage();
await page3.goto(`${server.PREFIX}/dom.html`);
await expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
);

const page4 = await context.newPage();
await page4.goto(`${server.PREFIX}/grid.html`);
await expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
);

await page2.close();
await expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/background-color.html`,
);

await recorder.page.close();
// 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 expect(recorder.recorderPage).toHaveTitle(
`Playwright Inspector - ${server.PREFIX}/grid.html`,
);
});

0 comments on commit 4bc8cf0

Please sign in to comment.