diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index 50564fa31f..25035b6998 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -383,7 +383,11 @@ export function getAriaLabelledByElements(element: Element): Element[] | null { const ref = element.getAttribute('aria-labelledby'); if (ref === null) return null; - return getIdRefs(element, ref); + const refs = getIdRefs(element, ref); + // step 2b: + // "if the current node has an aria-labelledby attribute that contains at least one valid IDREF" + // Therefore, if none of the refs match an element, we consider aria-labelledby to be missing. + return refs.length ? refs : null; } function allowsNameFromContent(role: string, targetDescendant: boolean) { diff --git a/packages/playwright-core/src/server/launchApp.ts b/packages/playwright-core/src/server/launchApp.ts index 3d119f9d46..d8c81a3169 100644 --- a/packages/playwright-core/src/server/launchApp.ts +++ b/packages/playwright-core/src/server/launchApp.ts @@ -43,12 +43,12 @@ export async function launchApp(browserType: BrowserType, options: { } const context = await browserType.launchPersistentContext(serverSideCallMetadata(), '', { - channel: !options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined, - noDefaultViewport: true, ignoreDefaultArgs: ['--enable-automation'], - colorScheme: 'no-override', - acceptDownloads: isUnderTest() ? 'accept' : 'internal-browser-default', ...options?.persistentContextOptions, + channel: options.persistentContextOptions?.channel ?? (!options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined), + noDefaultViewport: options.persistentContextOptions?.noDefaultViewport ?? true, + acceptDownloads: options?.persistentContextOptions?.acceptDownloads ?? (isUnderTest() ? 'accept' : 'internal-browser-default'), + colorScheme: options?.persistentContextOptions?.colorScheme ?? 'no-override', args, }); const [page] = context.pages(); diff --git a/tests/library/role-utils.spec.ts b/tests/library/role-utils.spec.ts index a02680ce86..2b5792d0f1 100644 --- a/tests/library/role-utils.spec.ts +++ b/tests/library/role-utils.spec.ts @@ -495,6 +495,16 @@ test('should not include hidden pseudo into accessible name', async ({ page }) = expect.soft(await getNameAndRole(page, 'a')).toEqual({ role: 'link', name: 'hello hello' }); }); +test('should ignore invalid aria-labelledby', async ({ page }) => { + await page.setContent(` + + `); + expect.soft(await getNameAndRole(page, 'input')).toEqual({ role: 'textbox', name: 'Text here' }); +}); + function toArray(x: any): any[] { return Array.isArray(x) ? x : [x]; } diff --git a/utils/build/build.js b/utils/build/build.js index ac18a2cde6..b67b36aee3 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -301,7 +301,7 @@ if (watchMode) { args: [ 'vite', '--config', 'vite.sw.config.ts', 'build', '--watch', '--minify=false', - '--outDir', path.join(__dirname, '..', '..', 'packages', 'playwright-core', 'lib', 'vite', 'trace-viewer'), + '--outDir', path.join(__dirname, '..', '..', 'packages', 'playwright-core', 'lib', 'vite', 'traceViewer'), '--emptyOutDir=false' ], shell: true,