From 20699c36ba82c5d65993c70fc4ed12141059513b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 5 Feb 2024 19:07:30 -0800 Subject: [PATCH] chore: simplify types handling in toHaveScreenshot (#29374) --- packages/playwright-core/src/client/page.ts | 22 +-- .../playwright-core/src/protocol/validator.ts | 36 ++-- .../src/server/dispatchers/pageDispatcher.ts | 11 +- packages/playwright-core/src/server/page.ts | 12 +- .../playwright-core/src/utils/comparators.ts | 8 +- .../src/matchers/toMatchSnapshot.ts | 176 +++++++++--------- packages/protocol/src/channels.ts | 72 ++++--- packages/protocol/src/protocol.yml | 20 +- tests/config/comparator.ts | 2 +- 9 files changed, 164 insertions(+), 195 deletions(-) diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index df03d2f229..8ef39c4994 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -62,14 +62,13 @@ type PDFOptions = Omit & path?: string, }; -type ExpectScreenshotOptions = Omit & { +export type ExpectScreenshotOptions = Omit & { expected?: Buffer, - locator?: Locator, + locator?: api.Locator, isNot: boolean, - screenshotOptions: Omit & { mask?: Locator[] } + mask?: api.Locator[], }; - export class Page extends ChannelOwner implements api.Page { private _browserContext: BrowserContext; _ownedContext: BrowserContext | undefined; @@ -547,22 +546,19 @@ export class Page extends ChannelOwner implements api.Page } async _expectScreenshot(options: ExpectScreenshotOptions): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[]}> { - const mask = options.screenshotOptions?.mask ? options.screenshotOptions?.mask.map(locator => ({ - frame: locator._frame._channel, - selector: locator._selector, + const mask = options?.mask ? options?.mask.map(locator => ({ + frame: (locator as Locator)._frame._channel, + selector: (locator as Locator)._selector, })) : undefined; const locator = options.locator ? { - frame: options.locator._frame._channel, - selector: options.locator._selector, + frame: (options.locator as Locator)._frame._channel, + selector: (options.locator as Locator)._selector, } : undefined; return await this._channel.expectScreenshot({ ...options, isNot: !!options.isNot, locator, - screenshotOptions: { - ...options.screenshotOptions, - mask, - } + mask, }); } diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 8aa42c4df7..e67f38e9c2 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -1059,26 +1059,22 @@ scheme.PageExpectScreenshotParams = tObject({ frame: tChannel(['Frame']), selector: tString, })), - comparatorOptions: tOptional(tObject({ - comparator: tOptional(tString), - maxDiffPixels: tOptional(tNumber), - maxDiffPixelRatio: tOptional(tNumber), - threshold: tOptional(tNumber), - })), - screenshotOptions: tOptional(tObject({ - fullPage: tOptional(tBoolean), - clip: tOptional(tType('Rect')), - omitBackground: tOptional(tBoolean), - caret: tOptional(tEnum(['hide', 'initial'])), - animations: tOptional(tEnum(['disabled', 'allow'])), - scale: tOptional(tEnum(['css', 'device'])), - mask: tOptional(tArray(tObject({ - frame: tChannel(['Frame']), - selector: tString, - }))), - maskColor: tOptional(tString), - style: tOptional(tString), - })), + comparator: tOptional(tString), + maxDiffPixels: tOptional(tNumber), + maxDiffPixelRatio: tOptional(tNumber), + threshold: tOptional(tNumber), + fullPage: tOptional(tBoolean), + clip: tOptional(tType('Rect')), + omitBackground: tOptional(tBoolean), + caret: tOptional(tEnum(['hide', 'initial'])), + animations: tOptional(tEnum(['disabled', 'allow'])), + scale: tOptional(tEnum(['css', 'device'])), + mask: tOptional(tArray(tObject({ + frame: tChannel(['Frame']), + selector: tString, + }))), + maskColor: tOptional(tString), + style: tOptional(tString), }); scheme.PageExpectScreenshotResult = tObject({ diff: tOptional(tBinary), diff --git a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts index 775fd515f0..fb2e1f0468 100644 --- a/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/pageDispatcher.ts @@ -179,7 +179,7 @@ export class PageDispatcher extends Dispatcher { - const mask: { frame: Frame, selector: string }[] = (params.screenshotOptions?.mask || []).map(({ frame, selector }) => ({ + const mask: { frame: Frame, selector: string }[] = (params.mask || []).map(({ frame, selector }) => ({ frame: (frame as FrameDispatcher)._object, selector, })); @@ -190,14 +190,7 @@ export class PageDispatcher extends Dispatcher { const locator = options.locator; const rafrafScreenshot = locator ? async (progress: Progress, timeout: number) => { - return await locator.frame.rafrafTimeoutScreenshotElementWithProgress(progress, locator.selector, timeout, options.screenshotOptions || {}); + return await locator.frame.rafrafTimeoutScreenshotElementWithProgress(progress, locator.selector, timeout, options || {}); } : async (progress: Progress, timeout: number) => { await this.performLocatorHandlersCheckpoint(progress); await this.mainFrame().rafrafTimeout(timeout); - return await this._screenshotter.screenshotPage(progress, options.screenshotOptions || {}); + return await this._screenshotter.screenshotPage(progress, options || {}); }; const comparator = getComparator('image/png'); @@ -549,7 +547,7 @@ export class Page extends SdkObject { if (!options.expected && options.isNot) return { errorMessage: '"not" matcher requires expected result' }; try { - const format = validateScreenshotOptions(options.screenshotOptions || {}); + const format = validateScreenshotOptions(options || {}); if (format !== 'png') throw new Error('Only PNG screenshots are supported'); } catch (error) { @@ -562,7 +560,7 @@ export class Page extends SdkObject { diff?: Buffer, } | undefined = undefined; const areEqualScreenshots = (actual: Buffer | undefined, expected: Buffer | undefined, previous: Buffer | undefined) => { - const comparatorResult = actual && expected ? comparator(actual, expected, options.comparatorOptions) : undefined; + const comparatorResult = actual && expected ? comparator(actual, expected, options) : undefined; if (comparatorResult !== undefined && !!comparatorResult === !!options.isNot) return true; if (comparatorResult) diff --git a/packages/playwright-core/src/utils/comparators.ts b/packages/playwright-core/src/utils/comparators.ts index 89b5cb2976..ef63b2d376 100644 --- a/packages/playwright-core/src/utils/comparators.ts +++ b/packages/playwright-core/src/utils/comparators.ts @@ -21,7 +21,7 @@ import { compare } from '../image_tools/compare'; const { diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL } = require('../third_party/diff_match_patch'); import { PNG } from '../utilsBundle'; -export type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxDiffPixelRatio?: number, _comparator?: string }; +export type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxDiffPixelRatio?: number, comparator?: string }; export type ComparatorResult = { diff?: Buffer; errorMessage: string; } | null; export type Comparator = (actualBuffer: Buffer | string, expectedBuffer: Buffer, options?: any) => ComparatorResult; @@ -65,18 +65,18 @@ function compareImages(mimeType: string, actualBuffer: Buffer | string, expected } const diff = new PNG({ width: size.width, height: size.height }); let count; - if (options._comparator === 'ssim-cie94') { + if (options.comparator === 'ssim-cie94') { count = compare(expected.data, actual.data, diff.data, size.width, size.height, { // All ΔE* formulae are originally designed to have the difference of 1.0 stand for a "just noticeable difference" (JND). // See https://en.wikipedia.org/wiki/Color_difference#CIELAB_%CE%94E* maxColorDeltaE94: 1.0, }); - } else if ((options._comparator ?? 'pixelmatch') === 'pixelmatch') { + } else if ((options.comparator ?? 'pixelmatch') === 'pixelmatch') { count = pixelmatch(expected.data, actual.data, diff.data, size.width, size.height, { threshold: options.threshold ?? 0.2, }); } else { - throw new Error(`Configuration specifies unknown comparator "${options._comparator}"`); + throw new Error(`Configuration specifies unknown comparator "${options.comparator}"`); } const maxDiffPixels1 = options.maxDiffPixels; diff --git a/packages/playwright/src/matchers/toMatchSnapshot.ts b/packages/playwright/src/matchers/toMatchSnapshot.ts index 0a913b24dd..80e602f5ad 100644 --- a/packages/playwright/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchSnapshot.ts @@ -15,12 +15,10 @@ */ import type { Locator, Page } from 'playwright-core'; -import type { Page as PageEx } from 'playwright-core/lib/client/page'; -import type { Locator as LocatorEx } from 'playwright-core/lib/client/locator'; +import type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page'; import { currentTestInfo, currentExpectTimeout } from '../common/globals'; import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils'; import { getComparator, sanitizeForFilePath, zones } from 'playwright-core/lib/utils'; -import type { PageScreenshotOptions } from 'playwright-core/types/types'; import { addSuffixToFilePath, trimLongString, callLogText, @@ -32,6 +30,7 @@ import { mime } from 'playwright-core/lib/utilsBundle'; import type { TestInfoImpl } from '../worker/testInfo'; import type { ExpectMatcherContext } from './expect'; import type { MatcherResult } from './matcherHint'; +import type { FullProjectInternal } from '../common/config'; type NameOrSegments = string | string[]; const snapshotNamesSymbol = Symbol('snapshotNames'); @@ -43,7 +42,36 @@ type SnapshotNames = { type ImageMatcherResult = MatcherResult & { diff?: string }; -class SnapshotHelper { +type ToHaveScreenshotConfigOptions = NonNullable['toHaveScreenshot']> & { + _comparator?: string; +}; + +type ToHaveScreenshotOptions = ToHaveScreenshotConfigOptions & { + clip?: { + x: number; + y: number; + width: number; + height: number; + }; + fullPage?: boolean; + mask?: Array; + maskColor?: string; + omitBackground?: boolean; + timeout?: number; +}; + +// Keep in sync with above (begin). +const NonConfigProperties: (keyof ToHaveScreenshotOptions)[] = [ + 'clip', + 'fullPage', + 'mask', + 'maskColor', + 'omitBackground', + 'timeout', +]; +// Keep in sync with above (end). + +class SnapshotHelper { readonly testInfo: TestInfoImpl; readonly snapshotName: string; readonly legacyExpectedPath: string; @@ -54,9 +82,8 @@ class SnapshotHelper { readonly mimeType: string; readonly kind: 'Screenshot'|'Snapshot'; readonly updateSnapshots: 'all' | 'none' | 'missing'; - readonly comparatorOptions: ImageComparatorOptions; readonly comparator: Comparator; - readonly allOptions: T; + readonly options: Omit & { comparator?: string }; readonly matcherName: string; readonly locator: Locator | undefined; @@ -66,19 +93,18 @@ class SnapshotHelper { locator: Locator | undefined, snapshotPathResolver: (...pathSegments: string[]) => string, anonymousSnapshotExtension: string, - configOptions: ImageComparatorOptions, - nameOrOptions: NameOrSegments | { name?: NameOrSegments } & T, - optOptions: T, + configOptions: ToHaveScreenshotConfigOptions, + nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions, + optOptions: ToHaveScreenshotOptions, ) { - let options: T; let name: NameOrSegments | undefined; if (Array.isArray(nameOrOptions) || typeof nameOrOptions === 'string') { name = nameOrOptions; - options = optOptions; + this.options = { ...optOptions }; } else { name = nameOrOptions.name; - options = { ...nameOrOptions }; - delete (options as any).name; + this.options = { ...nameOrOptions }; + delete (this.options as any).name; } let snapshotNames = (testInfo as any)[snapshotNamesSymbol] as SnapshotNames; @@ -116,15 +142,24 @@ class SnapshotHelper { } } - options = { - ...configOptions, - ...options, + const filteredConfigOptions = { ...configOptions }; + for (const prop of NonConfigProperties) + delete (filteredConfigOptions as any)[prop]; + this.options = { + ...filteredConfigOptions, + ...this.options, }; - if (options.maxDiffPixels !== undefined && options.maxDiffPixels < 0) + // While comparator is not a part of the public API, it is translated here. + if ((this.options as any)._comparator) { + this.options.comparator = (this.options as any)._comparator; + delete (this.options as any)._comparator; + } + + if (this.options.maxDiffPixels !== undefined && this.options.maxDiffPixels < 0) throw new Error('`maxDiffPixels` option value must be non-negative integer'); - if (options.maxDiffPixelRatio !== undefined && (options.maxDiffPixelRatio < 0 || options.maxDiffPixelRatio > 1)) + if (this.options.maxDiffPixelRatio !== undefined && (this.options.maxDiffPixelRatio < 0 || this.options.maxDiffPixelRatio > 1)) throw new Error('`maxDiffPixelRatio` option value must be between 0 and 1'); // sanitizes path if string @@ -145,13 +180,6 @@ class SnapshotHelper { this.comparator = getComparator(this.mimeType); this.testInfo = testInfo; - this.allOptions = options; - this.comparatorOptions = { - maxDiffPixels: options.maxDiffPixels, - maxDiffPixelRatio: options.maxDiffPixelRatio, - threshold: options.threshold, - _comparator: options._comparator, - }; this.kind = this.mimeType.startsWith('image/') ? 'Screenshot' : 'Snapshot'; } @@ -284,7 +312,7 @@ export function toMatchSnapshot( if (this.isNot) { if (!fs.existsSync(helper.snapshotPath)) return helper.handleMissingNegated(); - const isDifferent = !!helper.comparator(received, fs.readFileSync(helper.snapshotPath), helper.comparatorOptions); + const isDifferent = !!helper.comparator(received, fs.readFileSync(helper.snapshotPath), helper.options); return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated(); } @@ -292,7 +320,7 @@ export function toMatchSnapshot( return helper.handleMissing(received); const expected = fs.readFileSync(helper.snapshotPath); - const result = helper.comparator(received, expected, helper.comparatorOptions); + const result = helper.comparator(received, expected, helper.options); if (!result) return helper.handleMatching(); @@ -306,11 +334,9 @@ export function toMatchSnapshot( return helper.handleDifferent(received, expected, undefined, result.diff, result.errorMessage, undefined); } -type HaveScreenshotOptions = ImageComparatorOptions & Omit & { stylePath?: string | string[] }; - export function toHaveScreenshotStepTitle( - nameOrOptions: NameOrSegments | { name?: NameOrSegments } & HaveScreenshotOptions = {}, - optOptions: HaveScreenshotOptions = {} + nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {}, + optOptions: ToHaveScreenshotOptions = {} ): string { let name: NameOrSegments | undefined; if (typeof nameOrOptions === 'object' && !Array.isArray(nameOrOptions)) @@ -323,8 +349,8 @@ export function toHaveScreenshotStepTitle( export async function toHaveScreenshot( this: ExpectMatcherContext, pageOrLocator: Page | Locator, - nameOrOptions: NameOrSegments | { name?: NameOrSegments } & HaveScreenshotOptions = {}, - optOptions: HaveScreenshotOptions = {} + nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {}, + optOptions: ToHaveScreenshotOptions = {} ): Promise> { const testInfo = currentTestInfo(); if (!testInfo) @@ -334,47 +360,45 @@ export async function toHaveScreenshot( return { pass: !this.isNot, message: () => '', name: 'toHaveScreenshot', expected: nameOrOptions }; expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot'); - const [page, locator] = pageOrLocator.constructor.name === 'Page' ? [(pageOrLocator as PageEx), undefined] : [(pageOrLocator as Locator).page() as PageEx, pageOrLocator as LocatorEx]; - const config = (testInfo._projectInternal.expect as any)?.toHaveScreenshot; + const [page, locator] = pageOrLocator.constructor.name === 'Page' ? [(pageOrLocator as PageEx), undefined] : [(pageOrLocator as Locator).page() as PageEx, pageOrLocator as Locator]; + const configOptions = testInfo._projectInternal.expect?.toHaveScreenshot || {}; const snapshotPathResolver = testInfo.snapshotPath.bind(testInfo); const helper = new SnapshotHelper( testInfo, 'toHaveScreenshot', locator, snapshotPathResolver, 'png', - { - _comparator: config?._comparator, - maxDiffPixels: config?.maxDiffPixels, - maxDiffPixelRatio: config?.maxDiffPixelRatio, - threshold: config?.threshold, - }, - nameOrOptions, optOptions); + configOptions, nameOrOptions, optOptions); if (!helper.snapshotPath.toLowerCase().endsWith('.png')) throw new Error(`Screenshot name "${path.basename(helper.snapshotPath)}" must have '.png' extension`); expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot'); return await zones.preserve(async () => { // Loading from filesystem resets zones. - const style = await loadScreenshotStyles(helper.allOptions.stylePath || config?.stylePath); - return toHaveScreenshotContinuation.call(this, helper, page, locator, config, style); + const style = await loadScreenshotStyles(helper.options.stylePath); + return toHaveScreenshotContinuation.call(this, helper, page, locator, style); }); } async function toHaveScreenshotContinuation( this: ExpectMatcherContext, - helper: SnapshotHelper, + helper: SnapshotHelper, page: PageEx, - locator: LocatorEx | undefined, - config?: HaveScreenshotOptions, + locator: Locator | undefined, style?: string) { - const screenshotOptions: any = { - animations: config?.animations ?? 'disabled', - scale: config?.scale ?? 'css', - caret: config?.caret ?? 'hide', + const expectScreenshotOptions: ExpectScreenshotOptions = { + locator, + animations: helper.options.animations ?? 'disabled', + caret: helper.options.caret ?? 'hide', + clip: helper.options.clip, + fullPage: helper.options.fullPage, + mask: helper.options.mask, + maskColor: helper.options.maskColor, + omitBackground: helper.options.omitBackground, + scale: helper.options.scale ?? 'css', style, - ...helper.allOptions, - mask: (helper.allOptions.mask || []) as LocatorEx[], - maskColor: helper.allOptions.maskColor, - name: undefined, - threshold: undefined, - maxDiffPixels: undefined, - maxDiffPixelRatio: undefined, + isNot: !!this.isNot, + timeout: currentExpectTimeout(helper.options), + comparator: helper.options.comparator, + maxDiffPixels: helper.options.maxDiffPixels, + maxDiffPixelRatio: helper.options.maxDiffPixelRatio, + threshold: helper.options.threshold, }; const hasSnapshot = fs.existsSync(helper.snapshotPath); @@ -385,17 +409,8 @@ async function toHaveScreenshotContinuation( // Having `errorMessage` means we timed out while waiting // for screenshots not to match, so screenshots // are actually the same in the end. - const isDifferent = !(await page._expectScreenshot({ - expected: await fs.promises.readFile(helper.snapshotPath), - isNot: true, - locator, - comparatorOptions: { - ...helper.comparatorOptions, - comparator: helper.comparatorOptions._comparator, - }, - screenshotOptions, - timeout: currentExpectTimeout(helper.allOptions), - })).errorMessage; + expectScreenshotOptions.expected = await fs.promises.readFile(helper.snapshotPath); + const isDifferent = !(await page._expectScreenshot(expectScreenshotOptions)).errorMessage; return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated(); } @@ -405,15 +420,7 @@ async function toHaveScreenshotContinuation( if (!hasSnapshot) { // Regenerate a new screenshot by waiting until two screenshots are the same. - const timeout = currentExpectTimeout(helper.allOptions); - const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot({ - expected: undefined, - isNot: false, - locator, - comparatorOptions: { ...helper.comparatorOptions, comparator: helper.comparatorOptions._comparator }, - screenshotOptions, - timeout, - }); + const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions); // We tried re-generating new snapshot but failed. // This can be due to e.g. spinning animation, so we want to show it as a diff. if (errorMessage) @@ -427,15 +434,8 @@ async function toHaveScreenshotContinuation( // - snapshot exists // - regular matcher (i.e. not a `.not`) // - perhaps an 'all' flag to update non-matching screenshots - const expected = await fs.promises.readFile(helper.snapshotPath); - const { actual, diff, errorMessage, log } = await page._expectScreenshot({ - expected, - isNot: false, - locator, - comparatorOptions: { ...helper.comparatorOptions, comparator: helper.comparatorOptions._comparator }, - screenshotOptions, - timeout: currentExpectTimeout(helper.allOptions), - }); + expectScreenshotOptions.expected = await fs.promises.readFile(helper.snapshotPath); + const { actual, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions); if (!errorMessage) return helper.handleMatching(); @@ -448,7 +448,7 @@ async function toHaveScreenshotContinuation( return helper.createMatcherResult(helper.snapshotPath + ' running with --update-snapshots, writing actual.', true); } - return helper.handleDifferent(actual, expected, undefined, diff, errorMessage, log); + return helper.handleDifferent(actual, expectScreenshotOptions.expected, undefined, diff, errorMessage, log); } function writeFileSync(aPath: string, content: Buffer | string) { diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index 21a4b0e5cd..37811f4d6c 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -1939,26 +1939,22 @@ export type PageExpectScreenshotParams = { frame: FrameChannel, selector: string, }, - comparatorOptions?: { - comparator?: string, - maxDiffPixels?: number, - maxDiffPixelRatio?: number, - threshold?: number, - }, - screenshotOptions?: { - fullPage?: boolean, - clip?: Rect, - omitBackground?: boolean, - caret?: 'hide' | 'initial', - animations?: 'disabled' | 'allow', - scale?: 'css' | 'device', - mask?: { - frame: FrameChannel, - selector: string, - }[], - maskColor?: string, - style?: string, - }, + comparator?: string, + maxDiffPixels?: number, + maxDiffPixelRatio?: number, + threshold?: number, + fullPage?: boolean, + clip?: Rect, + omitBackground?: boolean, + caret?: 'hide' | 'initial', + animations?: 'disabled' | 'allow', + scale?: 'css' | 'device', + mask?: { + frame: FrameChannel, + selector: string, + }[], + maskColor?: string, + style?: string, }; export type PageExpectScreenshotOptions = { expected?: Binary, @@ -1967,26 +1963,22 @@ export type PageExpectScreenshotOptions = { frame: FrameChannel, selector: string, }, - comparatorOptions?: { - comparator?: string, - maxDiffPixels?: number, - maxDiffPixelRatio?: number, - threshold?: number, - }, - screenshotOptions?: { - fullPage?: boolean, - clip?: Rect, - omitBackground?: boolean, - caret?: 'hide' | 'initial', - animations?: 'disabled' | 'allow', - scale?: 'css' | 'device', - mask?: { - frame: FrameChannel, - selector: string, - }[], - maskColor?: string, - style?: string, - }, + comparator?: string, + maxDiffPixels?: number, + maxDiffPixelRatio?: number, + threshold?: number, + fullPage?: boolean, + clip?: Rect, + omitBackground?: boolean, + caret?: 'hide' | 'initial', + animations?: 'disabled' | 'allow', + scale?: 'css' | 'device', + mask?: { + frame: FrameChannel, + selector: string, + }[], + maskColor?: string, + style?: string, }; export type PageExpectScreenshotResult = { diff?: Binary, diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index dde01b6c9a..feeda1c317 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -1367,19 +1367,13 @@ Page: properties: frame: Frame selector: string - comparatorOptions: - type: object? - properties: - comparator: string? - maxDiffPixels: number? - maxDiffPixelRatio: number? - threshold: number? - screenshotOptions: - type: object? - properties: - fullPage: boolean? - clip: Rect? - $mixin: CommonScreenshotOptions + comparator: string? + maxDiffPixels: number? + maxDiffPixelRatio: number? + threshold: number? + fullPage: boolean? + clip: Rect? + $mixin: CommonScreenshotOptions returns: diff: binary? errorMessage: string? diff --git a/tests/config/comparator.ts b/tests/config/comparator.ts index 4a87bf4bb5..3376da3e80 100644 --- a/tests/config/comparator.ts +++ b/tests/config/comparator.ts @@ -22,5 +22,5 @@ type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxD export function comparePNGs(actual: Buffer, expected: Buffer, options: ImageComparatorOptions = {}): ComparatorResult { // Strict threshold by default in our tests. - return pngComparator(actual, expected, { _comparator: 'ssim-cie94', threshold: 0, ...options }); + return pngComparator(actual, expected, { comparator: 'ssim-cie94', threshold: 0, ...options }); }