mirror of
https://github.com/microsoft/playwright.git
synced 2024-11-28 17:44:33 +03:00
chore: fix more aria escaping edge cases (#33460)
This commit is contained in:
parent
9d94ad152e
commit
d4ad520a9b
@ -168,7 +168,6 @@ export class KeyParser {
|
||||
escaped = false;
|
||||
} else if (ch === '\\') {
|
||||
escaped = true;
|
||||
result += ch;
|
||||
} else if (ch === '"') {
|
||||
return result;
|
||||
} else {
|
||||
|
@ -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]`;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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/
|
||||
|
@ -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}\"
|
||||
+ \`);
|
||||
|
Loading…
Reference in New Issue
Block a user