diff --git a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts index 3c16e089a2cc6..58459d8ae93be 100644 --- a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts +++ b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts @@ -38,11 +38,19 @@ export interface LocatorFactory { } export function asLocatorDescription(lang: Language, selector: string): string | undefined { - const parsed = parseSelector(selector); - const lastPart = parsed.parts[parsed.parts.length - 1]; - if (lastPart?.name === 'internal:describe') - return JSON.parse(lastPart.body as string); - return asLocator(lang, selector); + try { + const parsed = parseSelector(selector); + const lastPart = parsed.parts[parsed.parts.length - 1]; + if (lastPart?.name === 'internal:describe') { + const description = JSON.parse(lastPart.body as string); + if (typeof description === 'string') + return description; + } + return innerAsLocators(new generators[lang](), parsed, false, 1)[0]; + } catch (e) { + // Tolerate invalid input. + return selector; + } } export function asLocator(lang: Language, selector: string, isFrameLocator: boolean = false): string { diff --git a/tests/library/locator-generator.spec.ts b/tests/library/locator-generator.spec.ts index cc54a143e80b6..9040438125df8 100644 --- a/tests/library/locator-generator.spec.ts +++ b/tests/library/locator-generator.spec.ts @@ -15,7 +15,7 @@ */ import { contextTest as it, expect } from '../config/browserTest'; -import { asLocator, asLocators } from '../../packages/playwright-core/lib/utils/isomorphic/locatorGenerators'; +import { asLocator, asLocators, asLocatorDescription } from '../../packages/playwright-core/lib/utils/isomorphic/locatorGenerators'; import { locatorOrSelectorAsSelector as parseLocator } from '../../packages/playwright-core/lib/utils/isomorphic/locatorParser'; import type { Page, Frame, Locator, FrameLocator } from 'playwright-core'; @@ -654,3 +654,10 @@ it('should not oom in locator parser', async ({ page }) => { const error = await locator.count().catch(e => e); expect(error.message).toContain('Frame locators are not allowed inside composite locators'); }); + +it('asLocatorDescription invalid input', async () => { + expect.soft(asLocatorDescription('javascript', `body >> internal:describe="desc"`)).toBe(`desc`); + expect.soft(asLocatorDescription('javascript', `body >> internal:describe=12`)).toBe(`locator('body')`); + expect.soft(asLocatorDescription('javascript', `following-sibling::*[1]`)).toBe(`following-sibling::*[1]`); + expect.soft(asLocatorDescription('javascript', `body >> internal:describe="desc" >> div`)).toBe(`locator('body').locator('div')`); +});