/** * Copyright (c) Microsoft Corporation. All rights reserved. * * 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 { stripAnsi } from '../config/utils'; import { test, expect } from './pageTest'; test('should match page', async ({ page }) => { await page.setContent(`

title

`); await expect(page).toMatchAriaSnapshot(` - heading "title" `); }); test('should match page complex', async ({ page }) => { await page.setContent(`

Microsoft

Open source projects and samples from Microsoft
`); await expect(page).toMatchAriaSnapshot(` - heading "Microsoft" - text: Open source projects and samples from Microsoft - list: - listitem: - link "Playwright" `); }); test('should match page with not', async ({ page }) => { await page.setContent(`

title

`); await expect(page).not.toMatchAriaSnapshot(` - heading "wrong" `); }); test('should fail page with timeout', async ({ page }) => { await page.setContent(`

title

`); const e = await expect(page).toMatchAriaSnapshot(` - heading "wrong" `, { timeout: 2000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 2000ms'); expect(stripAnsi(e.message)).not.toContain('Locator'); }); test('should match', async ({ page }) => { await page.setContent(`

title

`); await expect(page).toMatchAriaSnapshot(` - heading "title" `); }); test('should match in list', async ({ page }) => { await page.setContent(`

title

title 2

`); await expect(page).toMatchAriaSnapshot(` - heading "title" `); }); test('should match list with accessible name', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - list "my list": - listitem: "one" - listitem: "two" `); }); test('should match deep item', async ({ page }) => { await page.setContent(`

title

title 2

`); await expect(page).toMatchAriaSnapshot(` - heading "title" `); }); test('should match complex', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - list: - listitem: - link "link" `); }); test('should match regex', async ({ page }) => { { await page.setContent(`

Issues 12

`); await expect(page).toMatchAriaSnapshot(` - heading ${/Issues \d+/} `); } { await page.setContent(`

Issues 1/2

`); await expect(page).toMatchAriaSnapshot(` - heading ${/Issues 1[/]2/} `); } { await page.setContent(`

Issues 1[

`); await expect(page).toMatchAriaSnapshot(` - heading ${/Issues 1\[/} `); } { await page.setContent(`

Issues 1]]2

`); await expect(page).toMatchAriaSnapshot(` - heading ${/Issues 1[\]]]2/} `); } }); test('should allow text nodes', async ({ page }) => { await page.setContent(`

Microsoft

Open source projects and samples from Microsoft
`); await expect(page).toMatchAriaSnapshot(` - heading "Microsoft" - text: "Open source projects and samples from Microsoft" `); }); test('details visibility', async ({ page }) => { await page.setContent(`
Summary
Details
`); await expect(page).toMatchAriaSnapshot(` - group: "Summary" `); }); test('checked attribute', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - checkbox `); await expect(page).toMatchAriaSnapshot(` - checkbox [checked] `); await expect(page).toMatchAriaSnapshot(` - checkbox [checked=true] `); { const e = await expect(page).toMatchAriaSnapshot(` - checkbox [checked=false] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - checkbox [checked=mixed] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - checkbox [checked=5] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a boolean or "mixed"'); } }); test('disabled attribute', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button `); await expect(page).toMatchAriaSnapshot(` - button [disabled] `); await expect(page).toMatchAriaSnapshot(` - button [disabled=true] `); { const e = await expect(page).toMatchAriaSnapshot(` - button [disabled=false] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - button [disabled=invalid] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); } }); test('expanded attribute', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button `); await expect(page).toMatchAriaSnapshot(` - button [expanded] `); await expect(page).toMatchAriaSnapshot(` - button [expanded=true] `); { const e = await expect(page).toMatchAriaSnapshot(` - button [expanded=false] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - button [expanded=invalid] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); } }); test('level attribute', async ({ page }) => { await page.setContent(`

Section Title

`); await expect(page).toMatchAriaSnapshot(` - heading `); await expect(page).toMatchAriaSnapshot(` - heading [level=2] `); { const e = await expect(page).toMatchAriaSnapshot(` - heading [level=3] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - heading [level=two] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a number'); } }); test('pressed attribute', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button `); await expect(page).toMatchAriaSnapshot(` - button [pressed] `); await expect(page).toMatchAriaSnapshot(` - button [pressed=true] `); { const e = await expect(page).toMatchAriaSnapshot(` - button [pressed=false] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } // Test for 'mixed' state await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button [pressed=mixed] `); { const e = await expect(page).toMatchAriaSnapshot(` - button [pressed=true] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('Timeout: 1000ms'); } { const e = await expect(page).toMatchAriaSnapshot(` - button [pressed=5] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a boolean or "mixed"'); } }); test('selected attribute', async ({ page }) => { await page.setContent(`
Row
Row 2
`); await expect(page).toMatchAriaSnapshot(` - row - row `); await expect(page).toMatchAriaSnapshot(` - row [selected] - row `); await expect(page).toMatchAriaSnapshot(` - row [selected=true] - row [selected=false] `); await expect(page.locator('table')).toMatchAriaSnapshot(` - table: - rowgroup: - row [selected=true] - row [selected=false] `); { const e = await expect(page).toMatchAriaSnapshot(` - row [selected=false] - row [selected=false] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(`expect(page).toMatchAriaSnapshot(expected) failed Timeout: 1000ms - Expected - 2 + Received + 6 - - row [selected=false] - - row [selected=false] + - table: + - rowgroup: + - row "Row" [selected]: + - cell "Row" + - row \"Row 2\": + - cell \"Row 2\" Call log: `); } { const e = await expect(page).toMatchAriaSnapshot(` - row [selected=invalid] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); } }); test('integration test', async ({ page }) => { await page.setContent(`

Microsoft

Open source projects and samples from Microsoft
`); await expect(page).toMatchAriaSnapshot(` - heading "Microsoft" - text: Open source projects and samples from Microsoft - list: - listitem: - group: Verified - listitem: - link "Sponsor" `); }); test('integration test 2', async ({ page }) => { await page.setContent(`

todos

`); await expect(page).toMatchAriaSnapshot(` - heading "todos" - textbox "What needs to be done?" `); }); test('expected formatter', async ({ page }) => { await page.setContent(`

todos

`); const error = await expect(page).toMatchAriaSnapshot(` - heading "todos" - textbox "Wrong text" `, { timeout: 1 }).catch(e => e); // Note that error message should not contain any regular expressions, // unlike the baseline generated by --update-snapshots. expect(stripAnsi(error.message)).toContain(`expect(page).toMatchAriaSnapshot(expected) failed Timeout: 1ms - Expected - 2 + Received + 4 - - heading "todos" - - textbox "Wrong text" + - banner: + - heading "todos" [level=1] + - textbox "What needs to be done?" + - button "Time 15:30" Call log: `); }); test('should unpack escaped names', async ({ page }) => { { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - 'button "Click: me"' `); await expect(page).toMatchAriaSnapshot(` - 'button /Click: me/' `); } { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button "Click / me" `); await expect(page).toMatchAriaSnapshot(` - button /Click \\/ me/ `); await expect(page).toMatchAriaSnapshot(` - 'button /Click \\/ me/' `); } { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button "Click \\\" me" `); await expect(page).toMatchAriaSnapshot(` - button /Click \" me/ `); await expect(page).toMatchAriaSnapshot(` - button /Click \\\" me/ `); } { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button "Click \\\\ me" `); await expect(page).toMatchAriaSnapshot(` - button /Click \\\\ me/ `); await expect(page).toMatchAriaSnapshot(` - 'button /Click \\\\ me/' `); } { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - 'button "Click '' me"' `); } { await page.setContent(`

heading "name" [level=1]

`); await expect(page).toMatchAriaSnapshot(` - heading "heading \\"name\\" [level=1]" [level=1] `); } { await page.setContent(`

heading \\" [level=2]

`); await expect(page).toMatchAriaSnapshot(` - | heading "heading \\\\\\" [level=2]" [ level = 1 ] `); } }); test('should report error in YAML', async ({ page }) => { await page.setContent(`

title

`); { const error = await expect(page).toMatchAriaSnapshot(` heading "title" `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Aria snapshot must be a YAML sequence, elements starting with " -"`); } { const error = await expect(page).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(`

title

`); { const error = await expect(page).toMatchAriaSnapshot(` - heading "title `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unterminated string: heading "title ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading /title `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unterminated regex: heading /title ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading [level=a] `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "level" attribute must be a number: heading [level=a] ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading [expanded=FALSE] `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "expanded" attribute must be a boolean: heading [expanded=FALSE] ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading [checked=foo] `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "checked" attribute must be a boolean or "mixed": heading [checked=foo] ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading [level=] `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Value of "level" attribute must be a number: heading [level=] ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading [bogus] `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unsupported attribute [bogus]: heading [bogus] ^ `); } { const error = await expect(page).toMatchAriaSnapshot(` - heading invalid `).catch(e => e); expect.soft(error.message).toBe(`expect.toMatchAriaSnapshot: Unexpected input: heading invalid ^ `); } }); test('call log should contain actual snapshot', async ({ page }) => { await page.setContent(`

todos

`); const error = await expect(page).toMatchAriaSnapshot(` - heading "wrong" `, { timeout: 3000 }).catch(e => e); expect(stripAnsi(error.message)).toContain(`unexpected value "- heading "todos" [level=1]"`); }); test('should parse attributes', async ({ page }) => { { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - button [pressed=mixed ] `); } { await page.setContent(`

hello world

`); await expect(page.locator('body')).not.toMatchAriaSnapshot(` - heading [level = -3 ] `); } }); test('should not unshift actual template text', async ({ page }) => { await page.setContent(`

title

title 2

`); const error = await expect(page).toMatchAriaSnapshot(` - heading "title" [level=1] - heading "title 2" [level=1] `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(error.message)).toContain(` - heading "title" [level=1] - heading "title 2" [level=1]`); }); test('should not match what is not matched', async ({ page }) => { await page.setContent(`

Text

`); const error = await expect(page).toMatchAriaSnapshot(` - paragraph: - button "bogus" `).catch(e => e); expect(stripAnsi(error.message)).toContain(` - - paragraph: - - button "bogus" + - paragraph: Text`); }); test('should match url', async ({ page }) => { await page.setContent(` Link `); await expect(page).toMatchAriaSnapshot(` - link: - /url: /.*example.com/ `); }); test('should detect unexpected children: equal', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - list: - listitem: "One" - listitem: "Three" `); const e = await expect(page).toMatchAriaSnapshot(` - list: - /children: equal - listitem: "One" - listitem: "Three" `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('+ - listitem: Two'); }); test('should detect unexpected children: deep-equal', async ({ page }) => { await page.setContent(` `); await expect(page).toMatchAriaSnapshot(` - list: - listitem: - list: - listitem: 1.1 `); await expect(page).toMatchAriaSnapshot(` - list: - /children: equal - listitem: - list: - listitem: 1.1 `); const e = await expect(page).toMatchAriaSnapshot(` - list: - /children: deep-equal - listitem: - list: - listitem: 1.1 `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('+ - listitem: \"1.2\"'); }); test('should allow restoring contain mode inside deep-equal', async ({ page }) => { await page.setContent(` `); const e = await expect(page).toMatchAriaSnapshot(` - list: - /children: deep-equal - listitem: - list: - listitem: 1.1 `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(e.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(e.message)).toContain('+ - listitem: \"1.2\"'); await expect(page).toMatchAriaSnapshot(` - list: - /children: deep-equal - listitem: - list: - /children: contain - listitem: 1.1 `); }); test('top-level deep-equal', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36456' } }, async ({ page }) => { await page.setContent(` `); const error = await expect(page).toMatchAriaSnapshot(` - /children: deep-equal - list `, { timeout: 1000 }).catch(e => e); expect(stripAnsi(error.message)).toContain(` - - /children: deep-equal - - list + - list: + - listitem: + - list: + - listitem: "1.1" + - listitem: "1.2" `.trim()); }); test('generated snapshot includes text children when name is longer than text', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/40079' } }, async ({ page }) => { await page.setContent(`
Alpha 7
`); await expect(page.locator('section')).toMatchAriaSnapshot(` - /children: deep-equal - progressbar "Alpha Beta": Alpha 7 `); }); test('treat bad regex as a string', async ({ page }) => { await page.setContent(`Log in`); const error = await expect(page).toMatchAriaSnapshot(` - link "Log in": - /url: /[a/ `, { timeout: 1 }).catch(e => e); expect(stripAnsi(error.message)).toContain('expect(page).toMatchAriaSnapshot(expected) failed'); expect(stripAnsi(error.message)).toContain('- - /url: /[a/'); expect(stripAnsi(error.message)).toContain('+ - /url: /foo'); });