|
|
|
@ -42,7 +42,11 @@ const expect = baseExpect.configure({ timeout: process.env.CI ? 75000 : 25000 })
|
|
|
|
|
|
|
|
|
|
|
|
test.describe.configure({ mode: 'parallel' });
|
|
|
|
test.describe.configure({ mode: 'parallel' });
|
|
|
|
|
|
|
|
|
|
|
|
test('should generate report', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
for (const useIntermediateMergeReport of [false, true] as const) {
|
|
|
|
|
|
|
|
test.describe(`${useIntermediateMergeReport ? 'merged' : 'created'}`, () => {
|
|
|
|
|
|
|
|
test.use({ useIntermediateMergeReport });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test('should generate report', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
await runInlineTest({
|
|
|
|
await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = { name: 'project-name' };
|
|
|
|
module.exports = { name: 'project-name' };
|
|
|
|
@ -79,10 +83,10 @@ test('should generate report', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
await expect(page.getByTestId('project-name'), 'should contain project name').toContainText('project-name');
|
|
|
|
await expect(page.getByTestId('project-name'), 'should contain project name').toContainText('project-name');
|
|
|
|
|
|
|
|
|
|
|
|
await expect(page.locator('.metadata-view')).not.toBeVisible();
|
|
|
|
await expect(page.locator('.metadata-view')).not.toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test('should not throw when attachment is missing', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
test('should not throw when attachment is missing', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = { preserveOutput: 'failures-only' };
|
|
|
|
module.exports = { preserveOutput: 'failures-only' };
|
|
|
|
@ -102,9 +106,9 @@ test('should not throw when attachment is missing', async ({ runInlineTest, page
|
|
|
|
await showReport();
|
|
|
|
await showReport();
|
|
|
|
await page.click('text=passes');
|
|
|
|
await page.click('text=passes');
|
|
|
|
await expect(page.getByRole('link', { name: 'screenshot' })).toBeVisible();
|
|
|
|
await expect(page.getByRole('link', { name: 'screenshot' })).toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include image diff', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include image diff', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
@ -156,9 +160,9 @@ test('should include image diff', async ({ runInlineTest, page, showReport }) =>
|
|
|
|
await imageDiff.locator('text="Diff"').click();
|
|
|
|
await imageDiff.locator('text="Diff"').click();
|
|
|
|
set.add(await imageDiff.locator('img').getAttribute('src'));
|
|
|
|
set.add(await imageDiff.locator('img').getAttribute('src'));
|
|
|
|
expect(set.size, 'Should be three images altogether').toBe(3);
|
|
|
|
expect(set.size, 'Should be three images altogether').toBe(3);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include multiple image diffs', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include multiple image diffs', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const IMG_WIDTH = 200;
|
|
|
|
const IMG_WIDTH = 200;
|
|
|
|
const IMG_HEIGHT = 200;
|
|
|
|
const IMG_HEIGHT = 200;
|
|
|
|
const redImage = createImage(IMG_WIDTH, IMG_HEIGHT, 255, 0, 0);
|
|
|
|
const redImage = createImage(IMG_WIDTH, IMG_HEIGHT, 255, 0, 0);
|
|
|
|
@ -197,9 +201,9 @@ test('should include multiple image diffs', async ({ runInlineTest, page, showRe
|
|
|
|
const image = imageDiff.locator('img').first();
|
|
|
|
const image = imageDiff.locator('img').first();
|
|
|
|
await expect(image).toHaveAttribute('src', /.*png/);
|
|
|
|
await expect(image).toHaveAttribute('src', /.*png/);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include image diffs for same expectation', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include image diffs for same expectation', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
@ -230,9 +234,9 @@ test('should include image diffs for same expectation', async ({ runInlineTest,
|
|
|
|
'Image mismatch: expected.png-1',
|
|
|
|
'Image mismatch: expected.png-1',
|
|
|
|
'Image mismatch: expected.png-2',
|
|
|
|
'Image mismatch: expected.png-2',
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include image diff when screenshot failed to generate due to animation', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include image diff when screenshot failed to generate due to animation', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = { use: { viewport: { width: 200, height: 200 }} };
|
|
|
|
module.exports = { use: { viewport: { width: 200, height: 200 }} };
|
|
|
|
@ -270,9 +274,9 @@ test('should include image diff when screenshot failed to generate due to animat
|
|
|
|
const diffSrc = await image.getAttribute('src');
|
|
|
|
const diffSrc = await image.getAttribute('src');
|
|
|
|
const set = new Set([previousSrc, actualSrc, diffSrc]);
|
|
|
|
const set = new Set([previousSrc, actualSrc, diffSrc]);
|
|
|
|
expect(set.size).toBe(3);
|
|
|
|
expect(set.size).toBe(3);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should not include image diff with non-images', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should not include image diff with non-images', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const expected = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAAhVJREFUeJzt07ERwCAQwLCQ/Xd+FuDcQiFN4MZrZuYDjv7bAfAyg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAgEg0AwCASDQDAIBINAMAiEDVPZBYx6ffy+AAAAAElFTkSuQmCC', 'base64');
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
@ -299,9 +303,9 @@ test('should not include image diff with non-images', async ({ runInlineTest, pa
|
|
|
|
await expect(page.locator('img')).toHaveCount(0);
|
|
|
|
await expect(page.locator('img')).toHaveCount(0);
|
|
|
|
await expect(page.locator('a', { hasText: 'expected-actual' })).toBeVisible();
|
|
|
|
await expect(page.locator('a', { hasText: 'expected-actual' })).toBeVisible();
|
|
|
|
await expect(page.locator('a', { hasText: 'expected-expected' })).toBeVisible();
|
|
|
|
await expect(page.locator('a', { hasText: 'expected-expected' })).toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include screenshot on failure', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include screenshot on failure', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
module.exports = {
|
|
|
|
@ -328,9 +332,9 @@ test('should include screenshot on failure', async ({ runInlineTest, page, showR
|
|
|
|
await expect(page.locator('img')).toBeVisible();
|
|
|
|
await expect(page.locator('img')).toBeVisible();
|
|
|
|
const src = await page.locator('img').getAttribute('src');
|
|
|
|
const src = await page.locator('img').getAttribute('src');
|
|
|
|
expect(src).toBeTruthy();
|
|
|
|
expect(src).toBeTruthy();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should use different path if attachments base url option is provided', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
test('should use different path if attachments base url option is provided', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
module.exports = {
|
|
|
|
@ -364,9 +368,9 @@ test('should use different path if attachments base url option is provided', asy
|
|
|
|
|
|
|
|
|
|
|
|
await expect(page.getByRole('link', { name: 'trace' })).toHaveAttribute('href', /(https:\/\/some-url\.com\/)[^/\s]+?\.[^/\s]+/);
|
|
|
|
await expect(page.getByRole('link', { name: 'trace' })).toHaveAttribute('href', /(https:\/\/some-url\.com\/)[^/\s]+?\.[^/\s]+/);
|
|
|
|
await expect(page.locator('div').filter({ hasText: /^Tracestrace$/ }).getByRole('link').first()).toHaveAttribute('href', /trace=(https:\/\/some-url\.com\/)[^/\s]+?\.[^/\s]+/);
|
|
|
|
await expect(page.locator('div').filter({ hasText: /^Tracestrace$/ }).getByRole('link').first()).toHaveAttribute('href', /trace=(https:\/\/some-url\.com\/)[^/\s]+?\.[^/\s]+/);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should include stdio', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should include stdio', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.test.js': `
|
|
|
|
'a.test.js': `
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
@ -387,9 +391,9 @@ test('should include stdio', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
await expect(page.locator('.attachment-body')).toHaveText('First line\nSecond line');
|
|
|
|
await expect(page.locator('.attachment-body')).toHaveText('First line\nSecond line');
|
|
|
|
await page.locator('text=stderr').click();
|
|
|
|
await page.locator('text=stderr').click();
|
|
|
|
await expect(page.locator('.attachment-body').nth(1)).toHaveText('Third line');
|
|
|
|
await expect(page.locator('.attachment-body').nth(1)).toHaveText('Third line');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should highlight error', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should highlight error', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.test.js': `
|
|
|
|
'a.test.js': `
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
@ -404,9 +408,9 @@ test('should highlight error', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
await showReport();
|
|
|
|
await showReport();
|
|
|
|
await page.click('text=fails');
|
|
|
|
await page.click('text=fails');
|
|
|
|
await expect(page.locator('.test-result-error-message span:has-text("received")').nth(1)).toHaveCSS('color', 'rgb(204, 0, 0)');
|
|
|
|
await expect(page.locator('.test-result-error-message span:has-text("received")').nth(1)).toHaveCSS('color', 'rgb(204, 0, 0)');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should show trace source', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should show trace source', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
@ -437,9 +441,9 @@ test('should show trace source', async ({ runInlineTest, page, showReport }) =>
|
|
|
|
/a.test.js:[\d]+/,
|
|
|
|
/a.test.js:[\d]+/,
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
await expect(page.getByTestId('stack-trace').locator('.list-view-entry.selected')).toContainText('a.test.js');
|
|
|
|
await expect(page.getByTestId('stack-trace').locator('.list-view-entry.selected')).toContainText('a.test.js');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should show trace title', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should show trace title', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
@ -458,9 +462,9 @@ test('should show trace title', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
await page.click('text=passes');
|
|
|
|
await page.click('text=passes');
|
|
|
|
await page.click('img');
|
|
|
|
await page.click('img');
|
|
|
|
await expect(page.locator('.workbench .title')).toHaveText('a.test.js:3 › passes');
|
|
|
|
await expect(page.locator('.workbench .title')).toHaveText('a.test.js:3 › passes');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should show multi trace source', async ({ runInlineTest, page, server, showReport }) => {
|
|
|
|
test('should show multi trace source', async ({ runInlineTest, page, server, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
@ -492,9 +496,9 @@ test('should show multi trace source', async ({ runInlineTest, page, server, sho
|
|
|
|
await page.click('.action-title >> text=apiRequestContext.get');
|
|
|
|
await page.click('.action-title >> text=apiRequestContext.get');
|
|
|
|
await page.click('text=Source');
|
|
|
|
await page.click('text=Source');
|
|
|
|
await expect(page.locator('.source-line-running')).toContainText('request.get');
|
|
|
|
await expect(page.locator('.source-line-running')).toContainText('request.get');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should warn user when viewing via file:// protocol', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
test('should warn user when viewing via file:// protocol', async ({ runInlineTest, page, showReport }, testInfo) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
module.exports = { use: { trace: 'on' } };
|
|
|
|
@ -522,9 +526,9 @@ test('should warn user when viewing via file:// protocol', async ({ runInlineTes
|
|
|
|
await expect(page.locator('dialog')).toBeVisible();
|
|
|
|
await expect(page.locator('dialog')).toBeVisible();
|
|
|
|
await expect(page.locator('dialog')).toContainText('must be loaded over');
|
|
|
|
await expect(page.locator('dialog')).toContainText('must be loaded over');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should show failed and timed out steps and hooks', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should show failed and timed out steps and hooks', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { timeout: 3000 };
|
|
|
|
module.exports = { timeout: 3000 };
|
|
|
|
@ -593,9 +597,9 @@ test('should show failed and timed out steps and hooks', async ({ runInlineTest,
|
|
|
|
/afterEach hook/,
|
|
|
|
/afterEach hook/,
|
|
|
|
/afterAll hook/,
|
|
|
|
/afterAll hook/,
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should render annotations', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should render annotations', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { timeout: 1500 };
|
|
|
|
module.exports = { timeout: 1500 };
|
|
|
|
@ -613,9 +617,9 @@ test('should render annotations', async ({ runInlineTest, page, showReport }) =>
|
|
|
|
await showReport();
|
|
|
|
await showReport();
|
|
|
|
await page.click('text=skipped test');
|
|
|
|
await page.click('text=skipped test');
|
|
|
|
await expect(page.locator('.test-case-annotation')).toHaveText('skip: I am not interested in this test');
|
|
|
|
await expect(page.locator('.test-case-annotation')).toHaveText('skip: I am not interested in this test');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should render annotations as link if needed', async ({ runInlineTest, page, showReport, server }) => {
|
|
|
|
test('should render annotations as link if needed', async ({ runInlineTest, page, showReport, server }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
module.exports = { timeout: 1500 };
|
|
|
|
module.exports = { timeout: 1500 };
|
|
|
|
@ -637,9 +641,9 @@ test('should render annotations as link if needed', async ({ runInlineTest, page
|
|
|
|
await page.getByRole('link', { name: server.EMPTY_PAGE }).click();
|
|
|
|
await page.getByRole('link', { name: server.EMPTY_PAGE }).click();
|
|
|
|
const popup = await popupPromise;
|
|
|
|
const popup = await popupPromise;
|
|
|
|
expect(popup.url()).toBe(server.EMPTY_PAGE);
|
|
|
|
expect(popup.url()).toBe(server.EMPTY_PAGE);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should render text attachments as text', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
test('should render text attachments as text', async ({ runInlineTest, page, showReport }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.test.js': `
|
|
|
|
'a.test.js': `
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
@ -678,9 +682,9 @@ test('should render text attachments as text', async ({ runInlineTest, page, sho
|
|
|
|
await page.getByText('example.json', { exact: true }).click();
|
|
|
|
await page.getByText('example.json', { exact: true }).click();
|
|
|
|
await page.getByText('example-utf16.txt', { exact: true }).click();
|
|
|
|
await page.getByText('example-utf16.txt', { exact: true }).click();
|
|
|
|
await expect(page.locator('.attachment-body')).toHaveText(['foo', '{"foo":1}', 'utf16 encoded']);
|
|
|
|
await expect(page.locator('.attachment-body')).toHaveText(['foo', '{"foo":1}', 'utf16 encoded']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should use file-browser friendly extensions for buffer attachments based on contentType', async ({ runInlineTest }, testInfo) => {
|
|
|
|
test('should use file-browser friendly extensions for buffer attachments based on contentType', async ({ runInlineTest }, testInfo) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.test.js': `
|
|
|
|
'a.test.js': `
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
@ -705,9 +709,9 @@ test('should use file-browser friendly extensions for buffer attachments based o
|
|
|
|
'84a516841ba77a5b4648de2cd0dfcb30ea46dbb4.png', // screenshot-that-already-has-an-extension-with-correct-contentType.png
|
|
|
|
'84a516841ba77a5b4648de2cd0dfcb30ea46dbb4.png', // screenshot-that-already-has-an-extension-with-correct-contentType.png
|
|
|
|
'e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98.ext-with-spaces', // example.ext with spaces
|
|
|
|
'e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98.ext-with-spaces', // example.ext with spaces
|
|
|
|
]));
|
|
|
|
]));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should strikethrough textual diff', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should strikethrough textual diff', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'helper.ts': `
|
|
|
|
'helper.ts': `
|
|
|
|
import { test as base } from '@playwright/test';
|
|
|
|
import { test as base } from '@playwright/test';
|
|
|
|
@ -732,9 +736,9 @@ test('should strikethrough textual diff', async ({ runInlineTest, showReport, pa
|
|
|
|
await page.click('text="is a test"');
|
|
|
|
await page.click('text="is a test"');
|
|
|
|
const stricken = await page.locator('css=strike').innerText();
|
|
|
|
const stricken = await page.locator('css=strike').innerText();
|
|
|
|
expect(stricken).toBe('old');
|
|
|
|
expect(stricken).toBe('old');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should strikethrough textual diff with commonalities', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should strikethrough textual diff with commonalities', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'helper.ts': `
|
|
|
|
'helper.ts': `
|
|
|
|
import { test as base } from '@playwright/test';
|
|
|
|
import { test as base } from '@playwright/test';
|
|
|
|
@ -759,9 +763,9 @@ test('should strikethrough textual diff with commonalities', async ({ runInlineT
|
|
|
|
await page.click('text="is a test"');
|
|
|
|
await page.click('text="is a test"');
|
|
|
|
const stricken = await page.locator('css=strike').innerText();
|
|
|
|
const stricken = await page.locator('css=strike').innerText();
|
|
|
|
expect(stricken).toBe('old');
|
|
|
|
expect(stricken).toBe('old');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should differentiate repeat-each test cases', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should differentiate repeat-each test cases', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/10859' });
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/10859' });
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.spec.js': `
|
|
|
|
'a.spec.js': `
|
|
|
|
@ -782,9 +786,9 @@ test('should differentiate repeat-each test cases', async ({ runInlineTest, show
|
|
|
|
await page.locator('text=sample').nth(1).click();
|
|
|
|
await page.locator('text=sample').nth(1).click();
|
|
|
|
await expect(page.locator('text=Before Hooks')).toBeVisible();
|
|
|
|
await expect(page.locator('text=Before Hooks')).toBeVisible();
|
|
|
|
await expect(page.locator('text=ouch')).toBeHidden();
|
|
|
|
await expect(page.locator('text=ouch')).toBeHidden();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should group similar / loop steps', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should group similar / loop steps', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/10098' });
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/10098' });
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.spec.js': `
|
|
|
|
'a.spec.js': `
|
|
|
|
@ -805,9 +809,9 @@ test('should group similar / loop steps', async ({ runInlineTest, showReport, pa
|
|
|
|
/expect\.toBe.*10/,
|
|
|
|
/expect\.toBe.*10/,
|
|
|
|
/expect\.toEqual.*20/,
|
|
|
|
/expect\.toEqual.*20/,
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('open tests from required file', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('open tests from required file', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11742' });
|
|
|
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11742' });
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'inner.js': `
|
|
|
|
'inner.js': `
|
|
|
|
@ -823,9 +827,9 @@ test('open tests from required file', async ({ runInlineTest, showReport, page }
|
|
|
|
await expect(page.locator('.tree-item-title')).toContainText([
|
|
|
|
await expect(page.locator('.tree-item-title')).toContainText([
|
|
|
|
/expect\.toBe/,
|
|
|
|
/expect\.toBe/,
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('gitCommitInfo plugin', () => {
|
|
|
|
test.describe('gitCommitInfo plugin', () => {
|
|
|
|
test('should include metadata', async ({ runInlineTest, writeFiles, showReport, page }) => {
|
|
|
|
test('should include metadata', async ({ runInlineTest, writeFiles, showReport, page }) => {
|
|
|
|
const files = {
|
|
|
|
const files = {
|
|
|
|
'uncommitted.txt': `uncommitted file`,
|
|
|
|
'uncommitted.txt': `uncommitted file`,
|
|
|
|
@ -962,9 +966,10 @@ test.describe('gitCommitInfo plugin', () => {
|
|
|
|
await expect.soft(page.locator('data-test-id=metadata-error')).toBeVisible();
|
|
|
|
await expect.soft(page.locator('data-test-id=metadata-error')).toBeVisible();
|
|
|
|
await expect.soft(page.locator('data-test-id=metadata-chip')).not.toBeVisible();
|
|
|
|
await expect.soft(page.locator('data-test-id=metadata-chip')).not.toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should report clashing folders', async ({ runInlineTest }) => {
|
|
|
|
test('should report clashing folders', async ({ runInlineTest, useIntermediateMergeReport }) => {
|
|
|
|
|
|
|
|
test.skip(useIntermediateMergeReport);
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.ts': `
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
module.exports = {
|
|
|
|
@ -981,10 +986,11 @@ test('should report clashing folders', async ({ runInlineTest }) => {
|
|
|
|
const output = result.output;
|
|
|
|
const output = result.output;
|
|
|
|
expect(output).toContain('Configuration Error');
|
|
|
|
expect(output).toContain('Configuration Error');
|
|
|
|
expect(output).toContain('html-report');
|
|
|
|
expect(output).toContain('html-report');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('report location', () => {
|
|
|
|
test.describe('report location', () => {
|
|
|
|
test('with config should create report relative to config', async ({ runInlineTest }, testInfo) => {
|
|
|
|
test('with config should create report relative to config', async ({ runInlineTest, useIntermediateMergeReport }, testInfo) => {
|
|
|
|
|
|
|
|
test.skip(useIntermediateMergeReport);
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'nested/project/playwright.config.ts': `
|
|
|
|
'nested/project/playwright.config.ts': `
|
|
|
|
module.exports = { reporter: [['html', { outputFolder: '../my-report/' }]] };
|
|
|
|
module.exports = { reporter: [['html', { outputFolder: '../my-report/' }]] };
|
|
|
|
@ -1044,9 +1050,9 @@ test.describe('report location', () => {
|
|
|
|
expect(result.passed).toBe(1);
|
|
|
|
expect(result.passed).toBe(1);
|
|
|
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report'))).toBe(true);
|
|
|
|
expect(fs.existsSync(testInfo.outputPath('foo', 'bar', 'baz', 'my-report'))).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test.describe('labels', () => {
|
|
|
|
test.describe('labels', () => {
|
|
|
|
test('should show labels in the test row', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should show labels in the test row', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'playwright.config.js': `
|
|
|
|
'playwright.config.js': `
|
|
|
|
@ -1835,9 +1841,9 @@ test.describe('labels', () => {
|
|
|
|
await expect(page.locator('.test-case-title')).toHaveText('Test passed -- @call @call-details @e2e @regression #VQ457');
|
|
|
|
await expect(page.locator('.test-case-title')).toHaveText('Test passed -- @call @call-details @e2e @regression #VQ457');
|
|
|
|
await expect(page.locator('.label')).toHaveText(['firefox', 'call', 'call-details', 'e2e', 'Monitoring', 'regression']);
|
|
|
|
await expect(page.locator('.label')).toHaveText(['firefox', 'call', 'call-details', 'e2e', 'Monitoring', 'regression']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('should list tests in the right order', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('should list tests in the right order', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
await runInlineTest({
|
|
|
|
await runInlineTest({
|
|
|
|
'main.spec.ts': `
|
|
|
|
'main.spec.ts': `
|
|
|
|
import firstTest from './first';
|
|
|
|
import firstTest from './first';
|
|
|
|
@ -1883,9 +1889,9 @@ test('should list tests in the right order', async ({ runInlineTest, showReport,
|
|
|
|
/main › first › passes\d+m?sfirst.ts:12/,
|
|
|
|
/main › first › passes\d+m?sfirst.ts:12/,
|
|
|
|
/main › second › passes\d+m?ssecond.ts:5/,
|
|
|
|
/main › second › passes\d+m?ssecond.ts:5/,
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('tests should filter by file', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('tests should filter by file', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'file-a.test.js': `
|
|
|
|
'file-a.test.js': `
|
|
|
|
const { test } = require('@playwright/test');
|
|
|
|
const { test } = require('@playwright/test');
|
|
|
|
@ -1918,9 +1924,9 @@ test('tests should filter by file', async ({ runInlineTest, showReport, page })
|
|
|
|
await searchInput.fill('file-a:3');
|
|
|
|
await searchInput.fill('file-a:3');
|
|
|
|
await expect(page.getByText('a test 1')).toBeVisible();
|
|
|
|
await expect(page.getByText('a test 1')).toBeVisible();
|
|
|
|
await expect(page.getByText('a test 2')).not.toBeVisible();
|
|
|
|
await expect(page.getByText('a test 2')).not.toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
test('tests should filter by status', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
test('tests should filter by status', async ({ runInlineTest, showReport, page }) => {
|
|
|
|
const result = await runInlineTest({
|
|
|
|
const result = await runInlineTest({
|
|
|
|
'a.test.js': `
|
|
|
|
'a.test.js': `
|
|
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
@ -1941,4 +1947,6 @@ test('tests should filter by status', async ({ runInlineTest, showReport, page }
|
|
|
|
await expect(page.getByText('a.test.js', { exact: true })).toBeVisible();
|
|
|
|
await expect(page.getByText('a.test.js', { exact: true })).toBeVisible();
|
|
|
|
await expect(page.getByText('failed title')).not.toBeVisible();
|
|
|
|
await expect(page.getByText('failed title')).not.toBeVisible();
|
|
|
|
await expect(page.getByText('passes title')).toBeVisible();
|
|
|
|
await expect(page.getByText('passes title')).toBeVisible();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|