chore: improve aria template error reporting (#33438)
This commit is contained in:
parent
36a975c30b
commit
f138c30915
|
|
@ -19,7 +19,9 @@ import { yaml } from '../utilsBundle';
|
|||
import { assert } from '../utils';
|
||||
|
||||
export function parseAriaSnapshot(text: string): AriaTemplateNode {
|
||||
const fragment = yaml.parse(text) as any[];
|
||||
const fragment = yaml.parse(text);
|
||||
if (!Array.isArray(fragment))
|
||||
throw new Error('Expected object key starting with "- ":\n\n' + text + '\n');
|
||||
const result: AriaTemplateNode = { kind: 'role', role: 'fragment' };
|
||||
populateNode(result, fragment);
|
||||
return result;
|
||||
|
|
@ -73,7 +75,7 @@ function populateNode(node: AriaTemplateRoleNode, container: any[]) {
|
|||
|
||||
function applyAttribute(node: AriaTemplateRoleNode, key: string, value: string) {
|
||||
if (key === 'checked') {
|
||||
assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "disabled" attribute must be a boolean or "mixed"');
|
||||
assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "checked\" attribute must be a boolean or "mixed"');
|
||||
node.checked = value === 'true' ? true : value === 'false' ? false : 'mixed';
|
||||
return;
|
||||
}
|
||||
|
|
@ -149,7 +151,7 @@ export class KeyParser {
|
|||
|
||||
private _readIdentifier(): string {
|
||||
if (this._eof())
|
||||
throw new Error('Unexpected end of input when expecting identifier');
|
||||
this._throwError('Unexpected end of input when expecting identifier');
|
||||
const start = this._pos;
|
||||
while (!this._eof() && /[a-zA-Z]/.test(this._peek()))
|
||||
this._pos++;
|
||||
|
|
@ -173,7 +175,11 @@ export class KeyParser {
|
|||
result += ch;
|
||||
}
|
||||
}
|
||||
throw new Error('Unterminated string starting at position ' + this._pos);
|
||||
this._throwError('Unterminated string');
|
||||
}
|
||||
|
||||
private _throwError(message: string): never {
|
||||
throw new Error(message + ':\n\n' + this._input + '\n' + ' '.repeat(this._pos) + '^\n');
|
||||
}
|
||||
|
||||
private _readRegex(): string {
|
||||
|
|
@ -193,7 +199,7 @@ export class KeyParser {
|
|||
result += ch;
|
||||
}
|
||||
}
|
||||
throw new Error('Unterminated regex starting at position ' + this._pos);
|
||||
this._throwError('Unterminated regex');
|
||||
}
|
||||
|
||||
private _readStringOrRegex(): string | RegExp | null {
|
||||
|
|
@ -229,7 +235,7 @@ export class KeyParser {
|
|||
}
|
||||
this._skipWhitespace();
|
||||
if (this._peek() !== ']')
|
||||
throw new Error('Expected ] at position ' + this._pos);
|
||||
this._throwError('Expected ]');
|
||||
|
||||
this._next(); // Consume ']'
|
||||
flags.set(flagName, flagValue || 'true');
|
||||
|
|
@ -252,8 +258,7 @@ export class KeyParser {
|
|||
applyAttribute(result, name, value);
|
||||
this._skipWhitespace();
|
||||
if (!this._eof())
|
||||
throw new Error('Unexpected input at position ' + this._pos);
|
||||
|
||||
this._throwError('Unexpected input');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -458,3 +458,100 @@ test('should unpack escaped names', async ({ page }) => {
|
|||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test('should report error in YAML', async ({ page }) => {
|
||||
await page.setContent(`<h1>title</h1>`);
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
heading "title"
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Expected object key starting with "- ":
|
||||
|
||||
heading "title"
|
||||
`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading: a:
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Nested mappings are not allowed in compact mappings at line 1, column 12:
|
||||
|
||||
- heading: a:
|
||||
^
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test('should report error in YAML keys', async ({ page }) => {
|
||||
await page.setContent(`<h1>title</h1>`);
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading "title
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unterminated string:
|
||||
|
||||
heading "title
|
||||
^
|
||||
`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading /title
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unterminated regex:
|
||||
|
||||
heading /title
|
||||
^
|
||||
`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading [level=a]
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "level" attribute must be a number`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading [expanded=FALSE]
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "expanded" attribute must be a boolean`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading [checked=foo]
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "checked" attribute must be a boolean or "mixed"`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading [level=]
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "level" attribute must be a number`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading [bogus]
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unsupported attribute [bogus]`);
|
||||
}
|
||||
|
||||
{
|
||||
const error = await expect(page.locator('body')).toMatchAriaSnapshot(`
|
||||
- heading invalid
|
||||
`).catch(e => e);
|
||||
expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unexpected input:
|
||||
|
||||
heading invalid
|
||||
^
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue