From 3a10c32d8a23eaa0793412a067fbca1b7649bf7a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 13 Dec 2024 16:10:59 -0800 Subject: [PATCH] chore: report highlight parse error to debug controller (#33984) --- .../src/server/debugController.ts | 15 +++++++++++++-- .../src/utils/isomorphic/locatorParser.ts | 19 ++++++++++++------- tests/library/debug-controller.spec.ts | 6 ++++++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts index 8878ecb59cbe5..b810e2fa65fb7 100644 --- a/packages/playwright-core/src/server/debugController.ts +++ b/packages/playwright-core/src/server/debugController.ts @@ -25,6 +25,9 @@ import { Recorder } from './recorder'; import { EmptyRecorderApp } from './recorder/recorderApp'; import { asLocator, type Language } from '../utils'; import { parseYamlForAriaSnapshot } from './ariaSnapshot'; +import type { ParsedYaml } from '../utils/isomorphic/ariaSnapshot'; +import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot'; +import { unsafeLocatorOrSelectorAsSelector } from '../utils/isomorphic/locatorParser'; const internalMetadata = serverSideCallMetadata(); @@ -144,9 +147,17 @@ export class DebugController extends SdkObject { } async highlight(params: { selector?: string, ariaTemplate?: string }) { + // Assert parameters validity. + if (params.selector) + unsafeLocatorOrSelectorAsSelector(this._sdkLanguage, params.selector, 'data-testid'); + let parsedYaml: ParsedYaml | undefined; + if (params.ariaTemplate) { + parsedYaml = parseYamlForAriaSnapshot(params.ariaTemplate); + parseYamlTemplate(parsedYaml); + } for (const recorder of await this._allRecorders()) { - if (params.ariaTemplate) - recorder.setHighlightedAriaTemplate(parseYamlForAriaSnapshot(params.ariaTemplate)); + if (parsedYaml) + recorder.setHighlightedAriaTemplate(parsedYaml); else if (params.selector) recorder.setHighlightedSelector(this._sdkLanguage, params.selector); } diff --git a/packages/playwright-core/src/utils/isomorphic/locatorParser.ts b/packages/playwright-core/src/utils/isomorphic/locatorParser.ts index 9bae0a62bdbe4..fff3d078fffd4 100644 --- a/packages/playwright-core/src/utils/isomorphic/locatorParser.ts +++ b/packages/playwright-core/src/utils/isomorphic/locatorParser.ts @@ -217,18 +217,23 @@ function transform(template: string, params: TemplateParams, testIdAttributeName export function locatorOrSelectorAsSelector(language: Language, locator: string, testIdAttributeName: string): string { try { - parseSelector(locator); - return locator; + return unsafeLocatorOrSelectorAsSelector(language, locator, testIdAttributeName); } catch (e) { + return ''; } +} + +export function unsafeLocatorOrSelectorAsSelector(language: Language, locator: string, testIdAttributeName: string): string { try { - const { selector, preferredQuote } = parseLocator(locator, testIdAttributeName); - const locators = asLocators(language, selector, undefined, undefined, preferredQuote); - const digest = digestForComparison(language, locator); - if (locators.some(candidate => digestForComparison(language, candidate) === digest)) - return selector; + parseSelector(locator); + return locator; } catch (e) { } + const { selector, preferredQuote } = parseLocator(locator, testIdAttributeName); + const locators = asLocators(language, selector, undefined, undefined, preferredQuote); + const digest = digestForComparison(language, locator); + if (locators.some(candidate => digestForComparison(language, candidate) === digest)) + return selector; return ''; } diff --git a/tests/library/debug-controller.spec.ts b/tests/library/debug-controller.spec.ts index c3fb643665cf9..b71cae12a5292 100644 --- a/tests/library/debug-controller.spec.ts +++ b/tests/library/debug-controller.spec.ts @@ -300,3 +300,9 @@ test('should highlight aria template', async ({ backend, connectedBrowser }, tes const box2 = roundBox(await highlight.boundingBox()); expect(box1).toEqual(box2); }); + +test('should report error in aria template', async ({ backend }) => { + await backend.navigate({ url: `data:text/html,` }); + const error = await backend.highlight({ ariaTemplate: `- button "Submit` }).catch(e => e); + expect(error.message).toContain('Unterminated string:'); +});