diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 5d81b8f4a7..ad1ca98b1a 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -1004,7 +1004,6 @@ Property value. ## async method: LocatorAssertions.toHaveScreenshot * langs: js -* experimental Ensures that [Locator] resolves to a given screenshot. This function will re-take screenshots until it matches with the saved expectation. diff --git a/docs/src/api/class-pageassertions.md b/docs/src/api/class-pageassertions.md index 10702a3d85..835bcfbf4c 100644 --- a/docs/src/api/class-pageassertions.md +++ b/docs/src/api/class-pageassertions.md @@ -116,7 +116,6 @@ Expected substring or RegExp. ## async method: PageAssertions.toHaveScreenshot * langs: js -* experimental Ensures that the page resolves to a given screenshot. This function will re-take screenshots until it matches with the saved expectation. diff --git a/docs/src/test-api/class-testconfig.md b/docs/src/test-api/class-testconfig.md index 5d5ed38180..3682646cd6 100644 --- a/docs/src/test-api/class-testconfig.md +++ b/docs/src/test-api/class-testconfig.md @@ -36,7 +36,7 @@ export default config; ## property: TestConfig.expect - type: ?<[Object]> - `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms. - - `toHaveScreenshot` ?e<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot`] method. + - `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot`] method. - `threshold` ?<[float]> an acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same pixel in compared images, between zero (strict) and one (lax). Defaults to `0.2`. - `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default. - `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. diff --git a/docs/src/test-api/class-testproject.md b/docs/src/test-api/class-testproject.md index 0279681da8..5bf818920a 100644 --- a/docs/src/test-api/class-testproject.md +++ b/docs/src/test-api/class-testproject.md @@ -107,7 +107,7 @@ export default config; ## property: TestProject.expect - type: ?<[Object]> - `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms. - - `toHaveScreenshot` ?e<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot`] method. + - `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot`] method. - `threshold` ?<[float]> an acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same pixel in compared images, between zero (strict) and one (lax). Defaults to `0.2`. - `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default. - `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. diff --git a/packages/playwright-test/src/matchers/toMatchSnapshot.ts b/packages/playwright-test/src/matchers/toMatchSnapshot.ts index ba01e004c5..52da1c28ae 100644 --- a/packages/playwright-test/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright-test/src/matchers/toMatchSnapshot.ts @@ -289,13 +289,11 @@ export async function toHaveScreenshot( nameOrOptions: NameOrSegments | { name?: NameOrSegments } & HaveScreenshotOptions = {}, optOptions: HaveScreenshotOptions = {} ): Promise { - if (!process.env.PLAYWRIGHT_EXPERIMENTAL_FEATURES) - throw new Error(`To use the experimental method "toHaveScreenshot", set PLAYWRIGHT_EXPERIMENTAL_FEATURES=1 enviroment variable.`); const testInfo = currentTestInfo(); if (!testInfo) throw new Error(`toHaveScreenshot() must be called during the test`); const config = (testInfo.project._expect as any)?.toHaveScreenshot; - const snapshotPathResolver = process.env.PLAYWRIGHT_EXPERIMENTAL_FEATURES && config?._useScreenshotsDir + const snapshotPathResolver = process.env.PWTEST_USE_SCREENSHOTS_DIR_FOR_TEST ? testInfo._screenshotPath.bind(testInfo) : testInfo.snapshotPath.bind(testInfo); const helper = new SnapshotHelper( diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index 785601d556..53bbb918ff 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -501,6 +501,47 @@ interface TestConfig { */ timeout?: number; + /** + * Configuration for the + * [pageAssertions.toHaveScreenshot([options])](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot) + * method. + */ + toHaveScreenshot?: { + /** + * an acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same + * pixel in compared images, between zero (strict) and one (lax). Defaults to `0.2`. + */ + threshold?: number; + + /** + * an acceptable amount of pixels that could be different, unset by default. + */ + maxDiffPixels?: number; + + /** + * an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. + */ + maxDiffPixelRatio?: number; + + /** + * See `animations` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults + * to `"disable"`. + */ + animations?: "allow"|"disable"; + + /** + * See `caret` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults to + * `"hide"`. + */ + caret?: "hide"|"initial"; + + /** + * See `scale` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults to + * `"css"`. + */ + scale?: "css"|"device"; + }; + /** * Configuration for the * [screenshotAssertions.toMatchSnapshot(name[, options])](https://playwright.dev/docs/api/class-screenshotassertions#screenshot-assertions-to-match-snapshot-1) @@ -3303,6 +3344,81 @@ interface LocatorAssertions { timeout?: number; }): Promise; + /** + * Ensures that [Locator] resolves to a given screenshot. This function will re-take screenshots until it matches with the + * saved expectation. + * + * If there's no expectation yet, it will wait until two consecutive screenshots yield the same result, and save the last + * one as an expectation. + * + * ```js + * const locator = page.locator('button'); + * await expect(locator).toHaveScreenshot(); + * ``` + * + * @param options + */ + toHaveScreenshot(options?: { + /** + * When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event. + * - infinite animations are canceled to initial state, and then played over after the screenshot. + * + * Defaults to `"allow"` that leaves animations untouched. + */ + animations?: "disabled"|"allow"; + + /** + * When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be changed. + * Defaults to `"hide"`. + */ + caret?: "hide"|"initial"; + + /** + * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlayed with a pink box + * `#FF00FF` that completely covers its bounding box. + */ + mask?: Array; + + /** + * An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1`. Default is + * configurable with `TestConfig.expect`. Unset by default. + */ + maxDiffPixelRatio?: number; + + /** + * An acceptable amount of pixels that could be different, default is configurable with `TestConfig.expect`. Default is + * configurable with `TestConfig.expect`. Unset by default. + */ + maxDiffPixels?: number; + + /** + * Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. + * Defaults to `false`. + */ + omitBackground?: boolean; + + /** + * When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will + * keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so screenhots of + * high-dpi devices will be twice as large or even larger. Defaults to `"device"`. + */ + scale?: "css"|"device"; + + /** + * An acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same + * pixel in compared images, between zero (strict) and one (lax), default is configurable with `TestConfig.expect`. + * Defaults to `0.2`. + */ + threshold?: number; + + /** + * Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`. + */ + timeout?: number; + }): Promise; + /** * Ensures the [Locator] points to an element with the given text. You can use regular expressions for the value as well. * @@ -3382,6 +3498,111 @@ interface PageAssertions { */ not: PageAssertions; + /** + * Ensures that the page resolves to a given screenshot. This function will re-take screenshots until it matches with the + * saved expectation. + * + * If there's no expectation yet, it will wait until two consecutive screenshots yield the same result, and save the last + * one as an expectation. + * + * ```js + * await expect(page).toHaveScreenshot(); + * ``` + * + * @param options + */ + toHaveScreenshot(options?: { + /** + * When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different treatment + * depending on their duration: + * - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event. + * - infinite animations are canceled to initial state, and then played over after the screenshot. + * + * Defaults to `"allow"` that leaves animations untouched. + */ + animations?: "disabled"|"allow"; + + /** + * When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be changed. + * Defaults to `"hide"`. + */ + caret?: "hide"|"initial"; + + /** + * An object which specifies clipping of the resulting image. Should have the following fields: + */ + clip?: { + /** + * x-coordinate of top-left corner of clip area + */ + x: number; + + /** + * y-coordinate of top-left corner of clip area + */ + y: number; + + /** + * width of clipping area + */ + width: number; + + /** + * height of clipping area + */ + height: number; + }; + + /** + * When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to + * `false`. + */ + fullPage?: boolean; + + /** + * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlayed with a pink box + * `#FF00FF` that completely covers its bounding box. + */ + mask?: Array; + + /** + * An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1`. Default is + * configurable with `TestConfig.expect`. Unset by default. + */ + maxDiffPixelRatio?: number; + + /** + * An acceptable amount of pixels that could be different, default is configurable with `TestConfig.expect`. Default is + * configurable with `TestConfig.expect`. Unset by default. + */ + maxDiffPixels?: number; + + /** + * Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. + * Defaults to `false`. + */ + omitBackground?: boolean; + + /** + * When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this will + * keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so screenhots of + * high-dpi devices will be twice as large or even larger. Defaults to `"device"`. + */ + scale?: "css"|"device"; + + /** + * An acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same + * pixel in compared images, between zero (strict) and one (lax), default is configurable with `TestConfig.expect`. + * Defaults to `0.2`. + */ + threshold?: number; + + /** + * Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`. + */ + timeout?: number; + }): Promise; + /** * Ensures the page has the given title. * @@ -3614,6 +3835,47 @@ interface TestProject { */ timeout?: number; + /** + * Configuration for the + * [pageAssertions.toHaveScreenshot([options])](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot) + * method. + */ + toHaveScreenshot?: { + /** + * an acceptable perceived color difference in the [YIQ color space](https://en.wikipedia.org/wiki/YIQ) between the same + * pixel in compared images, between zero (strict) and one (lax). Defaults to `0.2`. + */ + threshold?: number; + + /** + * an acceptable amount of pixels that could be different, unset by default. + */ + maxDiffPixels?: number; + + /** + * an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default. + */ + maxDiffPixelRatio?: number; + + /** + * See `animations` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults + * to `"disable"`. + */ + animations?: "allow"|"disable"; + + /** + * See `caret` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults to + * `"hide"`. + */ + caret?: "hide"|"initial"; + + /** + * See `scale` in [page.screenshot([options])](https://playwright.dev/docs/api/class-page#page-screenshot). Defaults to + * `"css"`. + */ + scale?: "css"|"device"; + }; + /** * Configuration for the * [screenshotAssertions.toMatchSnapshot(name[, options])](https://playwright.dev/docs/api/class-screenshotassertions#screenshot-assertions-to-match-snapshot-1) diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index ecbc0593a9..3d4549148e 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -180,9 +180,8 @@ test('should include multiple image diffs', async ({ runInlineTest, page, showRe const result = await runInlineTest({ 'playwright.config.ts': ` - process.env.PLAYWRIGHT_EXPERIMENTAL_FEATURES = 1; + process.env.PWTEST_USE_SCREENSHOTS_DIR_FOR_TEST = '1'; module.exports = { - expect: { toHaveScreenshot: { _useScreenshotsDir: true } }, screenshotsDir: '__screenshots__', use: { viewport: { width: ${IMG_WIDTH}, height: ${IMG_HEIGHT} }} }; diff --git a/tests/playwright-test/to-have-screenshot.spec.ts b/tests/playwright-test/to-have-screenshot.spec.ts index 194a204a60..f1283d279b 100644 --- a/tests/playwright-test/to-have-screenshot.spec.ts +++ b/tests/playwright-test/to-have-screenshot.spec.ts @@ -99,10 +99,9 @@ test('should fail with proper error when unsupported argument is given', async ( test('should use match snapshot paths by default', async ({ runInlineTest }, testInfo) => { const result = await runInlineTest({ - // The helper function `playwrightConfig` injects a `_useScreenshotsDir` flag. + // The helper function `playwrightConfig` set PWTEST_USE_SCREENSHOTS_DIR_FOR_TEST env variable. // Provide default config manually instead. 'playwright.config.js': ` - process.env.PLAYWRIGHT_EXPERIMENTAL_FEATURES = '1'; module.exports = {}; `, 'a.spec.js': ` @@ -941,12 +940,9 @@ test('should update expectations with retries', async ({ runInlineTest }, testIn }); function playwrightConfig(obj: any) { - obj.expect ??= {}; - obj.expect.toHaveScreenshot ??= {}; - obj.expect.toHaveScreenshot._useScreenshotsDir ??= true; return { 'playwright.config.js': ` - process.env.PLAYWRIGHT_EXPERIMENTAL_FEATURES = '1'; + process.env.PWTEST_USE_SCREENSHOTS_DIR_FOR_TEST = '1'; module.exports = ${JSON.stringify(obj, null, 2)} `, };