Skip to content

Commit 4817483

Browse files
authored
chore: allow highlighting aria template from extension (#33594)
1 parent a8af7cc commit 4817483

9 files changed

Lines changed: 50 additions & 19 deletions

File tree

packages/playwright-core/src/protocol/validator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ scheme.DebugControllerSetRecorderModeParams = tObject({
422422
});
423423
scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({}));
424424
scheme.DebugControllerHighlightParams = tObject({
425-
selector: tString,
425+
selector: tOptional(tString),
426+
ariaTemplate: tOptional(tString),
426427
});
427428
scheme.DebugControllerHighlightResult = tOptional(tObject({}));
428429
scheme.DebugControllerHideHighlightParams = tOptional(tObject({}));

packages/playwright-core/src/server/ariaSnapshot.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
*/
1616

1717
import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot';
18-
import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
18+
import type { AriaTemplateNode, ParsedYaml } from '@isomorphic/ariaSnapshot';
1919
import { yaml } from '../utilsBundle';
2020

2121
export function parseAriaSnapshot(text: string): AriaTemplateNode {
22-
const fragment = yaml.parse(text);
23-
if (!Array.isArray(fragment))
22+
return parseYamlTemplate(parseYamlForAriaSnapshot(text));
23+
}
24+
25+
export function parseYamlForAriaSnapshot(text: string): ParsedYaml {
26+
const parsed = yaml.parse(text);
27+
if (!Array.isArray(parsed))
2428
throw new Error('Expected object key starting with "- ":\n\n' + text + '\n');
25-
return parseYamlTemplate(fragment);
29+
return parsed;
2630
}

packages/playwright-core/src/server/debugController.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type { Playwright } from './playwright';
2424
import { Recorder } from './recorder';
2525
import { EmptyRecorderApp } from './recorder/recorderApp';
2626
import { asLocator, type Language } from '../utils';
27+
import { parseYamlForAriaSnapshot } from './ariaSnapshot';
2728

2829
const internalMetadata = serverSideCallMetadata();
2930

@@ -142,9 +143,13 @@ export class DebugController extends SdkObject {
142143
this._autoCloseTimer = setTimeout(heartBeat, 30000);
143144
}
144145

145-
async highlight(selector: string) {
146-
for (const recorder of await this._allRecorders())
147-
recorder.setHighlightedSelector(this._sdkLanguage, selector);
146+
async highlight(params: { selector?: string, ariaTemplate?: string }) {
147+
for (const recorder of await this._allRecorders()) {
148+
if (params.ariaTemplate)
149+
recorder.setHighlightedAriaTemplate(parseYamlForAriaSnapshot(params.ariaTemplate));
150+
else if (params.selector)
151+
recorder.setHighlightedSelector(this._sdkLanguage, params.selector);
152+
}
148153
}
149154

150155
async hideHighlight() {

packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class DebugControllerDispatcher extends Dispatcher<DebugController, chann
6868
}
6969

7070
async highlight(params: channels.DebugControllerHighlightParams) {
71-
await this._object.highlight(params.selector);
71+
await this._object.highlight(params);
7272
}
7373

7474
async hideHighlight() {

packages/playwright-core/src/server/recorder.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class Recorder implements InstrumentationListener, IRecorder {
4040
readonly handleSIGINT: boolean | undefined;
4141
private _context: BrowserContext;
4242
private _mode: Mode;
43-
private _highlightedElement: { selector?: string, ariaSnapshot?: ParsedYaml } = {};
43+
private _highlightedElement: { selector?: string, ariaTemplate?: ParsedYaml } = {};
4444
private _overlayState: OverlayState = { offsetX: 0 };
4545
private _recorderApp: IRecorderApp | null = null;
4646
private _currentCallsMetadata = new Map<CallMetadata, SdkObject>();
@@ -107,8 +107,8 @@ export class Recorder implements InstrumentationListener, IRecorder {
107107
if (data.event === 'highlightRequested') {
108108
if (data.params.selector)
109109
this.setHighlightedSelector(this._currentLanguage, data.params.selector);
110-
if (data.params.ariaSnapshot)
111-
this.setHighlightedAriaSnapshot(data.params.ariaSnapshot);
110+
if (data.params.ariaTemplate)
111+
this.setHighlightedAriaTemplate(data.params.ariaTemplate);
112112
return;
113113
}
114114
if (data.event === 'step') {
@@ -169,7 +169,7 @@ export class Recorder implements InstrumentationListener, IRecorder {
169169
mode: this._mode,
170170
actionPoint,
171171
actionSelector,
172-
ariaTemplate: this._highlightedElement.ariaSnapshot,
172+
ariaTemplate: this._highlightedElement.ariaTemplate,
173173
language: this._currentLanguage,
174174
testIdAttributeName: this._contextRecorder.testIdAttributeName(),
175175
overlay: this._overlayState,
@@ -245,8 +245,8 @@ export class Recorder implements InstrumentationListener, IRecorder {
245245
this._refreshOverlay();
246246
}
247247

248-
setHighlightedAriaSnapshot(ariaSnapshot: ParsedYaml) {
249-
this._highlightedElement = { ariaSnapshot };
248+
setHighlightedAriaTemplate(ariaTemplate: ParsedYaml) {
249+
this._highlightedElement = { ariaTemplate };
250250
this._refreshOverlay();
251251
}
252252

packages/protocol/src/channels.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,10 +741,12 @@ export type DebugControllerSetRecorderModeOptions = {
741741
};
742742
export type DebugControllerSetRecorderModeResult = void;
743743
export type DebugControllerHighlightParams = {
744-
selector: string,
744+
selector?: string,
745+
ariaTemplate?: string,
745746
};
746747
export type DebugControllerHighlightOptions = {
747-
748+
selector?: string,
749+
ariaTemplate?: string,
748750
};
749751
export type DebugControllerHighlightResult = void;
750752
export type DebugControllerHideHighlightParams = {};

packages/protocol/src/protocol.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,8 @@ DebugController:
791791

792792
highlight:
793793
parameters:
794-
selector: string
794+
selector: string?
795+
ariaTemplate: string?
795796

796797
hideHighlight:
797798

packages/recorder/src/recorder.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export const Recorder: React.FC<RecorderProps> = ({
120120
setAriaSnapshotErrors(errors);
121121
setAriaSnapshot(ariaSnapshot);
122122
if (!errors.length)
123-
window.dispatch({ event: 'highlightRequested', params: { ariaSnapshot: fragment } });
123+
window.dispatch({ event: 'highlightRequested', params: { ariaTemplate: fragment } });
124124
}, [mode]);
125125
const isRecording = mode === 'recording' || mode === 'recording-inspecting';
126126
const locatorPlaceholder = isRecording ? '// Unavailable while recording' : (locator ? undefined : '// Pick element or type locator');

tests/library/debug-controller.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { createGuid } from '../../packages/playwright-core/lib/utils/crypto';
2020
import { Backend } from '../config/debugControllerBackend';
2121
import type { Browser, BrowserContext } from '@playwright/test';
2222
import type * as channels from '@protocol/channels';
23+
import { roundBox } from '../page/pageTest';
2324

2425
type BrowserWithReuse = Browser & { _newContextForReuse: () => Promise<BrowserContext> };
2526
type Fixtures = {
@@ -279,3 +280,20 @@ test('should highlight inside iframe', async ({ backend, connectedBrowser }, tes
279280
await expect(highlight).toHaveCount(1);
280281
await expect(page.locator('x-pw-highlight')).toHaveCount(1);
281282
});
283+
284+
test('should highlight aria template', async ({ backend, connectedBrowser }, testInfo) => {
285+
const context = await connectedBrowser._newContextForReuse();
286+
const page = await context.newPage();
287+
await backend.navigate({ url: `data:text/html,<button>Submit</button>` });
288+
289+
const button = page.getByRole('button');
290+
const highlight = page.locator('x-pw-highlight');
291+
292+
await backend.highlight({ ariaTemplate: `- button "Submit2"` });
293+
await expect(highlight).toHaveCount(0);
294+
295+
await backend.highlight({ ariaTemplate: `- button "Submit"` });
296+
const box1 = roundBox(await button.boundingBox());
297+
const box2 = roundBox(await highlight.boundingBox());
298+
expect(box1).toEqual(box2);
299+
});

0 commit comments

Comments
 (0)