chore: fix more aria escaping edge cases (#33460)

This commit is contained in:
Pavel Feldman 2024-11-05 16:22:02 -08:00 committed by GitHub
parent 9d94ad152e
commit d4ad520a9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 24 additions and 31 deletions

View File

@ -168,7 +168,6 @@ export class KeyParser {
escaped = false;
} else if (ch === '\\') {
escaped = true;
result += ch;
} else if (ch === '"') {
return result;
} else {

View File

@ -18,7 +18,7 @@ import * as roleUtils from './roleUtils';
import { getElementComputedStyle } from './domUtils';
import type { AriaRole } from './roleUtils';
import { escapeRegExp, longestCommonSubstring } from '@isomorphic/stringUtils';
import { yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded, yamlQuoteFragment } from './yaml';
import { yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded } from './yaml';
type AriaProps = {
checked?: boolean | 'mixed';
@ -318,8 +318,10 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'r
let key = ariaNode.role;
if (ariaNode.name) {
const name = renderString(ariaNode.name);
if (name)
key += ' ' + (name.startsWith('/') && name.endsWith('/') ? name : yamlQuoteFragment(name));
if (name) {
const stringifiedName = name.startsWith('/') && name.endsWith('/') ? name : JSON.stringify(name);
key += ' ' + stringifiedName;
}
}
if (ariaNode.checked === 'mixed')
key += ` [checked=mixed]`;

View File

@ -46,19 +46,6 @@ export function yamlEscapeValueIfNeeded(str: string): string {
}) + '"';
}
export function yamlQuoteFragment(str: string, quote = '"'): string {
return quote + str.replace(/['"]/g, c => {
switch (c) {
case '"':
return quote === '"' ? '\\"' : '"';
case '\'':
return quote === '\'' ? '\\\'' : '\'';
default:
return c;
}
}) + quote;
}
function yamlStringNeedsQuotes(str: string): boolean {
if (str.length === 0)
return true;

View File

@ -85,19 +85,18 @@ export async function toMatchAriaSnapshot(
};
}
const escapedExpected = escapePrivateUsePoints(expected);
const escapedReceived = escapePrivateUsePoints(typedReceived.raw);
const receivedText = typedReceived.raw;
const message = () => {
if (pass) {
if (notFound)
return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log);
const printedReceived = printReceivedStringContainExpectedSubstring(escapedReceived, escapedReceived.indexOf(escapedExpected), escapedExpected.length);
return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived: ${printedReceived}` + callLogText(log);
return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log);
const printedReceived = printReceivedStringContainExpectedSubstring(receivedText, receivedText.indexOf(expected), expected.length);
return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${printedReceived}` + callLogText(log);
} else {
const labelExpected = `Expected`;
if (notFound)
return messagePrefix + `${labelExpected}: ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log);
return messagePrefix + this.utils.printDiffOrStringify(escapedExpected, escapedReceived, labelExpected, 'Received', false) + callLogText(log);
return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log);
return messagePrefix + this.utils.printDiffOrStringify(expected, receivedText, labelExpected, 'Received', false) + callLogText(log);
}
};
@ -118,10 +117,6 @@ export async function toMatchAriaSnapshot(
};
}
function escapePrivateUsePoints(str: string) {
return escapeTemplateString(str).replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
}
function unshift(snapshot: string): string {
const lines = snapshot.split('\n');
let whitespacePrefixLength = 100;

View File

@ -436,10 +436,16 @@ test('should unpack escaped names', async ({ page }) => {
{
await page.setContent(`
<button>Click \\ me</button>
<button>Click " me</button>
`);
await expect(page.locator('body')).toMatchAriaSnapshot(`
- button "Click \\ me"
- button "Click \\\" me"
`);
}
{
await page.setContent(`
<button>Click \\ me</button>
`);
await expect(page.locator('body')).toMatchAriaSnapshot(`
- button /Click \\\\ me/

View File

@ -166,6 +166,8 @@ test('should generate baseline with special characters', async ({ runInlineTest
<button>Click: 123</button>
<button>Click ' me</button>
<button>Click: ' me</button>
<button>Click " me</button>
<button>Click \\\\ me</button>
<li>Item: 1</li>
<li>Item {a: b}</li>
</ul>\`);
@ -179,7 +181,7 @@ test('should generate baseline with special characters', async ({ runInlineTest
const data = fs.readFileSync(patchPath, 'utf-8');
expect(data).toBe(`--- a/a.spec.ts
+++ b/a.spec.ts
@@ -9,6 +9,14 @@
@@ -11,6 +11,16 @@
<li>Item: 1</li>
<li>Item {a: b}</li>
</ul>\`);
@ -190,6 +192,8 @@ test('should generate baseline with special characters', async ({ runInlineTest
+ - 'button /Click: \\\\d+/'
+ - button "Click ' me"
+ - 'button "Click: '' me"'
+ - button "Click \\\\" me"
+ - button "Click \\\\\\\\ me"
+ - listitem: \"Item: 1\"
+ - listitem: \"Item {a: b}\"
+ \`);