chore: allow highlighting aria template from extension (#33594)
This commit is contained in:
		
							parent
							
								
									a8af7cc435
								
							
						
					
					
						commit
						4817483ff2
					
				|  | @ -422,7 +422,8 @@ scheme.DebugControllerSetRecorderModeParams = tObject({ | |||
| }); | ||||
| scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({})); | ||||
| scheme.DebugControllerHighlightParams = tObject({ | ||||
|   selector: tString, | ||||
|   selector: tOptional(tString), | ||||
|   ariaTemplate: tOptional(tString), | ||||
| }); | ||||
| scheme.DebugControllerHighlightResult = tOptional(tObject({})); | ||||
| scheme.DebugControllerHideHighlightParams = tOptional(tObject({})); | ||||
|  |  | |||
|  | @ -15,12 +15,16 @@ | |||
|  */ | ||||
| 
 | ||||
| import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot'; | ||||
| import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot'; | ||||
| import type { AriaTemplateNode, ParsedYaml } from '@isomorphic/ariaSnapshot'; | ||||
| import { yaml } from '../utilsBundle'; | ||||
| 
 | ||||
| export function parseAriaSnapshot(text: string): AriaTemplateNode { | ||||
|   const fragment = yaml.parse(text); | ||||
|   if (!Array.isArray(fragment)) | ||||
|     throw new Error('Expected object key starting with "- ":\n\n' + text + '\n'); | ||||
|   return parseYamlTemplate(fragment); | ||||
|   return parseYamlTemplate(parseYamlForAriaSnapshot(text)); | ||||
| } | ||||
| 
 | ||||
| export function parseYamlForAriaSnapshot(text: string): ParsedYaml { | ||||
|   const parsed = yaml.parse(text); | ||||
|   if (!Array.isArray(parsed)) | ||||
|     throw new Error('Expected object key starting with "- ":\n\n' + text + '\n'); | ||||
|   return parsed; | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ import type { Playwright } from './playwright'; | |||
| import { Recorder } from './recorder'; | ||||
| import { EmptyRecorderApp } from './recorder/recorderApp'; | ||||
| import { asLocator, type Language } from '../utils'; | ||||
| import { parseYamlForAriaSnapshot } from './ariaSnapshot'; | ||||
| 
 | ||||
| const internalMetadata = serverSideCallMetadata(); | ||||
| 
 | ||||
|  | @ -142,9 +143,13 @@ export class DebugController extends SdkObject { | |||
|     this._autoCloseTimer = setTimeout(heartBeat, 30000); | ||||
|   } | ||||
| 
 | ||||
|   async highlight(selector: string) { | ||||
|     for (const recorder of await this._allRecorders()) | ||||
|       recorder.setHighlightedSelector(this._sdkLanguage, selector); | ||||
|   async highlight(params: { selector?: string, ariaTemplate?: string }) { | ||||
|     for (const recorder of await this._allRecorders()) { | ||||
|       if (params.ariaTemplate) | ||||
|         recorder.setHighlightedAriaTemplate(parseYamlForAriaSnapshot(params.ariaTemplate)); | ||||
|       else if (params.selector) | ||||
|         recorder.setHighlightedSelector(this._sdkLanguage, params.selector); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async hideHighlight() { | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ export class DebugControllerDispatcher extends Dispatcher<DebugController, chann | |||
|   } | ||||
| 
 | ||||
|   async highlight(params: channels.DebugControllerHighlightParams) { | ||||
|     await this._object.highlight(params.selector); | ||||
|     await this._object.highlight(params); | ||||
|   } | ||||
| 
 | ||||
|   async hideHighlight() { | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ export class Recorder implements InstrumentationListener, IRecorder { | |||
|   readonly handleSIGINT: boolean | undefined; | ||||
|   private _context: BrowserContext; | ||||
|   private _mode: Mode; | ||||
|   private _highlightedElement: { selector?: string, ariaSnapshot?: ParsedYaml } = {}; | ||||
|   private _highlightedElement: { selector?: string, ariaTemplate?: ParsedYaml } = {}; | ||||
|   private _overlayState: OverlayState = { offsetX: 0 }; | ||||
|   private _recorderApp: IRecorderApp | null = null; | ||||
|   private _currentCallsMetadata = new Map<CallMetadata, SdkObject>(); | ||||
|  | @ -107,8 +107,8 @@ export class Recorder implements InstrumentationListener, IRecorder { | |||
|       if (data.event === 'highlightRequested') { | ||||
|         if (data.params.selector) | ||||
|           this.setHighlightedSelector(this._currentLanguage, data.params.selector); | ||||
|         if (data.params.ariaSnapshot) | ||||
|           this.setHighlightedAriaSnapshot(data.params.ariaSnapshot); | ||||
|         if (data.params.ariaTemplate) | ||||
|           this.setHighlightedAriaTemplate(data.params.ariaTemplate); | ||||
|         return; | ||||
|       } | ||||
|       if (data.event === 'step') { | ||||
|  | @ -169,7 +169,7 @@ export class Recorder implements InstrumentationListener, IRecorder { | |||
|         mode: this._mode, | ||||
|         actionPoint, | ||||
|         actionSelector, | ||||
|         ariaTemplate: this._highlightedElement.ariaSnapshot, | ||||
|         ariaTemplate: this._highlightedElement.ariaTemplate, | ||||
|         language: this._currentLanguage, | ||||
|         testIdAttributeName: this._contextRecorder.testIdAttributeName(), | ||||
|         overlay: this._overlayState, | ||||
|  | @ -245,8 +245,8 @@ export class Recorder implements InstrumentationListener, IRecorder { | |||
|     this._refreshOverlay(); | ||||
|   } | ||||
| 
 | ||||
|   setHighlightedAriaSnapshot(ariaSnapshot: ParsedYaml) { | ||||
|     this._highlightedElement = { ariaSnapshot }; | ||||
|   setHighlightedAriaTemplate(ariaTemplate: ParsedYaml) { | ||||
|     this._highlightedElement = { ariaTemplate }; | ||||
|     this._refreshOverlay(); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -741,10 +741,12 @@ export type DebugControllerSetRecorderModeOptions = { | |||
| }; | ||||
| export type DebugControllerSetRecorderModeResult = void; | ||||
| export type DebugControllerHighlightParams = { | ||||
|   selector: string, | ||||
|   selector?: string, | ||||
|   ariaTemplate?: string, | ||||
| }; | ||||
| export type DebugControllerHighlightOptions = { | ||||
| 
 | ||||
|   selector?: string, | ||||
|   ariaTemplate?: string, | ||||
| }; | ||||
| export type DebugControllerHighlightResult = void; | ||||
| export type DebugControllerHideHighlightParams = {}; | ||||
|  |  | |||
|  | @ -791,7 +791,8 @@ DebugController: | |||
| 
 | ||||
|     highlight: | ||||
|       parameters: | ||||
|         selector: string | ||||
|         selector: string? | ||||
|         ariaTemplate: string? | ||||
| 
 | ||||
|     hideHighlight: | ||||
| 
 | ||||
|  |  | |||
|  | @ -120,7 +120,7 @@ export const Recorder: React.FC<RecorderProps> = ({ | |||
|     setAriaSnapshotErrors(errors); | ||||
|     setAriaSnapshot(ariaSnapshot); | ||||
|     if (!errors.length) | ||||
|       window.dispatch({ event: 'highlightRequested', params: { ariaSnapshot: fragment } }); | ||||
|       window.dispatch({ event: 'highlightRequested', params: { ariaTemplate: fragment } }); | ||||
|   }, [mode]); | ||||
|   const isRecording = mode === 'recording' || mode === 'recording-inspecting'; | ||||
|   const locatorPlaceholder = isRecording ? '// Unavailable while recording' : (locator ? undefined : '// Pick element or type locator'); | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ import { createGuid } from '../../packages/playwright-core/lib/utils/crypto'; | |||
| import { Backend } from '../config/debugControllerBackend'; | ||||
| import type { Browser, BrowserContext } from '@playwright/test'; | ||||
| import type * as channels from '@protocol/channels'; | ||||
| import { roundBox } from '../page/pageTest'; | ||||
| 
 | ||||
| type BrowserWithReuse = Browser & { _newContextForReuse: () => Promise<BrowserContext> }; | ||||
| type Fixtures = { | ||||
|  | @ -279,3 +280,20 @@ test('should highlight inside iframe', async ({ backend, connectedBrowser }, tes | |||
|   await expect(highlight).toHaveCount(1); | ||||
|   await expect(page.locator('x-pw-highlight')).toHaveCount(1); | ||||
| }); | ||||
| 
 | ||||
| test('should highlight aria template', async ({ backend, connectedBrowser }, testInfo) => { | ||||
|   const context = await connectedBrowser._newContextForReuse(); | ||||
|   const page = await context.newPage(); | ||||
|   await backend.navigate({ url: `data:text/html,<button>Submit</button>` }); | ||||
| 
 | ||||
|   const button = page.getByRole('button'); | ||||
|   const highlight = page.locator('x-pw-highlight'); | ||||
| 
 | ||||
|   await backend.highlight({ ariaTemplate: `- button "Submit2"` }); | ||||
|   await expect(highlight).toHaveCount(0); | ||||
| 
 | ||||
|   await backend.highlight({ ariaTemplate: `- button "Submit"` }); | ||||
|   const box1 = roundBox(await button.boundingBox()); | ||||
|   const box2 = roundBox(await highlight.boundingBox()); | ||||
|   expect(box1).toEqual(box2); | ||||
| }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue