chore: remove the leaf node notion (#33249)
This commit is contained in:
parent
24cafbc8cb
commit
9a0a6cec10
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { escapeWithQuotes } from '@isomorphic/stringUtils';
|
||||
import * as roleUtils from './roleUtils';
|
||||
import { isElementVisible, isElementStyleVisibilityVisible, getElementComputedStyle } from './domUtils';
|
||||
import { getElementComputedStyle } from './domUtils';
|
||||
import type { AriaRole } from './roleUtils';
|
||||
|
||||
type AriaProps = {
|
||||
|
|
@ -29,7 +29,7 @@ type AriaProps = {
|
|||
};
|
||||
|
||||
type AriaNode = AriaProps & {
|
||||
role: AriaRole | 'fragment' | 'text';
|
||||
role: AriaRole | 'fragment';
|
||||
name: string;
|
||||
children: (AriaNode | string)[];
|
||||
};
|
||||
|
|
@ -56,22 +56,10 @@ export function generateAriaTree(rootElement: Element): AriaNode {
|
|||
if (roleUtils.isElementHiddenForAria(element))
|
||||
return;
|
||||
|
||||
const visible = isElementVisible(element);
|
||||
const hasVisibleChildren = isElementStyleVisibilityVisible(element);
|
||||
|
||||
if (!hasVisibleChildren)
|
||||
return;
|
||||
|
||||
if (visible) {
|
||||
const childAriaNode = toAriaNode(element);
|
||||
const isHiddenContainer = childAriaNode && hiddenContainerRoles.has(childAriaNode.ariaNode.role);
|
||||
if (childAriaNode && !isHiddenContainer)
|
||||
ariaNode.children.push(childAriaNode.ariaNode);
|
||||
if (isHiddenContainer || !childAriaNode?.isLeaf)
|
||||
processChildNodes(childAriaNode?.ariaNode || ariaNode, element);
|
||||
} else {
|
||||
processChildNodes(ariaNode, element);
|
||||
}
|
||||
if (childAriaNode)
|
||||
ariaNode.children.push(childAriaNode);
|
||||
processChildNodes(childAriaNode || ariaNode, element);
|
||||
};
|
||||
|
||||
function processChildNodes(ariaNode: AriaNode, element: Element) {
|
||||
|
|
@ -101,6 +89,9 @@ export function generateAriaTree(rootElement: Element): AriaNode {
|
|||
|
||||
if (treatAsBlock)
|
||||
ariaNode.children.push(treatAsBlock);
|
||||
|
||||
if (ariaNode.children.length === 1 && ariaNode.name === ariaNode.children[0])
|
||||
ariaNode.children = [];
|
||||
}
|
||||
|
||||
roleUtils.beginAriaCaches();
|
||||
|
|
@ -115,19 +106,13 @@ export function generateAriaTree(rootElement: Element): AriaNode {
|
|||
return ariaRoot;
|
||||
}
|
||||
|
||||
function toAriaNode(element: Element): { ariaNode: AriaNode, isLeaf: boolean } | null {
|
||||
function toAriaNode(element: Element): AriaNode | null {
|
||||
const role = roleUtils.getAriaRole(element);
|
||||
if (!role)
|
||||
return null;
|
||||
|
||||
const name = roleUtils.getElementAccessibleName(element, false) || '';
|
||||
const isLeaf = leafRoles.has(role);
|
||||
const result: AriaNode = { role, name, children: [] };
|
||||
if (isLeaf && !name) {
|
||||
const text = roleUtils.accumulatedElementText(element);
|
||||
if (text)
|
||||
result.children = [text];
|
||||
}
|
||||
|
||||
if (roleUtils.kAriaCheckedRoles.includes(role))
|
||||
result.checked = roleUtils.getAriaChecked(element);
|
||||
|
|
@ -147,7 +132,7 @@ function toAriaNode(element: Element): { ariaNode: AriaNode, isLeaf: boolean } |
|
|||
if (roleUtils.kAriaSelectedRoles.includes(role))
|
||||
result.selected = roleUtils.getAriaSelected(element);
|
||||
|
||||
return { isLeaf, ariaNode: result };
|
||||
return result;
|
||||
}
|
||||
|
||||
export function renderedAriaTree(rootElement: Element): string {
|
||||
|
|
@ -178,21 +163,12 @@ function normalizeStringChildren(rootA11yNode: AriaNode) {
|
|||
}
|
||||
flushChildren(buffer, normalizedChildren);
|
||||
ariaNode.children = normalizedChildren.length ? normalizedChildren : [];
|
||||
if (ariaNode.children.length === 1 && ariaNode.children[0] === ariaNode.name)
|
||||
ariaNode.children = [];
|
||||
};
|
||||
visit(rootA11yNode);
|
||||
}
|
||||
|
||||
const hiddenContainerRoles = new Set(['none', 'presentation']);
|
||||
|
||||
const leafRoles = new Set<AriaRole>([
|
||||
'alert', 'blockquote', 'button', 'caption', 'checkbox', 'code', 'columnheader',
|
||||
'definition', 'deletion', 'emphasis', 'generic', 'heading', 'img', 'insertion',
|
||||
'link', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'meter', 'option',
|
||||
'progressbar', 'radio', 'rowheader', 'scrollbar', 'searchbox', 'separator',
|
||||
'slider', 'spinbutton', 'strong', 'subscript', 'superscript', 'switch', 'tab', 'term',
|
||||
'textbox', 'time', 'tooltip'
|
||||
]);
|
||||
|
||||
const normalizeWhitespaceWithin = (text: string) => text.replace(/[\s\t\r\n]+/g, ' ');
|
||||
|
||||
function matchesText(text: string | undefined, template: RegExp | string | undefined) {
|
||||
|
|
@ -305,15 +281,7 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean
|
|||
if (ariaNode.selected === true)
|
||||
line += ` [selected]`;
|
||||
|
||||
const stringValue = !ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string');
|
||||
if (stringValue) {
|
||||
if (!options?.noText && ariaNode.children.length)
|
||||
line += ': ' + quoteYamlString(ariaNode.children?.[0] as string);
|
||||
lines.push(line);
|
||||
return;
|
||||
}
|
||||
|
||||
lines.push(line + ':');
|
||||
lines.push(line + (ariaNode.children.length ? ':' : ''));
|
||||
for (const child of ariaNode.children || [])
|
||||
visit(child, indent + ' ');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,8 +64,10 @@ it('should snapshot list with accessible name', async ({ page }) => {
|
|||
`);
|
||||
await checkAndMatchSnapshot(page.locator('body'), `
|
||||
- list "my list":
|
||||
- listitem: "one"
|
||||
- listitem: "two"
|
||||
- listitem:
|
||||
- text: "one"
|
||||
- listitem:
|
||||
- text: "two"
|
||||
`);
|
||||
});
|
||||
|
||||
|
|
@ -105,7 +107,8 @@ it('should snapshot details visibility', async ({ page }) => {
|
|||
`);
|
||||
|
||||
await checkAndMatchSnapshot(page.locator('body'), `
|
||||
- group: "Summary"
|
||||
- group:
|
||||
- text: "Summary"
|
||||
`);
|
||||
});
|
||||
|
||||
|
|
@ -148,7 +151,8 @@ it('should snapshot integration', async ({ page }) => {
|
|||
- text: "Open source projects and samples from Microsoft"
|
||||
- list:
|
||||
- listitem:
|
||||
- group: "Verified"
|
||||
- group:
|
||||
- text: "Verified"
|
||||
- listitem:
|
||||
- link "Sponsor"
|
||||
`);
|
||||
|
|
@ -164,10 +168,12 @@ it('should support multiline text', async ({ page }) => {
|
|||
`);
|
||||
|
||||
await checkAndMatchSnapshot(page.locator('body'), `
|
||||
- paragraph: "Line 1 Line 2 Line 3"
|
||||
- paragraph:
|
||||
- text: "Line 1 Line 2 Line 3"
|
||||
`);
|
||||
await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- paragraph: |
|
||||
- paragraph:
|
||||
- text: |
|
||||
Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
|
@ -382,6 +388,22 @@ it('should include pseudo codepoints', async ({ page, server }) => {
|
|||
`);
|
||||
|
||||
await checkAndMatchSnapshot(page.locator('body'), `
|
||||
- paragraph: "\ueab2hello"
|
||||
- paragraph:
|
||||
- text: "\ueab2hello"
|
||||
`);
|
||||
});
|
||||
|
||||
it('check aria-hidden text', async ({ page, server }) => {
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
await page.setContent(`
|
||||
<p>
|
||||
<span>hello</span>
|
||||
<span aria-hidden="true">world</span>
|
||||
</p>
|
||||
`);
|
||||
|
||||
await checkAndMatchSnapshot(page.locator('body'), `
|
||||
- paragraph:
|
||||
- text: "hello"
|
||||
`);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue