{action.apiName}
- {
- <>
-
Time
-
-
- >
- }
+
Time
+
+
{
!!paramKeys.length && <>
Parameters
@@ -78,6 +72,15 @@ type Property = {
text: string;
};
+function renderDuration(action: ActionTraceEventInContext): string {
+ if (action.endTime)
+ return msToString(action.endTime - action.startTime);
+ else if (!!action.error)
+ return 'Timed Out';
+ else
+ return 'Running';
+}
+
function renderProperty(property: Property) {
let text = property.text.replace(/\n/g, '↵');
if (property.type === 'string')
diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts
index 878262400d..78bfb667d8 100644
--- a/tests/page/page-aria-snapshot.spec.ts
+++ b/tests/page/page-aria-snapshot.spec.ts
@@ -605,3 +605,16 @@ it('should escape special yaml values', async ({ page }) => {
- textbox: "555"
`);
});
+
+it('should not report textarea textContent', async ({ page }) => {
+ await page.setContent(`
`);
+ await checkAndMatchSnapshot(page.locator('body'), `
+ - textbox: Before
+ `);
+ await page.evaluate(() => {
+ document.querySelector('textarea').value = 'After';
+ });
+ await checkAndMatchSnapshot(page.locator('body'), `
+ - textbox: After
+ `);
+});
diff --git a/tests/playwright-test/aria-snapshot-file.spec.ts b/tests/playwright-test/aria-snapshot-file.spec.ts
index f9c2563f37..c121d623d1 100644
--- a/tests/playwright-test/aria-snapshot-file.spec.ts
+++ b/tests/playwright-test/aria-snapshot-file.spec.ts
@@ -22,12 +22,7 @@ test.describe.configure({ mode: 'parallel' });
test('should match snapshot with name', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
- '__snapshots__/a.spec.ts/test.yml': `
+ 'a.spec.ts-snapshots/test.yml': `
- heading "hello world"
`,
'a.spec.ts': `
@@ -44,11 +39,6 @@ test('should match snapshot with name', async ({ runInlineTest }, testInfo) => {
test('should generate multiple missing', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
'a.spec.ts': `
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
@@ -61,25 +51,20 @@ test('should generate multiple missing', async ({ runInlineTest }, testInfo) =>
});
expect(result.exitCode).toBe(1);
- expect(result.output).toContain(`A snapshot doesn't exist at __snapshots__${path.sep}a.spec.ts${path.sep}test-1.yml, writing actual`);
- expect(result.output).toContain(`A snapshot doesn't exist at __snapshots__${path.sep}a.spec.ts${path.sep}test-2.yml, writing actual`);
- const snapshot1 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-1.yml'), 'utf8');
+ expect(result.output).toContain(`A snapshot doesn't exist at a.spec.ts-snapshots${path.sep}test-1.yml, writing actual`);
+ expect(result.output).toContain(`A snapshot doesn't exist at a.spec.ts-snapshots${path.sep}test-2.yml, writing actual`);
+ const snapshot1 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-1.yml'), 'utf8');
expect(snapshot1).toBe('- heading "hello world" [level=1]');
- const snapshot2 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-2.yml'), 'utf8');
+ const snapshot2 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-2.yml'), 'utf8');
expect(snapshot2).toBe('- heading "hello world 2" [level=1]');
});
test('should rebaseline all', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
- '__snapshots__/a.spec.ts/test-1.yml': `
+ 'a.spec.ts-snapshots/test-1.yml': `
- heading "foo"
`,
- '__snapshots__/a.spec.ts/test-2.yml': `
+ 'a.spec.ts-snapshots/test-2.yml': `
- heading "bar"
`,
'a.spec.ts': `
@@ -94,22 +79,17 @@ test('should rebaseline all', async ({ runInlineTest }, testInfo) => {
}, { 'update-snapshots': 'all' });
expect(result.exitCode).toBe(0);
- expect(result.output).toContain(`A snapshot is generated at __snapshots__${path.sep}a.spec.ts${path.sep}test-1.yml`);
- expect(result.output).toContain(`A snapshot is generated at __snapshots__${path.sep}a.spec.ts${path.sep}test-2.yml`);
- const snapshot1 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-1.yml'), 'utf8');
+ expect(result.output).toContain(`A snapshot is generated at a.spec.ts-snapshots${path.sep}test-1.yml`);
+ expect(result.output).toContain(`A snapshot is generated at a.spec.ts-snapshots${path.sep}test-2.yml`);
+ const snapshot1 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-1.yml'), 'utf8');
expect(snapshot1).toBe('- heading "hello world" [level=1]');
- const snapshot2 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-2.yml'), 'utf8');
+ const snapshot2 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-2.yml'), 'utf8');
expect(snapshot2).toBe('- heading "hello world 2" [level=1]');
});
test('should not rebaseline matching', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
- '__snapshots__/a.spec.ts/test.yml': `
+ 'a.spec.ts-snapshots/test.yml': `
- heading "hello world"
`,
'a.spec.ts': `
@@ -122,17 +102,12 @@ test('should not rebaseline matching', async ({ runInlineTest }, testInfo) => {
}, { 'update-snapshots': 'changed' });
expect(result.exitCode).toBe(0);
- const snapshot1 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test.yml'), 'utf8');
+ const snapshot1 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test.yml'), 'utf8');
expect(snapshot1.trim()).toBe('- heading "hello world"');
});
test('should generate snapshot name', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
'a.spec.ts': `
import { test, expect } from '@playwright/test';
test('test name', async ({ page }) => {
@@ -145,11 +120,11 @@ test('should generate snapshot name', async ({ runInlineTest }, testInfo) => {
});
expect(result.exitCode).toBe(1);
- expect(result.output).toContain(`A snapshot doesn't exist at __snapshots__${path.sep}a.spec.ts${path.sep}test-name-1.yml, writing actual`);
- expect(result.output).toContain(`A snapshot doesn't exist at __snapshots__${path.sep}a.spec.ts${path.sep}test-name-2.yml, writing actual`);
- const snapshot1 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-name-1.yml'), 'utf8');
+ expect(result.output).toContain(`A snapshot doesn't exist at a.spec.ts-snapshots${path.sep}test-name-1.yml, writing actual`);
+ expect(result.output).toContain(`A snapshot doesn't exist at a.spec.ts-snapshots${path.sep}test-name-2.yml, writing actual`);
+ const snapshot1 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-name-1.yml'), 'utf8');
expect(snapshot1).toBe('- heading "hello world" [level=1]');
- const snapshot2 = await fs.promises.readFile(testInfo.outputPath('__snapshots__/a.spec.ts/test-name-2.yml'), 'utf8');
+ const snapshot2 = await fs.promises.readFile(testInfo.outputPath('a.spec.ts-snapshots/test-name-2.yml'), 'utf8');
expect(snapshot2).toBe('- heading "hello world 2" [level=1]');
});
@@ -158,7 +133,6 @@ for (const updateSnapshots of ['all', 'changed', 'missing', 'none']) {
const result = await runInlineTest({
'playwright.config.ts': `
export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
updateSnapshots: '${updateSnapshots}',
};
`,
@@ -169,13 +143,13 @@ for (const updateSnapshots of ['all', 'changed', 'missing', 'none']) {
await expect(page.locator('body')).toMatchAriaSnapshot({ timeout: 1 });
});
`,
- '__snapshots__/a.spec.ts/test-1.yml': '- heading "Old content" [level=1]',
+ 'a.spec.ts-snapshots/test-1.yml': '- heading "Old content" [level=1]',
});
const rebase = updateSnapshots === 'all' || updateSnapshots === 'changed';
expect(result.exitCode).toBe(rebase ? 0 : 1);
if (rebase) {
- const snapshotOutputPath = testInfo.outputPath('__snapshots__/a.spec.ts/test-1.yml');
+ const snapshotOutputPath = testInfo.outputPath('a.spec.ts-snapshots/test-1.yml');
expect(result.output).toContain(`A snapshot is generated at`);
const data = fs.readFileSync(snapshotOutputPath);
expect(data.toString()).toBe('- heading "New content" [level=1]');
@@ -187,14 +161,6 @@ for (const updateSnapshots of ['all', 'changed', 'missing', 'none']) {
test('should respect timeout', async ({ runInlineTest }, testInfo) => {
const result = await runInlineTest({
- 'playwright.config.ts': `
- export default {
- snapshotPathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
- };
- `,
- 'test.yml': `
- - heading "hello world"
- `,
'a.spec.ts': `
import { test, expect } from '@playwright/test';
import path from 'path';
@@ -203,9 +169,61 @@ test('should respect timeout', async ({ runInlineTest }, testInfo) => {
await expect(page.locator('body')).toMatchAriaSnapshot({ timeout: 1 });
});
`,
- '__snapshots__/a.spec.ts/test-1.yml': '- heading "new world" [level=1]',
+ 'a.spec.ts-snapshots/test-1.yml': '- heading "new world" [level=1]',
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain(`Timed out 1ms waiting for`);
});
+
+test('should respect config.snapshotPathTemplate', async ({ runInlineTest }, testInfo) => {
+ const result = await runInlineTest({
+ 'playwright.config.ts': `
+ export default {
+ snapshotPathTemplate: 'my-snapshots/{testFilePath}/{arg}{ext}',
+ };
+ `,
+ 'my-snapshots/dir/a.spec.ts/test.yml': `
+ - heading "hello world"
+ `,
+ 'dir/a.spec.ts': `
+ import { test, expect } from '@playwright/test';
+ test('test', async ({ page }) => {
+ await page.setContent(\`
hello world
\`);
+ await expect(page.locator('body')).toMatchAriaSnapshot({ name: 'test.yml' });
+ });
+ `
+ });
+ expect(result.exitCode).toBe(0);
+ expect(result.passed).toBe(1);
+});
+
+test('should respect config.expect.toMatchAriaSnapshot.pathTemplate', async ({ runInlineTest }, testInfo) => {
+ const result = await runInlineTest({
+ 'playwright.config.ts': `
+ export default {
+ snapshotPathTemplate: 'my-snapshots/{testFilePath}/{arg}{ext}',
+ expect: {
+ toMatchAriaSnapshot: {
+ pathTemplate: 'actual-snapshots/{testFilePath}/{arg}{ext}',
+ },
+ },
+ };
+ `,
+ 'my-snapshots/dir/a.spec.ts/test.yml': `
+ - heading "wrong one"
+ `,
+ 'actual-snapshots/dir/a.spec.ts/test.yml': `
+ - heading "hello world"
+ `,
+ 'dir/a.spec.ts': `
+ import { test, expect } from '@playwright/test';
+ test('test', async ({ page }) => {
+ await page.setContent(\`
hello world
\`);
+ await expect(page.locator('body')).toMatchAriaSnapshot({ name: 'test.yml' });
+ });
+ `
+ });
+ expect(result.exitCode).toBe(0);
+ expect(result.passed).toBe(1);
+});
diff --git a/tests/playwright-test/reporter-line.spec.ts b/tests/playwright-test/reporter-line.spec.ts
index 7322af433f..9c69fd9cdc 100644
--- a/tests/playwright-test/reporter-line.spec.ts
+++ b/tests/playwright-test/reporter-line.spec.ts
@@ -125,7 +125,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
});
});
`,
- }, { reporter: 'line' });
+ }, { reporter: 'line' }, { PLAYWRIGHT_FORCE_TTY: '1' });
const text = result.output;
expect(text).toContain('[1/1] a.test.ts:3:15 › passes › outer › inner');
expect(result.exitCode).toBe(0);
diff --git a/tests/playwright-test/to-have-screenshot.spec.ts b/tests/playwright-test/to-have-screenshot.spec.ts
index 3afa7a8d90..65e348cc52 100644
--- a/tests/playwright-test/to-have-screenshot.spec.ts
+++ b/tests/playwright-test/to-have-screenshot.spec.ts
@@ -740,6 +740,25 @@ test('should update snapshot with the update-snapshots flag', async ({ runInline
expect(comparePNGs(fs.readFileSync(snapshotOutputPath), whiteImage)).toBe(null);
});
+test('should respect config.expect.toHaveScreenshot.pathTemplate', async ({ runInlineTest }, testInfo) => {
+ const result = await runInlineTest({
+ ...playwrightConfig({
+ snapshotPathTemplate: '__screenshots__/{testFilePath}/{arg}{ext}',
+ expect: { toHaveScreenshot: { pathTemplate: 'actual-screenshots/{testFilePath}/{arg}{ext}' } },
+ }),
+ '__screenshots__/a.spec.js/snapshot.png': blueImage,
+ 'actual-screenshots/a.spec.js/snapshot.png': whiteImage,
+ 'a.spec.js': `
+ const { test, expect } = require('@playwright/test');
+ test('is a test', async ({ page }) => {
+ await expect(page).toHaveScreenshot('snapshot.png');
+ });
+ `
+ });
+ expect(result.exitCode).toBe(0);
+ expect(result.passed).toBe(1);
+});
+
test('shouldn\'t update snapshot with the update-snapshots flag for negated matcher', async ({ runInlineTest }, testInfo) => {
const EXPECTED_SNAPSHOT = blueImage;
const result = await runInlineTest({