Skip to content

Commit 1f2eb49

Browse files
authored
fix(aria snapshots): normalize whitespace (#34285)
1 parent 4f3a5e2 commit 1f2eb49

File tree

3 files changed

+30
-6
lines changed

3 files changed

+30
-6
lines changed

packages/playwright-core/src/server/injected/ariaSnapshot.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import * as roleUtils from './roleUtils';
1818
import { getElementComputedStyle } from './domUtils';
19-
import { escapeRegExp, longestCommonSubstring } from '@isomorphic/stringUtils';
19+
import { escapeRegExp, longestCommonSubstring, normalizeWhiteSpace } from '@isomorphic/stringUtils';
2020
import { yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded } from './yaml';
2121
import type { AriaProps, AriaRole, AriaTemplateNode, AriaTemplateRoleNode, AriaTemplateTextNode } from '@isomorphic/ariaSnapshot';
2222

@@ -137,7 +137,7 @@ function toAriaNode(element: Element): AriaNode | null {
137137
if (!role || role === 'presentation' || role === 'none')
138138
return null;
139139

140-
const name = roleUtils.getElementAccessibleName(element, false) || '';
140+
const name = normalizeWhiteSpace(roleUtils.getElementAccessibleName(element, false) || '');
141141
const result: AriaNode = { role, name, children: [], element };
142142

143143
if (roleUtils.kAriaCheckedRoles.includes(role))
@@ -170,7 +170,7 @@ function normalizeStringChildren(rootA11yNode: AriaNode) {
170170
const flushChildren = (buffer: string[], normalizedChildren: (AriaNode | string)[]) => {
171171
if (!buffer.length)
172172
return;
173-
const text = normalizeWhitespaceWithin(buffer.join('')).trim();
173+
const text = normalizeWhiteSpace(buffer.join(''));
174174
if (text)
175175
normalizedChildren.push(text);
176176
buffer.length = 0;
@@ -196,8 +196,6 @@ function normalizeStringChildren(rootA11yNode: AriaNode) {
196196
visit(rootA11yNode);
197197
}
198198

199-
const normalizeWhitespaceWithin = (text: string) => text.replace(/[\u200b\s\t\r\n]+/g, ' ');
200-
201199
function matchesText(text: string, template: RegExp | string | undefined): boolean {
202200
if (!template)
203201
return true;

packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class KeyParser {
212212
const ch = this._peek();
213213
if (ch === '"') {
214214
this._next();
215-
return this._readString();
215+
return normalizeWhitespace(this._readString());
216216
}
217217

218218
if (ch === '/') {

tests/page/page-aria-snapshot.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,32 @@ it('should escape yaml text in text nodes', async ({ page }) => {
509509
`);
510510
});
511511

512+
it('should normalize whitespace', async ({ page }) => {
513+
await page.setContent(`
514+
<details>
515+
<summary> one \n two <a href="#"> link &nbsp;\n 1 </a> </summary>
516+
</details>
517+
<input value=' hello &nbsp; world '>
518+
`);
519+
520+
await checkAndMatchSnapshot(page.locator('body'), `
521+
- group:
522+
- text: one two
523+
- link "link 1"
524+
- textbox: hello world
525+
`);
526+
527+
// Weird whitespace in the template should be normalized.
528+
await expect(page.locator('body')).toMatchAriaSnapshot(`
529+
- group:
530+
- text: |
531+
one
532+
two
533+
- link " link 1 "
534+
- textbox: hello world
535+
`);
536+
});
537+
512538
it('should handle long strings', async ({ page }) => {
513539
const s = 'a'.repeat(10000);
514540
await page.setContent(`

0 commit comments

Comments
 (0)