fix(debug controller): highlight selectors in iframe (#33273)

This commit is contained in:
Simon Knott 2024-11-04 14:41:06 +01:00 committed by GitHub
parent 96a29b69eb
commit b148ce1ad1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 4 deletions

View File

@ -30,6 +30,8 @@ import type { IRecorderAppFactory, IRecorderApp, IRecorder } from './recorder/re
import { metadataToCallLog } from './recorder/recorderUtils';
import type * as actions from '@recorder/actions';
import { buildFullSelector } from '../utils/isomorphic/recorderUtils';
import { stringifySelector } from '../utils/isomorphic/selectorParser';
import type { Frame } from './frames';
const recorderSymbol = Symbol('recorderSymbol');
@ -146,12 +148,12 @@ export class Recorder implements InstrumentationListener, IRecorder {
this._pushAllSources();
});
await this._context.exposeBinding('__pw_recorderState', false, source => {
await this._context.exposeBinding('__pw_recorderState', false, async source => {
let actionSelector = '';
let actionPoint: Point | undefined;
const hasActiveScreenshotCommand = [...this._currentCallsMetadata.keys()].some(isScreenshotCommand);
if (!hasActiveScreenshotCommand) {
actionSelector = this._highlightedSelector;
actionSelector = await this._scopeHighlightedSelectorToFrame(source.frame);
for (const [metadata, sdkObject] of this._currentCallsMetadata) {
if (source.page === sdkObject.attribution.page) {
actionPoint = metadata.point || actionPoint;
@ -243,13 +245,38 @@ export class Recorder implements InstrumentationListener, IRecorder {
this._refreshOverlay();
}
private async _scopeHighlightedSelectorToFrame(frame: Frame): Promise<string> {
try {
const mainFrame = frame._page.mainFrame();
const resolved = await mainFrame.selectors.resolveFrameForSelector(this._highlightedSelector);
// selector couldn't be found, don't highlight anything
if (!resolved)
return '';
// selector points to no specific frame, highlight in all frames
if (resolved?.frame === mainFrame)
return stringifySelector(resolved.info.parsed);
// selector points to this frame, highlight it
if (resolved?.frame === frame)
return stringifySelector(resolved.info.parsed);
// selector points to a different frame, highlight nothing
return '';
} catch {
return '';
}
}
setOutput(codegenId: string, outputFile: string | undefined) {
this._contextRecorder.setOutput(codegenId, outputFile);
}
private _refreshOverlay() {
for (const page of this._context.pages())
page.mainFrame().evaluateExpression('window.__pw_refreshOverlay()').catch(() => {});
for (const page of this._context.pages()) {
for (const frame of page.frames())
frame.evaluateExpression('window.__pw_refreshOverlay()').catch(() => {});
}
}
async onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata) {

View File

@ -253,3 +253,29 @@ test('should reset routes before reuse', async ({ server, connectedBrowserFactor
await expect(page2).toHaveTitle('console.log test');
await browser2.close();
});
test('should highlight inside iframe', async ({ backend, connectedBrowser }, testInfo) => {
testInfo.annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33146' });
const context = await connectedBrowser._newContextForReuse();
const page = await context.newPage();
await backend.navigate({ url: `data:text/html,<div>bar</div><iframe srcdoc="<div>bar</div>"/>` });
await page.frameLocator('iframe').getByText('bar').highlight();
const highlight = page.frameLocator('iframe').locator('x-pw-highlight');
await expect(highlight).not.toHaveCount(0);
await backend.hideHighlight();
await expect(highlight).toHaveCount(0);
await backend.highlight({ selector: `frameLocator('iframe').getByText('bar')` });
await expect(highlight).not.toHaveCount(0);
await backend.highlight({ selector: `frameLocator('iframe').frameLocator('iframe').getByText('bar')` });
await expect(highlight).toHaveCount(0);
await backend.highlight({ selector: `getByText('bar')` });
await expect(highlight).toHaveCount(1);
await expect(page.locator('x-pw-highlight')).toHaveCount(1);
});