Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/injected/src/roleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,9 +848,9 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt
// For "other form elements", we count select and any other input.
//
// Note: WebKit does not follow the spec and uses placeholder when aria-labelledby is present.
if (!labelledBy && (tagName === 'TEXTAREA' || tagName === 'SELECT' || tagName === 'INPUT')) {
if (!labelledBy && (tagName === 'TEXTAREA' || tagName === 'SELECT' || tagName === 'INPUT' || tagName === 'METER' || tagName === 'PROGRESS')) {
options.visitedElements.add(element);
const labels = (element as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)).labels || [];
const labels = (element as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | HTMLMeterElement | HTMLProgressElement)).labels || [];
if (labels.length)
return getAccessibleNameFromAssociatedLabels(labels, options);

Expand Down
15 changes: 15 additions & 0 deletions tests/library/role-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,21 @@ test('input type=search maps to searchbox unless list points at a datalist', {
expect.soft(await getNameAndRole(page, '#search4')).toEqual({ role: 'combobox', name: '' });
});

test('meter and progress get their name from an associated label', {
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41891' },
}, async ({ page }) => {
await page.setContent(`
<label for="meter1">Battery</label><meter id="meter1" value=0.5></meter>
<label for="progress1">Loading</label><progress id="progress1" value=0.3></progress>
<label>Charge <meter id="meter2" value=0.5></meter></label>
<label for="meter3">Ignored</label><meter id="meter3" aria-label="Overridden" value=0.5></meter>
`);
expect.soft(await getNameAndRole(page, '#meter1')).toEqual({ role: 'meter', name: 'Battery' });
expect.soft(await getNameAndRole(page, '#progress1')).toEqual({ role: 'progressbar', name: 'Loading' });
expect.soft(await getNameAndRole(page, '#meter2')).toEqual({ role: 'meter', name: 'Charge' });
expect.soft(await getNameAndRole(page, '#meter3')).toEqual({ role: 'meter', name: 'Overridden' });
});

test('native controls labelled-by', async ({ page }) => {
await page.setContent(`
<label id="for-text1">TEXT1</label><input aria-labelledby="for-text1" id="text1" type=text>
Expand Down
2 changes: 1 addition & 1 deletion tests/library/selector-generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ it.describe('selector generator', () => {
expect.soft(await generate(page, '#target1')).toBe('internal:role=textbox[name=\"Target1\"i]');
expect.soft(await generate(page, '#target2')).toBe('internal:role=button[name=\"Target2\"i]');
expect.soft(await generate(page, '#target3')).toBe('internal:label=\"Target3\"i');
expect.soft(await generate(page, '#target4')).toBe('internal:label=\"Target4\"i');
expect.soft(await generate(page, '#target4')).toBe('internal:role=progressbar[name=\"Target4\"i]');
expect.soft(await generate(page, '#target5')).toBe('#target5');
expect.soft(await generate(page, '#target6')).toBe('internal:text="text"i');

Expand Down