chore: add pageSnapshot option (#34669)
This commit is contained in:
parent
d2e7e8acdb
commit
8ed2f4319e
|
@ -507,6 +507,27 @@ export default defineConfig({
|
|||
|
||||
Learn more about [automatic screenshots](../test-use-options.md#recording-options).
|
||||
|
||||
## property: TestOptions.pageSnapshot
|
||||
* since: v1.51
|
||||
- type: <[PageSnapshotMode]<"off"|"on"|"only-on-failure">>
|
||||
|
||||
Whether to automatically capture a ARIA snapshot of the page after each test. Defaults to `'only-on-failure'`.
|
||||
* `'off'`: Do not capture page snapshots.
|
||||
* `'on'`: Capture page snapshot after each test.
|
||||
* `'only-on-failure'`: Capture page snapshot after each test failure.
|
||||
|
||||
**Usage**
|
||||
|
||||
```js title="playwright.config.ts"
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
use: {
|
||||
pageSnapshot: 'on',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## property: TestOptions.storageState = %%-js-python-context-option-storage-state-%%
|
||||
* since: v1.10
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import { addInternalStackPrefix, asLocator, createGuid, debugMode, isString, jso
|
|||
import { currentTestInfo } from './common/globals';
|
||||
import { rootTestType } from './common/testType';
|
||||
|
||||
import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, VideoMode } from '../types/test';
|
||||
import type { Fixtures, PageSnapshotMode, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, VideoMode } from '../types/test';
|
||||
import type { ContextReuseMode } from './common/config';
|
||||
import type { TestInfoImpl, TestStepInternal } from './worker/testInfo';
|
||||
import type { ApiCallData, ClientInstrumentation, ClientInstrumentationListener } from '../../playwright-core/src/client/clientInstrumentation';
|
||||
|
@ -59,7 +59,6 @@ type WorkerFixtures = PlaywrightWorkerArgs & PlaywrightWorkerOptions & {
|
|||
_optionContextReuseMode: ContextReuseMode,
|
||||
_optionConnectOptions: PlaywrightWorkerOptions['connectOptions'],
|
||||
_reuseContext: boolean,
|
||||
_pageSnapshot: PageSnapshotOption,
|
||||
};
|
||||
|
||||
const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||
|
@ -77,7 +76,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
|||
screenshot: ['off', { scope: 'worker', option: true }],
|
||||
video: ['off', { scope: 'worker', option: true }],
|
||||
trace: ['off', { scope: 'worker', option: true }],
|
||||
_pageSnapshot: ['off', { scope: 'worker', option: true }],
|
||||
pageSnapshot: ['only-on-failure', { scope: 'worker', option: true }],
|
||||
|
||||
_browserOptions: [async ({ playwright, headless, channel, launchOptions }, use) => {
|
||||
const options: LaunchOptions = {
|
||||
|
@ -245,13 +244,13 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
|||
playwright._defaultContextNavigationTimeout = undefined;
|
||||
}, { auto: 'all-hooks-included', title: 'context configuration', box: true } as any],
|
||||
|
||||
_setupArtifacts: [async ({ playwright, screenshot, _pageSnapshot }, use, testInfo) => {
|
||||
_setupArtifacts: [async ({ playwright, screenshot, pageSnapshot }, use, testInfo) => {
|
||||
// This fixture has a separate zero-timeout slot to ensure that artifact collection
|
||||
// happens even after some fixtures or hooks time out.
|
||||
// Now that default test timeout is known, we can replace zero with an actual value.
|
||||
testInfo.setTimeout(testInfo.project.timeout);
|
||||
|
||||
const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot, _pageSnapshot);
|
||||
const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot, pageSnapshot);
|
||||
await artifactsRecorder.willStartTest(testInfo as TestInfoImpl);
|
||||
|
||||
const tracingGroupSteps: TestStepInternal[] = [];
|
||||
|
@ -449,7 +448,6 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
|||
});
|
||||
|
||||
type ScreenshotOption = PlaywrightWorkerOptions['screenshot'] | undefined;
|
||||
type PageSnapshotOption = 'off' | 'on' | 'only-on-failure';
|
||||
|
||||
function normalizeVideoMode(video: VideoMode | 'retry-with-video' | { mode: VideoMode } | undefined): VideoMode {
|
||||
if (!video)
|
||||
|
@ -528,7 +526,7 @@ class SnapshotRecorder {
|
|||
|
||||
constructor(
|
||||
private _artifactsRecorder: ArtifactsRecorder,
|
||||
private _mode: ScreenshotMode | PageSnapshotOption,
|
||||
private _mode: ScreenshotMode | PageSnapshotMode,
|
||||
private _name: string,
|
||||
private _contentType: string,
|
||||
private _extension: string,
|
||||
|
@ -620,7 +618,7 @@ class ArtifactsRecorder {
|
|||
private _pageSnapshotRecorder: SnapshotRecorder;
|
||||
private _screenshotRecorder: SnapshotRecorder;
|
||||
|
||||
constructor(playwright: PlaywrightImpl, artifactsDir: string, screenshot: ScreenshotOption, pageSnapshot: PageSnapshotOption) {
|
||||
constructor(playwright: PlaywrightImpl, artifactsDir: string, screenshot: ScreenshotOption, pageSnapshot: PageSnapshotMode) {
|
||||
this._playwright = playwright;
|
||||
this._artifactsDir = artifactsDir;
|
||||
const screenshotOptions = typeof screenshot === 'string' ? undefined : screenshot;
|
||||
|
@ -631,7 +629,7 @@ class ArtifactsRecorder {
|
|||
});
|
||||
|
||||
this._pageSnapshotRecorder = new SnapshotRecorder(this, pageSnapshot, 'pageSnapshot', 'text/plain', '.ariasnapshot', async (page, path) => {
|
||||
const ariaSnapshot = await page.locator('body').ariaSnapshot();
|
||||
const ariaSnapshot = await page.locator('body').ariaSnapshot({ timeout: 5000 });
|
||||
await fs.promises.writeFile(path, ariaSnapshot);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -312,9 +312,9 @@ export class TestServerDispatcher implements TestServerInterface {
|
|||
...(params.trace === 'off' ? { trace: 'off' } : {}),
|
||||
...(params.video === 'on' || params.video === 'off' ? { video: params.video } : {}),
|
||||
...(params.headed !== undefined ? { headless: !params.headed } : {}),
|
||||
...(params.pageSnapshot ? { pageSnapshot: params.pageSnapshot } : undefined),
|
||||
_optionContextReuseMode: params.reuseContext ? 'when-possible' : undefined,
|
||||
_optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : undefined,
|
||||
_pageSnapshot: params.pageSnapshot,
|
||||
},
|
||||
...(params.updateSnapshots ? { updateSnapshots: params.updateSnapshots } : {}),
|
||||
...(params.updateSourceMethod ? { updateSourceMethod: params.updateSourceMethod } : {}),
|
||||
|
|
|
@ -6187,6 +6187,27 @@ export interface PlaywrightWorkerOptions {
|
|||
* Learn more about [automatic screenshots](https://playwright.dev/docs/test-use-options#recording-options).
|
||||
*/
|
||||
screenshot: ScreenshotMode | { mode: ScreenshotMode } & Pick<PageScreenshotOptions, 'fullPage' | 'omitBackground'>;
|
||||
/**
|
||||
* Whether to automatically capture a ARIA snapshot of the page after each test. Defaults to `'only-on-failure'`.
|
||||
* - `'off'`: Do not capture page snapshots.
|
||||
* - `'on'`: Capture page snapshot after each test.
|
||||
* - `'only-on-failure'`: Capture page snapshot after each test failure.
|
||||
*
|
||||
* **Usage**
|
||||
*
|
||||
* ```js
|
||||
* // playwright.config.ts
|
||||
* import { defineConfig } from '@playwright/test';
|
||||
*
|
||||
* export default defineConfig({
|
||||
* use: {
|
||||
* pageSnapshot: 'on',
|
||||
* },
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
pageSnapshot: PageSnapshotMode;
|
||||
/**
|
||||
* Whether to record trace for each test. Defaults to `'off'`.
|
||||
* - `'off'`: Do not record trace.
|
||||
|
@ -6246,6 +6267,7 @@ export interface PlaywrightWorkerOptions {
|
|||
}
|
||||
|
||||
export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure';
|
||||
export type PageSnapshotMode = 'off' | 'on' | 'only-on-failure';
|
||||
export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure';
|
||||
export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ test('should work with screenshot: on', async ({ runInlineTest }, testInfo) => {
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { screenshot: 'on' } };
|
||||
module.exports = { use: { screenshot: 'on', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
@ -168,7 +168,7 @@ test('should work with screenshot: only-on-failure', async ({ runInlineTest }, t
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { screenshot: 'only-on-failure' } };
|
||||
module.exports = { use: { screenshot: 'only-on-failure', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
@ -204,7 +204,7 @@ test('should work with screenshot: on-first-failure', async ({ runInlineTest },
|
|||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
retries: 1,
|
||||
use: { screenshot: 'on-first-failure' }
|
||||
use: { screenshot: 'on-first-failure', pageSnapshot: 'off' }
|
||||
};
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
@ -231,7 +231,7 @@ test('should work with screenshot: only-on-failure & fullPage', async ({ runInli
|
|||
});
|
||||
`,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { screenshot: { mode: 'only-on-failure', fullPage: true } } };
|
||||
module.exports = { use: { screenshot: { mode: 'only-on-failure', fullPage: true }, pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
expect(result.exitCode).toBe(1);
|
||||
|
@ -252,7 +252,7 @@ test('should work with trace: on', async ({ runInlineTest }, testInfo) => {
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'on' } };
|
||||
module.exports = { use: { trace: 'on', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
@ -288,7 +288,7 @@ test('should work with trace: retain-on-failure', async ({ runInlineTest }, test
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'retain-on-failure' } };
|
||||
module.exports = { use: { trace: 'retain-on-failure', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
@ -314,7 +314,7 @@ test('should work with trace: on-first-retry', async ({ runInlineTest }, testInf
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'on-first-retry' } };
|
||||
module.exports = { use: { trace: 'on-first-retry', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1, retries: 1 });
|
||||
|
||||
|
@ -340,7 +340,7 @@ test('should work with trace: on-all-retries', async ({ runInlineTest }, testInf
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'on-all-retries' } };
|
||||
module.exports = { use: { trace: 'on-all-retries', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1, retries: 2 });
|
||||
|
||||
|
@ -376,7 +376,7 @@ test('should work with trace: retain-on-first-failure', async ({ runInlineTest }
|
|||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'retain-on-first-failure' } };
|
||||
module.exports = { use: { trace: 'retain-on-first-failure', pageSnapshot: 'off' } };
|
||||
`,
|
||||
}, { workers: 1, retries: 2 });
|
||||
|
||||
|
@ -421,11 +421,11 @@ test('should take screenshot when page is closed in afterEach', async ({ runInli
|
|||
expect(fs.existsSync(testInfo.outputPath('test-results', 'a-fails', 'test-failed-1.png'))).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should work with _pageSnapshot: on', async ({ runInlineTest }, testInfo) => {
|
||||
test('should work with pageSnapshot: on', async ({ runInlineTest }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { _pageSnapshot: 'on' } };
|
||||
module.exports = { use: { pageSnapshot: 'on' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
@ -461,11 +461,11 @@ test('should work with _pageSnapshot: on', async ({ runInlineTest }, testInfo) =
|
|||
]);
|
||||
});
|
||||
|
||||
test('should work with _pageSnapshot: only-on-failure', async ({ runInlineTest }, testInfo) => {
|
||||
test('should work with pageSnapshot: only-on-failure', async ({ runInlineTest }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
...testFiles,
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { _pageSnapshot: 'only-on-failure' } };
|
||||
module.exports = { use: { pageSnapshot: 'only-on-failure' } };
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
|
|
|
@ -485,7 +485,7 @@ test('should work with video: retain-on-failure', async ({ runInlineTest }) => {
|
|||
test('should work with video: on-first-retry', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { video: 'on-first-retry' }, retries: 1, name: 'chromium' };
|
||||
module.exports = { use: { video: 'on-first-retry', pageSnapshot: 'off' }, retries: 1, name: 'chromium' };
|
||||
`,
|
||||
'a.test.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
|
|
@ -59,7 +59,7 @@ test('should stop tracing with trace: on-first-retry, when not retrying', async
|
|||
test('should record api trace', async ({ runInlineTest, server }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'on' } };
|
||||
module.exports = { use: { trace: 'on', pageSnapshot: 'off' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
@ -290,7 +290,7 @@ test('should work in serial mode', async ({ runInlineTest }, testInfo) => {
|
|||
test('should not override trace file in afterAll', async ({ runInlineTest, server }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'retain-on-failure' } };
|
||||
module.exports = { use: { trace: 'retain-on-failure', pageSnapshot: 'off' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
@ -642,7 +642,7 @@ test('should expand expect.toPass', async ({ runInlineTest }, testInfo) => {
|
|||
test('should show non-expect error in trace', async ({ runInlineTest }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: { mode: 'on' } } };
|
||||
module.exports = { use: { trace: { mode: 'on' }, pageSnapshot: 'off' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
@ -850,7 +850,7 @@ test('should record nested steps, even after timeout', async ({ runInlineTest },
|
|||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
use: { trace: { mode: 'on' } },
|
||||
use: { trace: { mode: 'on' }, pageSnapshot: 'off' },
|
||||
timeout: 5000,
|
||||
};
|
||||
`,
|
||||
|
@ -1156,6 +1156,9 @@ test('should record trace for manually created context in a failed test', async
|
|||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31541' });
|
||||
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { pageSnapshot: 'off' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('fail', async ({ browser }) => {
|
||||
|
@ -1234,6 +1237,9 @@ test('should record trace after fixture teardown timeout', {
|
|||
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30718' },
|
||||
}, async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { pageSnapshot: 'off' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test as base, expect } from '@playwright/test';
|
||||
const test = base.extend({
|
||||
|
|
|
@ -192,6 +192,9 @@ test('should not report nested after hooks', async ({ runInlineTest }) => {
|
|||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
reporter: './reporter',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
}
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
|
@ -577,6 +580,9 @@ test('should not mark page.close as failed when page.click fails', async ({ runI
|
|||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
reporter: './reporter',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
}
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
|
@ -1230,6 +1236,9 @@ test('should report api step failure', async ({ runInlineTest }) => {
|
|||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
reporter: './reporter',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
}
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
|
|
|
@ -619,6 +619,9 @@ test('should write missing expectations locally twice and attach them', async ({
|
|||
const result = await runInlineTest({
|
||||
...playwrightConfig({
|
||||
snapshotPathTemplate: '__screenshots__/{testFilePath}/{arg}{ext}',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
},
|
||||
}),
|
||||
'a.spec.js': `
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
@ -688,7 +691,12 @@ test('should attach missing expectations to right step', async ({ runInlineTest
|
|||
}
|
||||
module.exports = Reporter;
|
||||
`,
|
||||
...playwrightConfig({ reporter: [['dot'], ['./reporter']] }),
|
||||
...playwrightConfig({
|
||||
reporter: [['dot'], ['./reporter']],
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
}
|
||||
}),
|
||||
'a.spec.js': `
|
||||
const { test, expect } = require('@playwright/test');
|
||||
test('is a test', async ({ page }) => {
|
||||
|
@ -1118,6 +1126,9 @@ test('should attach expected/actual/diff when sizes are different', async ({ run
|
|||
const result = await runInlineTest({
|
||||
...playwrightConfig({
|
||||
snapshotPathTemplate: '__screenshots__/{testFilePath}/{arg}{ext}',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
},
|
||||
}),
|
||||
'__screenshots__/a.spec.js/snapshot.png': createImage(2, 2),
|
||||
'a.spec.js': `
|
||||
|
@ -1376,6 +1387,9 @@ test('should trim+sanitize attachment names and paths', async ({ runInlineTest }
|
|||
const result = await runInlineTest({
|
||||
...playwrightConfig({
|
||||
snapshotPathTemplate: '__screenshots__/{testFilePath}/{arg}{ext}',
|
||||
use: {
|
||||
pageSnapshot: 'off',
|
||||
}
|
||||
}),
|
||||
'a.spec.js': `
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
|
|
@ -234,11 +234,13 @@ export interface PlaywrightWorkerOptions {
|
|||
launchOptions: Omit<LaunchOptions, 'tracesDir'>;
|
||||
connectOptions: ConnectOptions | undefined;
|
||||
screenshot: ScreenshotMode | { mode: ScreenshotMode } & Pick<PageScreenshotOptions, 'fullPage' | 'omitBackground'>;
|
||||
pageSnapshot: PageSnapshotMode;
|
||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean, attachments?: boolean };
|
||||
video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize };
|
||||
}
|
||||
|
||||
export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure';
|
||||
export type PageSnapshotMode = 'off' | 'on' | 'only-on-failure';
|
||||
export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure';
|
||||
export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
|
||||
|
||||
|
|
Loading…
Reference in New Issue