chore: update missing snapshots by default (#33311)
This commit is contained in:
parent
c66af9c525
commit
74e5e5560f
|
|
@ -107,7 +107,7 @@ export function generateAriaTree(rootElement: Element): AriaNode {
|
||||||
|
|
||||||
function toAriaNode(element: Element): AriaNode | null {
|
function toAriaNode(element: Element): AriaNode | null {
|
||||||
const role = roleUtils.getAriaRole(element);
|
const role = roleUtils.getAriaRole(element);
|
||||||
if (!role)
|
if (!role || role === 'presentation' || role === 'none')
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const name = roleUtils.getElementAccessibleName(element, false) || '';
|
const name = roleUtils.getElementAccessibleName(element, false) || '';
|
||||||
|
|
@ -168,7 +168,7 @@ function normalizeStringChildren(rootA11yNode: AriaNode) {
|
||||||
visit(rootA11yNode);
|
visit(rootA11yNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizeWhitespaceWithin = (text: string) => text.replace(/[\s\t\r\n]+/g, ' ');
|
const normalizeWhitespaceWithin = (text: string) => text.replace(/[\u200b\s\t\r\n]+/g, ' ');
|
||||||
|
|
||||||
function matchesText(text: string | undefined, template: RegExp | string | undefined) {
|
function matchesText(text: string | undefined, template: RegExp | string | undefined) {
|
||||||
if (!template)
|
if (!template)
|
||||||
|
|
@ -251,11 +251,12 @@ function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean {
|
||||||
return !!results.length;
|
return !!results.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderAriaTree(ariaNode: AriaNode): string {
|
export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean }): string {
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
const visit = (ariaNode: AriaNode | string, indent: string) => {
|
const visit = (ariaNode: AriaNode | string, indent: string) => {
|
||||||
if (typeof ariaNode === 'string') {
|
if (typeof ariaNode === 'string') {
|
||||||
lines.push(indent + '- text: ' + quoteYamlString(ariaNode));
|
if (!options?.noText)
|
||||||
|
lines.push(indent + '- text: ' + quoteYamlString(ariaNode));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let line = `${indent}- ${ariaNode.role}`;
|
let line = `${indent}- ${ariaNode.role}`;
|
||||||
|
|
@ -282,7 +283,8 @@ export function renderAriaTree(ariaNode: AriaNode): string {
|
||||||
if (!ariaNode.children.length) {
|
if (!ariaNode.children.length) {
|
||||||
lines.push(line);
|
lines.push(line);
|
||||||
} else if (ariaNode.children.length === 1 && typeof ariaNode.children[0] === 'string') {
|
} else if (ariaNode.children.length === 1 && typeof ariaNode.children[0] === 'string') {
|
||||||
line += ': ' + quoteYamlString(ariaNode.children[0]);
|
if (!options?.noText)
|
||||||
|
line += ': ' + quoteYamlString(ariaNode.children[0]);
|
||||||
lines.push(line);
|
lines.push(line);
|
||||||
} else {
|
} else {
|
||||||
lines.push(line + ':');
|
lines.push(line + ':');
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export function matcherHint(state: ExpectMatcherState, locator: Locator | undefi
|
||||||
|
|
||||||
export type MatcherResult<E, A> = {
|
export type MatcherResult<E, A> = {
|
||||||
name: string;
|
name: string;
|
||||||
expected: E;
|
expected?: E;
|
||||||
message: () => string;
|
message: () => string;
|
||||||
pass: boolean;
|
pass: boolean;
|
||||||
actual?: A;
|
actual?: A;
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ export async function toMatchAriaSnapshot(
|
||||||
|
|
||||||
const testInfo = currentTestInfo();
|
const testInfo = currentTestInfo();
|
||||||
if (!testInfo)
|
if (!testInfo)
|
||||||
throw new Error(`toMatchSnapshot() must be called during the test`);
|
throw new Error(`toMatchAriaSnapshot() must be called during the test`);
|
||||||
|
|
||||||
if (testInfo._projectInternal.ignoreSnapshots)
|
if (testInfo._projectInternal.ignoreSnapshots)
|
||||||
return { pass: !this.isNot, message: () => '', name: 'toMatchSnapshot', expected };
|
return { pass: !this.isNot, message: () => '', name: 'toMatchAriaSnapshot', expected };
|
||||||
|
|
||||||
const updateSnapshots = testInfo.config.updateSnapshots;
|
const updateSnapshots = testInfo.config.updateSnapshots;
|
||||||
|
|
||||||
|
|
@ -54,13 +54,27 @@ export async function toMatchAriaSnapshot(
|
||||||
].join('\n\n'));
|
].join('\n\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generateMissingBaseline = updateSnapshots === 'missing' && !expected;
|
||||||
|
const generateNewBaseline = updateSnapshots === 'all' || generateMissingBaseline;
|
||||||
|
|
||||||
|
if (generateMissingBaseline) {
|
||||||
|
if (this.isNot) {
|
||||||
|
const message = `Matchers using ".not" can't generate new baselines`;
|
||||||
|
return { pass: this.isNot, message: () => message, name: 'toMatchAriaSnapshot' };
|
||||||
|
} else {
|
||||||
|
// When generating new baseline, run entire pipeline against impossible match.
|
||||||
|
expected = `- none "Generating new baseline"`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const timeout = options.timeout ?? this.timeout;
|
const timeout = options.timeout ?? this.timeout;
|
||||||
|
expected = unshift(expected);
|
||||||
const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: expected, isNot: this.isNot, timeout });
|
const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: expected, isNot: this.isNot, timeout });
|
||||||
|
|
||||||
const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
|
const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
|
||||||
const notFound = received === kNoElementsFoundError;
|
const notFound = received === kNoElementsFoundError;
|
||||||
const escapedExpected = unshift(escapePrivateUsePoints(expected));
|
const escapedExpected = escapePrivateUsePoints(expected);
|
||||||
const escapedReceived = unshift(escapePrivateUsePoints(received));
|
const escapedReceived = escapePrivateUsePoints(received);
|
||||||
const message = () => {
|
const message = () => {
|
||||||
if (pass) {
|
if (pass) {
|
||||||
if (notFound)
|
if (notFound)
|
||||||
|
|
@ -75,10 +89,10 @@ export async function toMatchAriaSnapshot(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let suggestedRebaseline: string | undefined;
|
if (!this.isNot && pass === this.isNot && generateNewBaseline) {
|
||||||
if (!this.isNot && pass === this.isNot) {
|
// Only rebaseline failed snapshots.
|
||||||
if (updateSnapshots === 'all' || (updateSnapshots === 'missing' && !expected.trim()))
|
const suggestedRebaseline = `toMatchAriaSnapshot(\`\n${indent(received, '${indent} ')}\n\${indent}\`)`;
|
||||||
suggestedRebaseline = `toMatchAriaSnapshot(\`\n${unshift(received, '${indent} ')}\n\${indent}\`)`;
|
return { pass: this.isNot, message: () => '', name: 'toMatchAriaSnapshot', suggestedRebaseline };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -88,7 +102,6 @@ export async function toMatchAriaSnapshot(
|
||||||
pass,
|
pass,
|
||||||
actual: received,
|
actual: received,
|
||||||
log,
|
log,
|
||||||
suggestedRebaseline,
|
|
||||||
timeout: timedOut ? timeout : undefined,
|
timeout: timedOut ? timeout : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +110,7 @@ function escapePrivateUsePoints(str: string) {
|
||||||
return str.replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
return str.replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unshift(snapshot: string, indent: string = ''): string {
|
function unshift(snapshot: string): string {
|
||||||
const lines = snapshot.split('\n');
|
const lines = snapshot.split('\n');
|
||||||
let whitespacePrefixLength = 100;
|
let whitespacePrefixLength = 100;
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
|
|
@ -108,5 +121,9 @@ function unshift(snapshot: string, indent: string = ''): string {
|
||||||
whitespacePrefixLength = match[1].length;
|
whitespacePrefixLength = match[1].length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return lines.filter(t => t.trim()).map(line => indent + line.substring(whitespacePrefixLength)).join('\n');
|
return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function indent(snapshot: string, indent: string): string {
|
||||||
|
return snapshot.split('\n').map(line => indent + line).join('\n');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ export const SourceTab: React.FunctionComponent<{
|
||||||
<CopyToClipboard description='Copy filename' value={shortFileName}/>
|
<CopyToClipboard description='Copy filename' value={shortFileName}/>
|
||||||
{location && <ToolbarButton icon='link-external' title='Open in VS Code' onClick={openExternally}></ToolbarButton>}
|
{location && <ToolbarButton icon='link-external' title='Open in VS Code' onClick={openExternally}></ToolbarButton>}
|
||||||
</Toolbar> }
|
</Toolbar> }
|
||||||
<CodeMirrorWrapper text={source.content || ''} language='javascript' highlight={highlight} revealLine={targetLine} readOnly={true} lineNumbers={true} />
|
<CodeMirrorWrapper text={source.content || ''} language='javascript' highlight={highlight} revealLine={targetLine} readOnly={true} lineNumbers={true} dataTestId='source-code-mirror'/>
|
||||||
</div>}
|
</div>}
|
||||||
sidebar={<StackTraceView stack={stack} selectedFrame={selectedFrame} setSelectedFrame={setSelectedFrame} />}
|
sidebar={<StackTraceView stack={stack} selectedFrame={selectedFrame} setSelectedFrame={setSelectedFrame} />}
|
||||||
/>;
|
/>;
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ export const FiltersView: React.FC<{
|
||||||
<span className='filter-label'>Projects:</span> {projectsLine}
|
<span className='filter-label'>Projects:</span> {projectsLine}
|
||||||
</div>
|
</div>
|
||||||
{expanded && <div className='hbox' style={{ marginLeft: 14, maxHeight: 200, overflowY: 'auto' }}>
|
{expanded && <div className='hbox' style={{ marginLeft: 14, maxHeight: 200, overflowY: 'auto' }}>
|
||||||
<div className='filter-list'>
|
<div className='filter-list' role='list' data-testid='status-filters'>
|
||||||
{[...statusFilters.entries()].map(([status, value]) => {
|
{[...statusFilters.entries()].map(([status, value]) => {
|
||||||
return <div className='filter-entry' key={status}>
|
return <div className='filter-entry' key={status} role='listitem'>
|
||||||
<label>
|
<label>
|
||||||
<input type='checkbox' checked={value} onClick={() => {
|
<input type='checkbox' checked={value} onClick={() => {
|
||||||
const copy = new Map(statusFilters);
|
const copy = new Map(statusFilters);
|
||||||
|
|
@ -72,9 +72,9 @@ export const FiltersView: React.FC<{
|
||||||
</div>;
|
</div>;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className='filter-list'>
|
<div className='filter-list' role='list' data-testid='project-filters'>
|
||||||
{[...projectFilters.entries()].map(([projectName, value]) => {
|
{[...projectFilters.entries()].map(([projectName, value]) => {
|
||||||
return <div className='filter-entry' key={projectName}>
|
return <div className='filter-entry' key={projectName} role='listitem'>
|
||||||
<label>
|
<label>
|
||||||
<input type='checkbox' checked={value} onClick={() => {
|
<input type='checkbox' checked={value} onClick={() => {
|
||||||
const copy = new Map(projectFilters);
|
const copy = new Map(projectFilters);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ export interface SourceProps {
|
||||||
focusOnChange?: boolean;
|
focusOnChange?: boolean;
|
||||||
wrapLines?: boolean;
|
wrapLines?: boolean;
|
||||||
onChange?: (text: string) => void;
|
onChange?: (text: string) => void;
|
||||||
|
dataTestId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CodeMirrorWrapper: React.FC<SourceProps> = ({
|
export const CodeMirrorWrapper: React.FC<SourceProps> = ({
|
||||||
|
|
@ -59,6 +60,7 @@ export const CodeMirrorWrapper: React.FC<SourceProps> = ({
|
||||||
focusOnChange,
|
focusOnChange,
|
||||||
wrapLines,
|
wrapLines,
|
||||||
onChange,
|
onChange,
|
||||||
|
dataTestId,
|
||||||
}) => {
|
}) => {
|
||||||
const [measure, codemirrorElement] = useMeasure<HTMLDivElement>();
|
const [measure, codemirrorElement] = useMeasure<HTMLDivElement>();
|
||||||
const [modulePromise] = React.useState<Promise<CodeMirror>>(import('./codeMirrorModule').then(m => m.default));
|
const [modulePromise] = React.useState<Promise<CodeMirror>>(import('./codeMirrorModule').then(m => m.default));
|
||||||
|
|
@ -170,7 +172,7 @@ export const CodeMirrorWrapper: React.FC<SourceProps> = ({
|
||||||
};
|
};
|
||||||
}, [codemirror, text, highlight, revealLine, focusOnChange, onChange]);
|
}, [codemirror, text, highlight, revealLine, focusOnChange, onChange]);
|
||||||
|
|
||||||
return <div className='cm-wrapper' ref={codemirrorElement} onClick={onCodeMirrorClick}></div>;
|
return <div data-testid={dataTestId} className='cm-wrapper' ref={codemirrorElement} onClick={onCodeMirrorClick}></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
function onCodeMirrorClick(event: React.MouseEvent) {
|
function onCodeMirrorClick(event: React.MouseEvent) {
|
||||||
|
|
|
||||||
|
|
@ -399,3 +399,17 @@ it('check aria-hidden text', async ({ page, server }) => {
|
||||||
- paragraph: "hello"
|
- paragraph: "hello"
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore presentation and none roles', async ({ page, server }) => {
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await page.setContent(`
|
||||||
|
<ul>
|
||||||
|
<li role='presentation'>hello</li>
|
||||||
|
<li role='none'>world</li>
|
||||||
|
</ul>
|
||||||
|
`);
|
||||||
|
|
||||||
|
await checkAndMatchSnapshot(page.locator('body'), `
|
||||||
|
- list: "hello world"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,15 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": "1.49.0-alpha-2024-10-20"
|
"@playwright/test": "1.49.0-alpha-2024-10-25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@playwright/test": {
|
"node_modules/@playwright/test": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-lSagJ8KSD636T/TNfSJRh+vuBBssCL5xJgYmsvsF37cDMATTdVf2OVozVK91V9MAL7CxP4F5sQFVq/8rqu23WA==",
|
"integrity": "sha512-ds5PrtfECd21uiyVhKFOns0B2QdbQrxTYZSJQYCKcjomH3i6Fu0ZgPMe8Fh/6Nnx1vYUv9P6XWsHdkSHF2IZVA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.49.0-alpha-2024-10-20"
|
"playwright": "1.49.0-alpha-2024-10-25"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -36,11 +36,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright": {
|
"node_modules/playwright": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-lkZXCaLoVKaa3eVu8qJJiLym6SkjXD+ilE4XZJx3AIE0o4vqMEYVB8tjLzAcl4UZx8wVcCps/WcCvTWhOSIXRA==",
|
"integrity": "sha512-D8hV9H9MARk2ZyOO0/ivoRYXqBcsXnKsDzTLpiF5HIiweGIlxdiDcRQhelNAdfnxa01oAy+Qosu7Dsoy/RYWBw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.49.0-alpha-2024-10-20"
|
"playwright-core": "1.49.0-alpha-2024-10-25"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -53,9 +53,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright-core": {
|
"node_modules/playwright-core": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-TeQNA7vsGVrHaArr+giPyiWPAV27+wIcuMLrAJXzUB0leVA9bkXbNQ5lA5+G4OhqlmYAbMOpJMtN+TREDv4nXA==",
|
"integrity": "sha512-zHESnOKxzkEwUpi391rHnnBR0D+dkn6Oto5L9SqrBgOIhYUm7fnIywXk8FWq/uRDtlTH1RaGh0H1aAoPvVuW1w==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
},
|
},
|
||||||
|
|
@ -66,11 +66,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": {
|
"@playwright/test": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-lSagJ8KSD636T/TNfSJRh+vuBBssCL5xJgYmsvsF37cDMATTdVf2OVozVK91V9MAL7CxP4F5sQFVq/8rqu23WA==",
|
"integrity": "sha512-ds5PrtfECd21uiyVhKFOns0B2QdbQrxTYZSJQYCKcjomH3i6Fu0ZgPMe8Fh/6Nnx1vYUv9P6XWsHdkSHF2IZVA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"playwright": "1.49.0-alpha-2024-10-20"
|
"playwright": "1.49.0-alpha-2024-10-25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
|
|
@ -80,18 +80,18 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-lkZXCaLoVKaa3eVu8qJJiLym6SkjXD+ilE4XZJx3AIE0o4vqMEYVB8tjLzAcl4UZx8wVcCps/WcCvTWhOSIXRA==",
|
"integrity": "sha512-D8hV9H9MARk2ZyOO0/ivoRYXqBcsXnKsDzTLpiF5HIiweGIlxdiDcRQhelNAdfnxa01oAy+Qosu7Dsoy/RYWBw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "2.3.2",
|
"fsevents": "2.3.2",
|
||||||
"playwright-core": "1.49.0-alpha-2024-10-20"
|
"playwright-core": "1.49.0-alpha-2024-10-25"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"playwright-core": {
|
"playwright-core": {
|
||||||
"version": "1.49.0-alpha-2024-10-20",
|
"version": "1.49.0-alpha-2024-10-25",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-20.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-25.tgz",
|
||||||
"integrity": "sha512-TeQNA7vsGVrHaArr+giPyiWPAV27+wIcuMLrAJXzUB0leVA9bkXbNQ5lA5+G4OhqlmYAbMOpJMtN+TREDv4nXA=="
|
"integrity": "sha512-zHESnOKxzkEwUpi391rHnnBR0D+dkn6Oto5L9SqrBgOIhYUm7fnIywXk8FWq/uRDtlTH1RaGh0H1aAoPvVuW1w=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/test": "1.49.0-alpha-2024-10-20"
|
"@playwright/test": "1.49.0-alpha-2024-10-25"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ test('should run visible', async ({ runUITest }) => {
|
||||||
- button "Run"
|
- button "Run"
|
||||||
- button "Show source"
|
- button "Show source"
|
||||||
- button "Watch"
|
- button "Watch"
|
||||||
- treeitem "[icon-error] suite"
|
- treeitem "[icon-error] suite" [expanded=false]
|
||||||
- treeitem "[icon-error] b.test.ts" [expanded]:
|
- treeitem "[icon-error] b.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-check\] passes/}
|
- treeitem ${/\[icon-check\] passes/}
|
||||||
|
|
@ -230,7 +230,7 @@ test('should run by project', async ({ runUITest }) => {
|
||||||
- button "Run"
|
- button "Run"
|
||||||
- button "Show source"
|
- button "Show source"
|
||||||
- button "Watch"
|
- button "Watch"
|
||||||
- treeitem "[icon-error] suite"
|
- treeitem "[icon-error] suite" [expanded=false]
|
||||||
- treeitem "[icon-error] b.test.ts" [expanded]:
|
- treeitem "[icon-error] b.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-check\] passes/}
|
- treeitem ${/\[icon-check\] passes/}
|
||||||
|
|
@ -263,23 +263,20 @@ test('should run by project', async ({ runUITest }) => {
|
||||||
- tree:
|
- tree:
|
||||||
- treeitem "[icon-error] a.test.ts" [expanded]:
|
- treeitem "[icon-error] a.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-circle-outline\] passes/}
|
- treeitem ${/\[icon-circle-outline\] passes/} [expanded=false]
|
||||||
- treeitem ${/\[icon-error\] fails/}:
|
- treeitem ${/\[icon-error\] fails/}:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-error\] foo/} [selected]:
|
- treeitem ${/\[icon-error\] foo/} [selected]
|
||||||
- button "Run"
|
|
||||||
- button "Show source"
|
|
||||||
- button "Watch"
|
|
||||||
- treeitem "[icon-circle-outline] bar"
|
- treeitem "[icon-circle-outline] bar"
|
||||||
- treeitem "[icon-error] suite"
|
- treeitem "[icon-error] suite" [expanded=false]
|
||||||
- treeitem "[icon-error] b.test.ts" [expanded]:
|
- treeitem "[icon-error] b.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-circle-outline\] passes/}
|
- treeitem ${/\[icon-circle-outline\] passes/} [expanded=false]
|
||||||
- treeitem ${/\[icon-error\] fails/}
|
- treeitem ${/\[icon-error\] fails/} [expanded=false]
|
||||||
- treeitem "[icon-circle-outline] c.test.ts" [expanded]:
|
- treeitem "[icon-circle-outline] c.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-circle-outline\] passes/}
|
- treeitem ${/\[icon-circle-outline\] passes/} [expanded=false]
|
||||||
- treeitem ${/\[icon-circle-outline\] skipped/}
|
- treeitem ${/\[icon-circle-outline\] skipped/} [expanded=false]
|
||||||
`);
|
`);
|
||||||
|
|
||||||
await page.getByText('Status:').click();
|
await page.getByText('Status:').click();
|
||||||
|
|
@ -347,12 +344,12 @@ test('should run by project', async ({ runUITest }) => {
|
||||||
- treeitem ${/\[icon-error\] suite/}
|
- treeitem ${/\[icon-error\] suite/}
|
||||||
- treeitem "[icon-error] b.test.ts" [expanded]:
|
- treeitem "[icon-error] b.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-check\] passes/}
|
- treeitem ${/\[icon-check\] passes/} [expanded=false]
|
||||||
- treeitem ${/\[icon-error\] fails/}
|
- treeitem ${/\[icon-error\] fails/} [expanded=false]
|
||||||
- treeitem "[icon-check] c.test.ts" [expanded]:
|
- treeitem "[icon-check] c.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-check\] passes/}
|
- treeitem ${/\[icon-check\] passes/} [expanded=false]
|
||||||
- treeitem ${/\[icon-circle-slash\] skipped/}
|
- treeitem ${/\[icon-circle-slash\] skipped/} [expanded=false]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -445,8 +442,8 @@ test('should run folder', async ({ runUITest }) => {
|
||||||
- tree:
|
- tree:
|
||||||
- treeitem "[icon-check] folder-b" [expanded] [selected]:
|
- treeitem "[icon-check] folder-b" [expanded] [selected]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem "[icon-check] folder-c"
|
- treeitem "[icon-check] folder-c" [expanded=false]
|
||||||
- treeitem "[icon-check] in-b.test.ts"
|
- treeitem "[icon-check] in-b.test.ts" [expanded=false]
|
||||||
- treeitem "[icon-circle-outline] in-a.test.ts" [expanded]:
|
- treeitem "[icon-circle-outline] in-a.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem "[icon-circle-outline] passes"
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
|
@ -483,7 +480,7 @@ test('should show time', async ({ runUITest }) => {
|
||||||
- button "Run"
|
- button "Run"
|
||||||
- button "Show source"
|
- button "Show source"
|
||||||
- button "Watch"
|
- button "Watch"
|
||||||
- treeitem "[icon-error] suite"
|
- treeitem "[icon-error] suite" [expanded=false]
|
||||||
- treeitem "[icon-error] b.test.ts" [expanded]:
|
- treeitem "[icon-error] b.test.ts" [expanded]:
|
||||||
- group:
|
- group:
|
||||||
- treeitem ${/\[icon-check\] passes \d+m?s/}
|
- treeitem ${/\[icon-check\] passes \d+m?s/}
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,16 @@ test('should run setup and teardown projects (1)', async ({ runUITest }) => {
|
||||||
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false);
|
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false);
|
||||||
await page.getByRole('checkbox', { name: 'test' }).setChecked(false);
|
await page.getByRole('checkbox', { name: 'test' }).setChecked(false);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('project-filters')).toMatchAriaSnapshot(`
|
||||||
|
- list:
|
||||||
|
- listitem:
|
||||||
|
- checkbox "teardown"
|
||||||
|
- listitem:
|
||||||
|
- checkbox "setup"
|
||||||
|
- listitem:
|
||||||
|
- checkbox "test"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Run all').click();
|
await page.getByTitle('Run all').click();
|
||||||
|
|
||||||
await expect.poll(dumpTestTree(page)).toBe(`
|
await expect.poll(dumpTestTree(page)).toBe(`
|
||||||
|
|
@ -155,10 +165,27 @@ test('should run setup and teardown projects (1)', async ({ runUITest }) => {
|
||||||
✅ test
|
✅ test
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-check] setup.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] setup/}
|
||||||
|
- treeitem "[icon-check] teardown.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] teardown/}
|
||||||
|
- treeitem "[icon-check] test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] test/}
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Toggle output').click();
|
await page.getByTitle('Toggle output').click();
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-setup`);
|
await expect(page.getByTestId('output')).toContainText(`from-setup`);
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-teardown`);
|
await expect(page.getByTestId('output')).toContainText(`from-teardown`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('output')).toMatchAriaSnapshot(`
|
||||||
|
- textbox "Terminal input"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should run setup and teardown projects (2)', async ({ runUITest }) => {
|
test('should run setup and teardown projects (2)', async ({ runUITest }) => {
|
||||||
|
|
@ -168,6 +195,16 @@ test('should run setup and teardown projects (2)', async ({ runUITest }) => {
|
||||||
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true);
|
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true);
|
||||||
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('project-filters')).toMatchAriaSnapshot(`
|
||||||
|
- list:
|
||||||
|
- listitem:
|
||||||
|
- checkbox "teardown" [checked]
|
||||||
|
- listitem:
|
||||||
|
- checkbox "setup"
|
||||||
|
- listitem:
|
||||||
|
- checkbox "test" [checked]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Run all').click();
|
await page.getByTitle('Run all').click();
|
||||||
|
|
||||||
await expect.poll(dumpTestTree(page)).toBe(`
|
await expect.poll(dumpTestTree(page)).toBe(`
|
||||||
|
|
@ -177,10 +214,24 @@ test('should run setup and teardown projects (2)', async ({ runUITest }) => {
|
||||||
✅ test
|
✅ test
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-check] teardown.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] teardown/}
|
||||||
|
- treeitem "[icon-check] test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] test/}
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Toggle output').click();
|
await page.getByTitle('Toggle output').click();
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-teardown`);
|
await expect(page.getByTestId('output')).toContainText(`from-teardown`);
|
||||||
await expect(page.getByTestId('output')).not.toContainText(`from-setup`);
|
await expect(page.getByTestId('output')).not.toContainText(`from-setup`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('output')).toMatchAriaSnapshot(`
|
||||||
|
- textbox "Terminal input"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should run setup and teardown projects (3)', async ({ runUITest }) => {
|
test('should run setup and teardown projects (3)', async ({ runUITest }) => {
|
||||||
|
|
@ -190,6 +241,16 @@ test('should run setup and teardown projects (3)', async ({ runUITest }) => {
|
||||||
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false);
|
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false);
|
||||||
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('project-filters')).toMatchAriaSnapshot(`
|
||||||
|
- list:
|
||||||
|
- listitem:
|
||||||
|
- checkbox "teardown"
|
||||||
|
- listitem:
|
||||||
|
- checkbox "setup"
|
||||||
|
- listitem:
|
||||||
|
- checkbox "test" [checked]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Run all').click();
|
await page.getByTitle('Run all').click();
|
||||||
|
|
||||||
await expect.poll(dumpTestTree(page)).toBe(`
|
await expect.poll(dumpTestTree(page)).toBe(`
|
||||||
|
|
@ -197,10 +258,21 @@ test('should run setup and teardown projects (3)', async ({ runUITest }) => {
|
||||||
✅ test
|
✅ test
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-check] test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] test/}
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Toggle output').click();
|
await page.getByTitle('Toggle output').click();
|
||||||
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
await expect(page.getByTestId('output')).toContainText(`from-test`);
|
||||||
await expect(page.getByTestId('output')).not.toContainText(`from-setup`);
|
await expect(page.getByTestId('output')).not.toContainText(`from-setup`);
|
||||||
await expect(page.getByTestId('output')).not.toContainText(`from-teardown`);
|
await expect(page.getByTestId('output')).not.toContainText(`from-teardown`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('output')).toMatchAriaSnapshot(`
|
||||||
|
- textbox "Terminal input"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should run part of the setup only', async ({ runUITest }) => {
|
test('should run part of the setup only', async ({ runUITest }) => {
|
||||||
|
|
@ -210,6 +282,16 @@ test('should run part of the setup only', async ({ runUITest }) => {
|
||||||
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true);
|
await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true);
|
||||||
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
await page.getByRole('checkbox', { name: 'test' }).setChecked(true);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('project-filters')).toMatchAriaSnapshot(`
|
||||||
|
- list:
|
||||||
|
- listitem:
|
||||||
|
- checkbox "teardown" [checked]
|
||||||
|
- listitem:
|
||||||
|
- checkbox "setup" [checked]
|
||||||
|
- listitem:
|
||||||
|
- checkbox "test" [checked]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByText('setup.ts').hover();
|
await page.getByText('setup.ts').hover();
|
||||||
await page.getByRole('treeitem', { name: 'setup.ts' }).getByRole('button', { name: 'Run' }).click();
|
await page.getByRole('treeitem', { name: 'setup.ts' }).getByRole('button', { name: 'Run' }).click();
|
||||||
|
|
||||||
|
|
@ -221,6 +303,22 @@ test('should run part of the setup only', async ({ runUITest }) => {
|
||||||
▼ ◯ test.ts
|
▼ ◯ test.ts
|
||||||
◯ test
|
◯ test
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-check] setup.ts" [expanded] [selected]:
|
||||||
|
- button "Run"
|
||||||
|
- button "Show source"
|
||||||
|
- button "Watch"
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] setup/}
|
||||||
|
- treeitem "[icon-check] teardown.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem ${/\[icon-check\] teardown/}
|
||||||
|
- treeitem "[icon-circle-outline] test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] test"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const useWeb of [true, false]) {
|
for (const useWeb of [true, false]) {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ test('should run tests', async ({ runUITest }) => {
|
||||||
◯ test 2
|
◯ test 2
|
||||||
✅ test 3
|
✅ test 3
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] test 0"
|
||||||
|
- treeitem "[icon-circle-outline] test 1"
|
||||||
|
- treeitem "[icon-circle-outline] test 2"
|
||||||
|
- treeitem ${/\[icon-check\] test 3/}
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should stop tests', async ({ runUITest }) => {
|
test('should stop tests', async ({ runUITest }) => {
|
||||||
|
|
@ -66,6 +76,16 @@ test('should stop tests', async ({ runUITest }) => {
|
||||||
🕦 test 3
|
🕦 test 3
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-loading] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-slash] test 0"
|
||||||
|
- treeitem ${/\[icon-check\] test 1/}
|
||||||
|
- treeitem ${/\[icon-loading\] test 2/}
|
||||||
|
- treeitem ${/\[icon-clock\] test 3/}
|
||||||
|
`);
|
||||||
|
|
||||||
await expect(page.getByTitle('Run all')).toBeDisabled();
|
await expect(page.getByTitle('Run all')).toBeDisabled();
|
||||||
await expect(page.getByTitle('Stop')).toBeEnabled();
|
await expect(page.getByTitle('Stop')).toBeEnabled();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,17 @@ test('should show selected test in sources', async ({ runUITest }) => {
|
||||||
◯ third
|
◯ third
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] first"
|
||||||
|
- treeitem "[icon-circle-outline] second"
|
||||||
|
- treeitem "[icon-circle-outline] b.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] third"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTestId('test-tree').getByText('first').click();
|
await page.getByTestId('test-tree').getByText('first').click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('source-code').locator('.source-tab-file-name')
|
page.getByTestId('source-code').locator('.source-tab-file-name')
|
||||||
|
|
@ -48,6 +59,13 @@ test('should show selected test in sources', async ({ runUITest }) => {
|
||||||
page.locator('.CodeMirror .source-line-running'),
|
page.locator('.CodeMirror .source-line-running'),
|
||||||
).toHaveText(`3 test('first', () => {});`);
|
).toHaveText(`3 test('first', () => {});`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('source-code-mirror')).toMatchAriaSnapshot(`
|
||||||
|
- text: |
|
||||||
|
import { test } from '@playwright/test';
|
||||||
|
test('first', () => {});
|
||||||
|
test('second', () => {});
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTestId('test-tree').getByText('second').click();
|
await page.getByTestId('test-tree').getByText('second').click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('source-code').locator('.source-tab-file-name')
|
page.getByTestId('source-code').locator('.source-tab-file-name')
|
||||||
|
|
@ -85,6 +103,14 @@ test('should show top-level errors in file', async ({ runUITest }) => {
|
||||||
◯ third
|
◯ third
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts"
|
||||||
|
- treeitem "[icon-circle-outline] b.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] third"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTestId('test-tree').getByText('a.test.ts').click();
|
await page.getByTestId('test-tree').getByText('a.test.ts').click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('source-code').locator('.source-tab-file-name')
|
page.getByTestId('source-code').locator('.source-tab-file-name')
|
||||||
|
|
@ -113,6 +139,11 @@ test('should show syntax errors in file', async ({ runUITest }) => {
|
||||||
◯ a.test.ts
|
◯ a.test.ts
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTestId('test-tree').getByText('a.test.ts').click();
|
await page.getByTestId('test-tree').getByText('a.test.ts').click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('source-code').locator('.source-tab-file-name')
|
page.getByTestId('source-code').locator('.source-tab-file-name')
|
||||||
|
|
@ -155,4 +186,12 @@ test('should load error (dupe tests) indicator on sources', async ({ runUITest }
|
||||||
' ',
|
' ',
|
||||||
/Error: duplicate test title "first", first declared in a.test.ts:3/
|
/Error: duplicate test title "first", first declared in a.test.ts:3/
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('source-code-mirror')).toMatchAriaSnapshot(`
|
||||||
|
- text: |
|
||||||
|
import { test } from '@playwright/test';
|
||||||
|
test('first', () => {});
|
||||||
|
test('first', () => {});
|
||||||
|
Error: duplicate test title "first", first declared in a.test.ts:3
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,19 @@ test('should list tests', async ({ runUITest }) => {
|
||||||
◯ passes
|
◯ passes
|
||||||
◯ fails
|
◯ fails
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded=false]
|
||||||
|
- treeitem "[icon-circle-outline] b.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should list all tests from projects with clashing names', async ({ runUITest }) => {
|
test('should list all tests from projects with clashing names', async ({ runUITest }) => {
|
||||||
|
|
@ -100,6 +113,22 @@ test('should list all tests from projects with clashing names', async ({ runUITe
|
||||||
◯ one
|
◯ one
|
||||||
◯ two
|
◯ two
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] bar" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] b.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] three"
|
||||||
|
- treeitem "[icon-circle-outline] four"
|
||||||
|
- treeitem "[icon-circle-outline] foo" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] one"
|
||||||
|
- treeitem "[icon-circle-outline] two"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should traverse up/down', async ({ runUITest }) => {
|
test('should traverse up/down', async ({ runUITest }) => {
|
||||||
|
|
@ -111,6 +140,14 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||||
◯ fails
|
◯ fails
|
||||||
► ◯ suite
|
► ◯ suite
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded=false]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.keyboard.press('ArrowDown');
|
await page.keyboard.press('ArrowDown');
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
|
|
@ -119,6 +156,15 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||||
◯ fails
|
◯ fails
|
||||||
► ◯ suite
|
► ◯ suite
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes" [selected]
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded=false]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.keyboard.press('ArrowDown');
|
await page.keyboard.press('ArrowDown');
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
▼ ◯ a.test.ts
|
▼ ◯ a.test.ts
|
||||||
|
|
@ -126,6 +172,14 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||||
◯ fails <=
|
◯ fails <=
|
||||||
► ◯ suite
|
► ◯ suite
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails" [selected]
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded=false]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.keyboard.press('ArrowUp');
|
await page.keyboard.press('ArrowUp');
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
|
|
@ -134,6 +188,14 @@ test('should traverse up/down', async ({ runUITest }) => {
|
||||||
◯ fails
|
◯ fails
|
||||||
► ◯ suite
|
► ◯ suite
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes" [selected]
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded=false]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should expand / collapse groups', async ({ runUITest }) => {
|
test('should expand / collapse groups', async ({ runUITest }) => {
|
||||||
|
|
@ -149,6 +211,17 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||||
◯ inner passes
|
◯ inner passes
|
||||||
◯ inner fails
|
◯ inner fails
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] inner passes"
|
||||||
|
- treeitem "[icon-circle-outline] inner fails"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.keyboard.press('ArrowLeft');
|
await page.keyboard.press('ArrowLeft');
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
|
|
@ -157,6 +230,14 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||||
◯ fails
|
◯ fails
|
||||||
► ◯ suite <=
|
► ◯ suite <=
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [selected] [expanded=false]
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTestId('test-tree').getByText('passes').first().click();
|
await page.getByTestId('test-tree').getByText('passes').first().click();
|
||||||
await page.keyboard.press('ArrowLeft');
|
await page.keyboard.press('ArrowLeft');
|
||||||
|
|
@ -165,11 +246,22 @@ test('should expand / collapse groups', async ({ runUITest }) => {
|
||||||
◯ passes
|
◯ passes
|
||||||
◯ fails
|
◯ fails
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.keyboard.press('ArrowLeft');
|
await page.keyboard.press('ArrowLeft');
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
► ◯ a.test.ts <=
|
► ◯ a.test.ts <=
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [selected] [expanded=false]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should merge folder trees', async ({ runUITest }) => {
|
test('should merge folder trees', async ({ runUITest }) => {
|
||||||
|
|
@ -195,6 +287,16 @@ test('should merge folder trees', async ({ runUITest }) => {
|
||||||
▼ ◯ in-a.test.ts
|
▼ ◯ in-a.test.ts
|
||||||
◯ passes
|
◯ passes
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] b" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] c" [expanded=false]
|
||||||
|
- treeitem "[icon-circle-outline] in-b.test.ts" [expanded=false]
|
||||||
|
- treeitem "[icon-circle-outline] in-a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should list parametrized tests', async ({ runUITest }) => {
|
test('should list parametrized tests', async ({ runUITest }) => {
|
||||||
|
|
@ -224,6 +326,18 @@ test('should list parametrized tests', async ({ runUITest }) => {
|
||||||
◯ test DE
|
◯ test DE
|
||||||
◯ test LT
|
◯ test LT
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] cookies" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] <anonymous>" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] test FR"
|
||||||
|
- treeitem "[icon-circle-outline] test DE"
|
||||||
|
- treeitem "[icon-circle-outline] test LT"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should update parametrized tests', async ({ runUITest, writeFiles }) => {
|
test('should update parametrized tests', async ({ runUITest, writeFiles }) => {
|
||||||
|
|
@ -253,6 +367,18 @@ test('should update parametrized tests', async ({ runUITest, writeFiles }) => {
|
||||||
◯ test DE
|
◯ test DE
|
||||||
◯ test LT
|
◯ test LT
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] cookies" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] <anonymous>" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] test FR"
|
||||||
|
- treeitem "[icon-circle-outline] test DE"
|
||||||
|
- treeitem "[icon-circle-outline] test LT"
|
||||||
|
`);
|
||||||
|
|
||||||
await writeFiles({
|
await writeFiles({
|
||||||
'a.test.ts': `
|
'a.test.ts': `
|
||||||
|
|
@ -275,6 +401,17 @@ test('should update parametrized tests', async ({ runUITest, writeFiles }) => {
|
||||||
◯ test FR
|
◯ test FR
|
||||||
◯ test LT
|
◯ test LT
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] cookies" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] <anonymous>" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] test FR"
|
||||||
|
- treeitem "[icon-circle-outline] test LT"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should collapse all', async ({ runUITest }) => {
|
test('should collapse all', async ({ runUITest }) => {
|
||||||
|
|
@ -290,11 +427,26 @@ test('should collapse all', async ({ runUITest }) => {
|
||||||
◯ inner passes
|
◯ inner passes
|
||||||
◯ inner fails
|
◯ inner fails
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] inner passes"
|
||||||
|
- treeitem "[icon-circle-outline] inner fails"
|
||||||
|
`);
|
||||||
|
|
||||||
await page.getByTitle('Collapse all').click();
|
await page.getByTitle('Collapse all').click();
|
||||||
await expect.poll(dumpTestTree(page)).toContain(`
|
await expect.poll(dumpTestTree(page)).toContain(`
|
||||||
► ◯ a.test.ts
|
► ◯ a.test.ts
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded=false]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should expand all', {
|
test('should expand all', {
|
||||||
|
|
@ -321,6 +473,21 @@ test('should expand all', {
|
||||||
◯ passes
|
◯ passes
|
||||||
◯ fails
|
◯ fails
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
- treeitem "[icon-circle-outline] suite" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] inner passes"
|
||||||
|
- treeitem "[icon-circle-outline] inner fails"
|
||||||
|
- treeitem "[icon-circle-outline] b.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] passes"
|
||||||
|
- treeitem "[icon-circle-outline] fails"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should resolve title conflicts', async ({ runUITest }) => {
|
test('should resolve title conflicts', async ({ runUITest }) => {
|
||||||
|
|
@ -349,4 +516,14 @@ test('should resolve title conflicts', async ({ runUITest }) => {
|
||||||
◯ bar
|
◯ bar
|
||||||
◯ bar 2
|
◯ bar 2
|
||||||
`);
|
`);
|
||||||
|
await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(`
|
||||||
|
- tree:
|
||||||
|
- treeitem "[icon-circle-outline] a.test.ts" [expanded]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] foo"
|
||||||
|
- treeitem "[icon-circle-outline] foo" [expanded] [selected]:
|
||||||
|
- group:
|
||||||
|
- treeitem "[icon-circle-outline] bar"
|
||||||
|
- treeitem "[icon-circle-outline] bar 2"
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { test, expect } from './playwright-test-fixtures';
|
import { test, expect } from './playwright-test-fixtures';
|
||||||
|
|
||||||
|
test.describe.configure({ mode: 'parallel' });
|
||||||
|
|
||||||
test('should update snapshot with the update-snapshots flag', async ({ runInlineTest }, testInfo) => {
|
test('should update snapshot with the update-snapshots flag', async ({ runInlineTest }, testInfo) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'a.spec.ts': `
|
'a.spec.ts': `
|
||||||
|
|
@ -46,3 +48,32 @@ test('should update snapshot with the update-snapshots flag', async ({ runInline
|
||||||
|
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should update missing snapshots', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'a.spec.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', async ({ page }) => {
|
||||||
|
await page.setContent(\`<h1>hello</h1>\`);
|
||||||
|
await expect(page.locator('body')).toMatchAriaSnapshot(\`\`);
|
||||||
|
});
|
||||||
|
`
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
const patchPath = testInfo.outputPath('test-results/rebaselines.patch');
|
||||||
|
const data = fs.readFileSync(patchPath, 'utf-8');
|
||||||
|
expect(data).toBe(`--- a/a.spec.ts
|
||||||
|
+++ b/a.spec.ts
|
||||||
|
@@ -2,6 +2,8 @@
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', async ({ page }) => {
|
||||||
|
await page.setContent(\`<h1>hello</h1>\`);
|
||||||
|
- await expect(page.locator('body')).toMatchAriaSnapshot(\`\`);
|
||||||
|
+ await expect(page.locator('body')).toMatchAriaSnapshot(\`
|
||||||
|
+ - heading "hello" [level=1]
|
||||||
|
+ \`);
|
||||||
|
});
|
||||||
|
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue