diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts
deleted file mode 100644
index 516688fef3..0000000000
--- a/packages/playwright-core/src/server/ariaSnapshot.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright (c) Microsoft Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot';
-import type { AriaTemplateNode, ParsedYaml } from '@isomorphic/ariaSnapshot';
-import { yaml } from '../utilsBundle';
-
-export function parseAriaSnapshot(text: string): AriaTemplateNode {
- return parseYamlTemplate(parseYamlForAriaSnapshot(text));
-}
-
-export function parseYamlForAriaSnapshot(text: string): ParsedYaml {
- const parsed = yaml.parse(text);
- if (!Array.isArray(parsed))
- throw new Error('Expected object key starting with "- ":\n\n' + text + '\n');
- return parsed;
-}
diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts
index 176b6d2734..468b550f48 100644
--- a/packages/playwright-core/src/server/debugController.ts
+++ b/packages/playwright-core/src/server/debugController.ts
@@ -24,10 +24,9 @@ import type { Playwright } from './playwright';
import { Recorder } from './recorder';
import { EmptyRecorderApp } from './recorder/recorderApp';
import { asLocator, type Language } from '../utils';
-import { parseYamlForAriaSnapshot } from './ariaSnapshot';
-import type { ParsedYaml } from '../utils/isomorphic/ariaSnapshot';
-import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot';
+import { yaml } from '../utilsBundle';
import { unsafeLocatorOrSelectorAsSelector } from '../utils/isomorphic/locatorParser';
+import { parseAriaSnapshotUnsafe } from '../utils/isomorphic/ariaSnapshot';
const internalMetadata = serverSideCallMetadata();
@@ -125,14 +124,10 @@ export class DebugController extends SdkObject {
// Assert parameters validity.
if (params.selector)
unsafeLocatorOrSelectorAsSelector(this._sdkLanguage, params.selector, 'data-testid');
- let parsedYaml: ParsedYaml | undefined;
- if (params.ariaTemplate) {
- parsedYaml = parseYamlForAriaSnapshot(params.ariaTemplate);
- parseYamlTemplate(parsedYaml);
- }
+ const ariaTemplate = params.ariaTemplate ? parseAriaSnapshotUnsafe(yaml, params.ariaTemplate) : undefined;
for (const recorder of await this._allRecorders()) {
- if (parsedYaml)
- recorder.setHighlightedAriaTemplate(parsedYaml);
+ if (ariaTemplate)
+ recorder.setHighlightedAriaTemplate(ariaTemplate);
else if (params.selector)
recorder.setHighlightedSelector(this._sdkLanguage, params.selector);
}
diff --git a/packages/playwright-core/src/server/dispatchers/DEPS.list b/packages/playwright-core/src/server/dispatchers/DEPS.list
index de1039af05..cefc3fa04c 100644
--- a/packages/playwright-core/src/server/dispatchers/DEPS.list
+++ b/packages/playwright-core/src/server/dispatchers/DEPS.list
@@ -3,5 +3,7 @@
../../generated/
../../protocol/
../../utils/
+../../utils/isomorphic
+../../utilsBundle.ts
../../zipBundle.ts
../**
diff --git a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts
index 2f172df694..3426389a9c 100644
--- a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts
+++ b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts
@@ -26,7 +26,8 @@ import type { CallMetadata } from '../instrumentation';
import type { BrowserContextDispatcher } from './browserContextDispatcher';
import type { PageDispatcher } from './pageDispatcher';
import { debugAssert } from '../../utils';
-import { parseAriaSnapshot } from '../ariaSnapshot';
+import { parseAriaSnapshotUnsafe } from '../../utils/isomorphic/ariaSnapshot';
+import { yaml } from '../../utilsBundle';
export class FrameDispatcher extends Dispatcher implements channels.FrameChannel {
_type_Frame = true;
@@ -261,7 +262,7 @@ export class FrameDispatcher extends Dispatcher & { expectedValue?: any };
@@ -86,7 +86,7 @@ export class InjectedScript {
isElementVisible,
isInsideScope,
normalizeWhiteSpace,
- parseYamlTemplate,
+ parseAriaSnapshot,
};
// eslint-disable-next-line no-restricted-globals
diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts
index b24feec5d1..5a3f3d9a14 100644
--- a/packages/playwright-core/src/server/injected/recorder/recorder.ts
+++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts
@@ -1146,8 +1146,7 @@ export class Recorder {
const ariaTemplateJSON = JSON.stringify(state.ariaTemplate);
if (this._lastHighlightedAriaTemplateJSON !== ariaTemplateJSON) {
this._lastHighlightedAriaTemplateJSON = ariaTemplateJSON;
- const template = state.ariaTemplate ? this.injectedScript.utils.parseYamlTemplate(state.ariaTemplate) : undefined;
- const elements = template ? this.injectedScript.getAllByAria(this.document, template) : [];
+ const elements = state.ariaTemplate ? this.injectedScript.getAllByAria(this.document, state.ariaTemplate) : [];
if (elements.length)
highlight = { elements };
else
diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts
index 16f9d791e1..115639223c 100644
--- a/packages/playwright-core/src/server/recorder.ts
+++ b/packages/playwright-core/src/server/recorder.ts
@@ -32,7 +32,7 @@ import type * as actions from '@recorder/actions';
import { buildFullSelector } from '../utils/isomorphic/recorderUtils';
import { stringifySelector } from '../utils/isomorphic/selectorParser';
import type { Frame } from './frames';
-import type { ParsedYaml } from '@isomorphic/ariaSnapshot';
+import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
const recorderSymbol = Symbol('recorderSymbol');
@@ -40,7 +40,7 @@ export class Recorder implements InstrumentationListener, IRecorder {
readonly handleSIGINT: boolean | undefined;
private _context: BrowserContext;
private _mode: Mode;
- private _highlightedElement: { selector?: string, ariaTemplate?: ParsedYaml } = {};
+ private _highlightedElement: { selector?: string, ariaTemplate?: AriaTemplateNode } = {};
private _overlayState: OverlayState = { offsetX: 0 };
private _recorderApp: IRecorderApp | null = null;
private _currentCallsMetadata = new Map();
@@ -249,7 +249,7 @@ export class Recorder implements InstrumentationListener, IRecorder {
this._refreshOverlay();
}
- setHighlightedAriaTemplate(ariaTemplate: ParsedYaml) {
+ setHighlightedAriaTemplate(ariaTemplate: AriaTemplateNode) {
this._highlightedElement = { ariaTemplate };
this._refreshOverlay();
}
diff --git a/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts
index 59b26ec049..b04add5be9 100644
--- a/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts
+++ b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts
@@ -24,8 +24,6 @@ export type AriaRole = 'alert' | 'alertdialog' | 'application' | 'article' | 'ba
'spinbutton' | 'status' | 'strong' | 'subscript' | 'superscript' | 'switch' | 'tab' | 'table' | 'tablist' | 'tabpanel' | 'term' | 'textbox' | 'time' | 'timer' |
'toolbar' | 'tooltip' | 'tree' | 'treegrid' | 'treeitem';
-export type ParsedYaml = Array;
-
export type AriaProps = {
checked?: boolean | 'mixed';
disabled?: boolean;
@@ -35,89 +33,209 @@ export type AriaProps = {
selected?: boolean;
};
+// We pass parsed template between worlds using JSON, make it easy.
+export type AriaRegex = { pattern: string };
+
export type AriaTemplateTextNode = {
kind: 'text';
- text: RegExp | string;
+ text: AriaRegex | string;
};
export type AriaTemplateRoleNode = AriaProps & {
kind: 'role';
role: AriaRole | 'fragment';
- name?: RegExp | string;
+ name?: AriaRegex | string;
children?: AriaTemplateNode[];
};
export type AriaTemplateNode = AriaTemplateRoleNode | AriaTemplateTextNode;
-export function parseYamlTemplate(fragment: ParsedYaml): AriaTemplateNode {
- const result: AriaTemplateNode = { kind: 'role', role: 'fragment' };
- populateNode(result, fragment);
- if (result.children && result.children.length === 1)
- return result.children[0];
- return result;
+import type * as yamlTypes from 'yaml';
+
+type YamlLibrary = {
+ parseDocument: typeof yamlTypes.parseDocument;
+ Scalar: typeof yamlTypes.Scalar;
+ YAMLMap: typeof yamlTypes.YAMLMap;
+ YAMLSeq: typeof yamlTypes.YAMLSeq;
+ LineCounter: typeof yamlTypes.LineCounter;
+};
+
+type ParsedYamlPosition = { line: number; col: number; };
+
+export type ParsedYamlError = {
+ message: string;
+ range: [ParsedYamlPosition, ParsedYamlPosition];
+};
+
+export function parseAriaSnapshotUnsafe(yaml: YamlLibrary, text: string): AriaTemplateNode {
+ const result = parseAriaSnapshot(yaml, text);
+ if (result.errors.length)
+ throw new Error(result.errors[0].message);
+ return result.fragment;
}
-function populateNode(node: AriaTemplateRoleNode, container: ParsedYaml) {
- for (const object of container) {
- if (typeof object === 'string') {
- const childNode = KeyParser.parse(object);
- node.children = node.children || [];
- node.children.push(childNode);
- continue;
+export function parseAriaSnapshot(yaml: YamlLibrary, text: string, options: yamlTypes.ParseOptions = {}): { fragment: AriaTemplateNode, errors: ParsedYamlError[] } {
+ const lineCounter = new yaml.LineCounter();
+ const parseOptions: yamlTypes.ParseOptions = {
+ keepSourceTokens: true,
+ lineCounter,
+ ...options,
+ };
+ const yamlDoc = yaml.parseDocument(text, parseOptions);
+ const errors: ParsedYamlError[] = [];
+
+ const convertRange = (range: [number, number] | yamlTypes.Range): [ParsedYamlPosition, ParsedYamlPosition] => {
+ return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])];
+ };
+
+ const addError = (error: yamlTypes.YAMLError) => {
+ errors.push({
+ message: error.message,
+ range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])],
+ });
+ };
+
+ const convertSeq = (container: AriaTemplateRoleNode, seq: yamlTypes.YAMLSeq) => {
+ for (const item of seq.items) {
+ const itemIsString = item instanceof yaml.Scalar && typeof item.value === 'string';
+ if (itemIsString) {
+ const childNode = KeyParser.parse(item, parseOptions, errors);
+ if (childNode) {
+ container.children = container.children || [];
+ container.children.push(childNode);
+ }
+ continue;
+ }
+ const itemIsMap = item instanceof yaml.YAMLMap;
+ if (itemIsMap) {
+ convertMap(container, item);
+ continue;
+ }
+ errors.push({
+ message: 'Sequence items should be strings or maps',
+ range: convertRange((item as any).range || seq.range),
+ });
}
+ };
- for (const key of Object.keys(object)) {
- node.children = node.children || [];
- const value = object[key];
-
- if (key === 'text') {
- node.children.push({
- kind: 'text',
- text: valueOrRegex(value)
+ const convertMap = (container: AriaTemplateRoleNode, map: yamlTypes.YAMLMap) => {
+ for (const entry of map.items) {
+ container.children = container.children || [];
+ // Key must by a string
+ const keyIsString = entry.key instanceof yaml.Scalar && typeof entry.key.value === 'string';
+ if (!keyIsString) {
+ errors.push({
+ message: 'Only string keys are supported',
+ range: convertRange((entry.key as any).range || map.range),
});
continue;
}
- const childNode = KeyParser.parse(key);
- if (childNode.kind === 'text') {
- node.children.push({
+ const key: yamlTypes.Scalar = entry.key as yamlTypes.Scalar;
+ const value = entry.value;
+
+ // - text: "text"
+ if (key.value === 'text') {
+ const valueIsString = value instanceof yaml.Scalar && typeof value.value === 'string';
+ if (!valueIsString) {
+ errors.push({
+ message: 'Text value should be a string',
+ range: convertRange(((entry.value as any).range || map.range)),
+ });
+ continue;
+ }
+ container.children.push({
kind: 'text',
- text: valueOrRegex(value)
+ text: valueOrRegex(value.value)
});
continue;
}
- if (typeof value === 'string') {
- node.children.push({
- ...childNode, children: [{
+ // role "name": ...
+ const childNode = KeyParser.parse(key, parseOptions, errors);
+ if (!childNode)
+ continue;
+
+ // - role "name": "text"
+ const valueIsScalar = value instanceof yaml.Scalar;
+ if (valueIsScalar) {
+ container.children.push({
+ ...childNode,
+ children: [{
kind: 'text',
- text: valueOrRegex(value)
+ text: valueOrRegex(String(value.value))
}]
});
continue;
}
- node.children.push(childNode);
- populateNode(childNode, value);
+ // - role "name":
+ // - child
+ const valueIsSequence = value instanceof yaml.YAMLSeq ;
+ if (valueIsSequence) {
+ convertSeq(childNode, value as yamlTypes.YAMLSeq);
+ continue;
+ }
+
+ errors.push({
+ message: 'Map values should be strings or sequences',
+ range: convertRange((entry.value as any).range || map.range),
+ });
}
+ };
+
+ const fragment: AriaTemplateNode = { kind: 'role', role: 'fragment' };
+
+ yamlDoc.errors.forEach(addError);
+ if (errors.length)
+ return { errors, fragment };
+
+ if (!(yamlDoc.contents instanceof yaml.YAMLSeq)) {
+ errors.push({
+ message: 'Aria snapshot must be a YAML sequence, elements starting with " -"',
+ range: convertRange(yamlDoc.contents!.range),
+ });
}
+ if (errors.length)
+ return { errors, fragment };
+
+ convertSeq(fragment, yamlDoc.contents as yamlTypes.YAMLSeq);
+ if (errors.length)
+ return { errors, fragment: emptyFragment };
+ if (fragment.children?.length === 1)
+ return { fragment: fragment.children[0], errors };
+ return { fragment, errors };
}
+const emptyFragment: AriaTemplateRoleNode = { kind: 'role', role: 'fragment' };
+
function normalizeWhitespace(text: string) {
return text.replace(/[\r\n\s\t]+/g, ' ').trim();
}
-function valueOrRegex(value: string): string | RegExp {
- return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value);
+export function valueOrRegex(value: string): string | AriaRegex {
+ return value.startsWith('/') && value.endsWith('/') ? { pattern: value.slice(1, -1) } : normalizeWhitespace(value);
}
-class KeyParser {
+export class KeyParser {
private _input: string;
private _pos: number;
private _length: number;
- static parse(input: string): AriaTemplateNode {
- return new KeyParser(input)._parse();
+ static parse(text: yamlTypes.Scalar, options: yamlTypes.ParseOptions, errors: ParsedYamlError[]): AriaTemplateRoleNode | null {
+ try {
+ return new KeyParser(text.value)._parse();
+ } catch (e) {
+ if (e instanceof ParserError) {
+ const message = options.prettyErrors === false ? e.message : e.message + ':\n\n' + text.value + '\n' + ' '.repeat(e.pos) + '^\n';
+ errors.push({
+ message,
+ range: [options.lineCounter!.linePos(text.range![0]), options.lineCounter!.linePos(text.range![0] + e.pos)],
+ });
+ return null;
+ }
+ throw e;
+ }
}
constructor(input: string) {
@@ -177,11 +295,11 @@ class KeyParser {
this._throwError('Unterminated string');
}
- private _throwError(message: string, pos?: number): never {
- throw new AriaKeyError(message, this._input, pos || this._pos);
+ private _throwError(message: string, offset: number = 0): never {
+ throw new ParserError(message, offset || this._pos);
}
- private _readRegex(): string {
+ private _readRegex(): AriaRegex {
let result = '';
let escaped = false;
let insideClass = false;
@@ -194,7 +312,7 @@ class KeyParser {
escaped = true;
result += ch;
} else if (ch === '/' && !insideClass) {
- return result;
+ return { pattern: result };
} else if (ch === '[') {
insideClass = true;
result += ch;
@@ -208,7 +326,7 @@ class KeyParser {
this._throwError('Unterminated regex');
}
- private _readStringOrRegex(): string | RegExp | null {
+ private _readStringOrRegex(): string | AriaRegex | null {
const ch = this._peek();
if (ch === '"') {
this._next();
@@ -217,7 +335,7 @@ class KeyParser {
if (ch === '/') {
this._next();
- return new RegExp(this._readRegex());
+ return this._readRegex();
}
return null;
@@ -253,7 +371,7 @@ class KeyParser {
}
}
- _parse(): AriaTemplateNode {
+ _parse(): AriaTemplateRoleNode {
this._skipWhitespace();
const role = this._readIdentifier('role') as AriaTemplateRoleNode['role'];
@@ -307,18 +425,11 @@ class KeyParser {
}
}
-export function parseAriaKey(key: string) {
- return KeyParser.parse(key);
-}
-
-export class AriaKeyError extends Error {
- readonly shortMessage: string;
+export class ParserError extends Error {
readonly pos: number;
- constructor(message: string, input: string, pos: number) {
- super(message + ':\n\n' + input + '\n' + ' '.repeat(pos) + '^\n');
- this.shortMessage = message;
+ constructor(message: string, pos: number) {
+ super(message);
this.pos = pos;
- this.stack = undefined;
}
}
diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts
index 72bcee397e..fba52c05a8 100644
--- a/packages/playwright-core/src/utilsBundle.ts
+++ b/packages/playwright-core/src/utilsBundle.ts
@@ -33,6 +33,7 @@ export const program: typeof import('../bundles/utils/node_modules/commander').p
export const progress: typeof import('../bundles/utils/node_modules/@types/progress') = require('./utilsBundleImpl').progress;
export const SocksProxyAgent: typeof import('../bundles/utils/node_modules/socks-proxy-agent').SocksProxyAgent = require('./utilsBundleImpl').SocksProxyAgent;
export const yaml: typeof import('../bundles/utils/node_modules/yaml') = require('./utilsBundleImpl').yaml;
+export type { Scalar as YAMLScalar, YAMLSeq, YAMLMap, YAMLError, Range as YAMLRange } from '../bundles/utils/node_modules/yaml';
export const ws: typeof import('../bundles/utils/node_modules/@types/ws') = require('./utilsBundleImpl').ws;
export const wsServer: typeof import('../bundles/utils/node_modules/@types/ws').WebSocketServer = require('./utilsBundleImpl').wsServer;
export const wsReceiver = require('./utilsBundleImpl').wsReceiver;
diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx
index a34131a2c8..bf0ead8ce2 100644
--- a/packages/recorder/src/recorder.tsx
+++ b/packages/recorder/src/recorder.tsx
@@ -29,8 +29,7 @@ import { asLocator } from '@isomorphic/locatorGenerators';
import { toggleTheme } from '@web/theme';
import { copy, useSetting } from '@web/uiUtils';
import yaml from 'yaml';
-import { parseAriaKey } from '@isomorphic/ariaSnapshot';
-import type { AriaKeyError, ParsedYaml } from '@isomorphic/ariaSnapshot';
+import { parseAriaSnapshot } from '@isomorphic/ariaSnapshot';
export interface RecorderProps {
sources: Source[],
@@ -117,8 +116,17 @@ export const Recorder: React.FC = ({
const onAriaEditorChange = React.useCallback((ariaSnapshot: string) => {
if (mode === 'none' || mode === 'inspecting')
window.dispatch({ event: 'setMode', params: { mode: 'standby' } });
- const { fragment, errors } = parseAriaSnapshot(ariaSnapshot);
- setAriaSnapshotErrors(errors);
+ const { fragment, errors } = parseAriaSnapshot(yaml, ariaSnapshot, { prettyErrors: false });
+ const highlights = errors.map(error => {
+ const highlight: SourceHighlight = {
+ message: error.message,
+ line: error.range[1].line,
+ column: error.range[1].col,
+ type: 'subtle-error',
+ };
+ return highlight;
+ });
+ setAriaSnapshotErrors(highlights);
setAriaSnapshot(ariaSnapshot);
if (!errors.length)
window.dispatch({ event: 'highlightRequested', params: { ariaTemplate: fragment } });
@@ -208,57 +216,3 @@ export const Recorder: React.FC = ({
/>
;
};
-
-function parseAriaSnapshot(ariaSnapshot: string): { fragment?: ParsedYaml, errors: SourceHighlight[] } {
- const lineCounter = new yaml.LineCounter();
- const yamlDoc = yaml.parseDocument(ariaSnapshot, {
- keepSourceTokens: true,
- lineCounter,
- prettyErrors: false,
- });
-
- const errors: SourceHighlight[] = [];
- for (const error of yamlDoc.errors) {
- errors.push({
- line: lineCounter.linePos(error.pos[0]).line,
- type: 'subtle-error',
- message: error.message,
- });
- }
-
- if (yamlDoc.errors.length)
- return { errors };
-
- const handleKey = (key: yaml.Scalar) => {
- try {
- parseAriaKey(key.value);
- } catch (e) {
- const keyError = e as AriaKeyError;
- const linePos = lineCounter.linePos(key.srcToken!.offset + keyError.pos);
- errors.push({
- message: keyError.shortMessage,
- line: linePos.line,
- column: linePos.col,
- type: 'subtle-error',
- });
- }
- };
- const visitSeq = (seq: yaml.YAMLSeq) => {
- for (const item of seq.items) {
- if (item instanceof yaml.YAMLMap) {
- const map = item as yaml.YAMLMap;
- for (const entry of map.items) {
- if (entry.key instanceof yaml.Scalar)
- handleKey(entry.key);
- if (entry.value instanceof yaml.YAMLSeq)
- visitSeq(entry.value);
- }
- continue;
- }
- if (item instanceof yaml.Scalar)
- handleKey(item);
- }
- };
- visitSeq(yamlDoc.contents as yaml.YAMLSeq);
- return errors.length ? { errors } : { fragment: yamlDoc.toJSON(), errors };
-}
diff --git a/packages/recorder/src/recorderTypes.d.ts b/packages/recorder/src/recorderTypes.d.ts
index 4822dda46f..22561608ae 100644
--- a/packages/recorder/src/recorderTypes.d.ts
+++ b/packages/recorder/src/recorderTypes.d.ts
@@ -15,7 +15,7 @@
*/
import type { Language } from '../../playwright-core/src/utils/isomorphic/locatorGenerators';
-import type { ParsedYaml } from '@isomorphic/ariaSnapshot';
+import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot';
export type Point = { x: number; y: number };
@@ -55,7 +55,7 @@ export type UIState = {
mode: Mode;
actionPoint?: Point;
actionSelector?: string;
- ariaTemplate?: ParsedYaml;
+ ariaTemplate?: AriaTemplateNode;
language: Language;
testIdAttributeName: string;
overlay: OverlayState;
diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts
index 3961d6ad0a..ac94909741 100644
--- a/tests/page/to-match-aria-snapshot.spec.ts
+++ b/tests/page/to-match-aria-snapshot.spec.ts
@@ -521,10 +521,7 @@ test('should report error in YAML', async ({ page }) => {
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"
-`);
+ expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Aria snapshot must be a YAML sequence, elements starting with " -"`);
}
{