@cappa/core
Version:
Core Playwright screenshot functionality for Cappa
364 lines (363 loc) • 10.5 kB
TypeScript
import { Browser, BrowserContext, Locator, Page } from "playwright-core";
import { Logger } from "@cappa/logger";
//#region src/compare.d.ts
interface CompareResult {
numDiffPixels: number;
totalPixels: number;
percentDifference: number;
diffBuffer?: Buffer;
passed: boolean;
error?: string;
differentSizes: boolean;
}
//#endregion
//#region src/filesystem.d.ts
/**
* Class for interacting with the local file system to store the screenshots.
*/
declare class ScreenshotFileSystem {
private readonly actualDir;
private readonly expectedDir;
private readonly diffDir;
constructor(outputDir: string);
clearActual(): void;
clearDiff(): void;
clearActualAndDiff(): void;
/**
* Approve a screenshot based on its actual file path.
* @param actualFilePath - The path to the actual screenshot file.
* @returns The paths to the actual, expected, and diff screenshot files.
*/
approveFromActualPath(actualFilePath: string): {
actualPath: string;
expectedPath: string;
diffPath: string;
};
/**
* Approve a screenshot based on its name.
* @param name - The name of the screenshot. Can include '.png' extension.
* @returns The paths to the actual, expected, and diff screenshot files.
*/
approveByName(name: string): {
actualPath: string;
expectedPath: string;
diffPath: string;
};
/**
* Approve a screenshot based on a relative path.
* @param relativePath - The relative path to the screenshot.
* @returns The paths to the actual, expected, and diff screenshot files.
*/
private approveRelative;
/**
* Ensure the parent directory of a file exists. If not, it creates it.
* @param filePath - The path to the file.
*/
private ensureParentDir;
/**
* Remove a directory and all its contents.
* @param dir - The path to the directory.
*/
private removeDir;
/**
* Get the actual directory path
*/
getActualDir(): string;
/**
* Get the expected directory path
*/
getExpectedDir(): string;
/**
* Get the diff directory path
*/
getDiffDir(): string;
/**
* Get the path to an actual screenshot file
*/
getActualFilePath(filename: string): string;
/**
* Get the path to an expected screenshot file
*/
getExpectedFilePath(filename: string): string;
/**
* Get the path to a diff screenshot file
*/
getDiffFilePath(filename: string): string;
/**
* Write a file to the actual directory
*/
writeActualFile(filename: string, data: Buffer): void;
/**
* Write a file to the diff directory
*/
writeDiffFile(filename: string, data: Buffer): void;
/**
* Check if an expected file exists
*/
hasExpectedFile(filename: string): boolean;
/**
* Read an expected file
*/
readExpectedFile(filename: string): Buffer;
/**
* Resolve the actual path of a screenshot file.
* @param filePath - The path to the screenshot file.
* @returns The actual path of the screenshot file.
*/
private resolveActualPath;
}
//#endregion
//#region src/screenshot.d.ts
interface ScreenshotCaptureDetails {
filename: string;
filepath?: string;
comparisonResult?: CompareResult;
diffImagePath?: string;
skipped?: boolean;
}
interface ScreenshotVariantCaptureDetails extends ScreenshotCaptureDetails {
id: string;
label?: string;
}
interface ScreenshotCaptureResult {
base: ScreenshotCaptureDetails;
variants: ScreenshotVariantCaptureDetails[];
}
interface ScreenshotCaptureExtras {
saveDiffImage?: boolean;
diffImageFilename?: string;
variants?: Record<string, {
saveDiffImage?: boolean;
diffImageFilename?: string;
}>;
}
declare class ScreenshotTool {
browserType: "chromium" | "firefox" | "webkit";
headless: boolean;
viewport: {
width: number;
height: number;
};
outputDir: string;
browser: Browser | null;
context: BrowserContext | null;
page: Page | null;
concurrency: number;
contexts: BrowserContext[];
pages: Page[];
diff: DiffConfig;
logger: Logger;
retries: number;
filesystem: ScreenshotFileSystem;
constructor(options: {
browserType?: "chromium" | "firefox" | "webkit";
headless?: boolean;
viewport?: {
width: number;
height: number;
};
outputDir?: string;
diff?: DiffConfig;
retries?: number;
concurrency?: number;
});
/**
* Initialize playwright and page
*/
init(): Promise<void>;
/**
* Closes browser
* If not closed, the process will not exit
*/
close(): Promise<void>;
/**
* Navigates to a URL with "domcontentloaded" waitUntil
*/
goTo(page: Page, url: string): Promise<void>;
/**
* Takes a screenshot of the page
*/
takeScreenshot(page: Page, filename: string, options: ScreenshotSettings): Promise<string | undefined>;
/**
* Sets the viewport size and executes the action, ensuring the original viewport is restored
* even if the action throws an error.
*/
private withViewport;
/**
* Takes a screenshot and returns the buffer (for comparison purposes)
*/
takeScreenshotBuffer(page: Page, options: ScreenshotSettings): Promise<Buffer>;
takeScreenshotWithComparison(page: Page, filename: string, referenceImage: Buffer, options: ScreenshotSettings & {
saveDiffImage?: boolean;
diffImageFilename?: string;
}): Promise<{
screenshotPath: string;
comparisonResult: CompareResult;
diffImagePath?: string;
}>;
retryScreenshot(page: Page, referenceImage: Buffer, options: ScreenshotSettings): Promise<{
screenshotPath: Buffer<ArrayBufferLike>;
comparisonResult: CompareResult;
passed: boolean;
} | {
screenshotPath: null;
comparisonResult: null;
passed: boolean;
}>;
getVariantFilename(filename: string, variant: ScreenshotVariant): string;
capture(page: Page, filename: string, options: ScreenshotOptions, extras?: ScreenshotCaptureExtras): Promise<ScreenshotCaptureResult>;
/**
* Gets the exponential backoff delay
*/
getIncBackoffDelay(i: number, delay: number): number;
/**
* Get a page from the pool by index
*/
getPageFromPool(index: number): Page;
}
//#endregion
//#region src/plugin.d.ts
/**
* Plugin task interface
*/
type PluginTask<TData = any> = {
id: string;
url: string;
data?: TData;
};
/**
* Plugin function type definition (legacy)
*/
type PluginFunction = (screenshotTool: ScreenshotTool) => Promise<any[]>;
/**
* Plugin definition interface
*/
type PluginDef<TResult = any, TContext = any, TData = any> = {
name: string;
description: string;
discover: (screenshotTool: ScreenshotTool) => Promise<PluginTask<TData>[]>;
execute: (task: PluginTask<TData>, page: Page, screenshotTool: ScreenshotTool, context: TContext) => Promise<TResult>;
initPage?: (page: Page, screenshotTool: ScreenshotTool) => Promise<TContext>;
};
/**
* Plugin function type definition
*/
type Plugin<Config = any> = (config?: Config) => PluginDef;
//#endregion
//#region src/types.d.ts
type PossiblePromise<T> = Promise<T> | T;
/**
* Configuration for the comparison of images
*/
interface DiffConfig {
/**
* Matching threshold (0-1). Lower = more sensitive
* Default = 0.1
*
* This affects how similar a pixel needs to be in the reference image to be considered the same.
*/
threshold?: number;
/**
* Include anti-aliased pixels in diff count
* Default = false
*
* For most users this should be false, because it makes comparisons very sensitive to sub-pixel differences of
* fonts and other UI elements.
*/
includeAA?: boolean;
/**
* Use fast buffer comparison for identical images
* Default = true
*/
fastBufferCheck?: boolean;
/**
* Maximum number of different pixels
* Default = 0
*
* The amount of pixels that can be different before the comparison fails.
*/
maxDiffPixels?: number;
/**
* Maximum percentage of pixels different
* Default = 0
*
* The amount of pixels that can be different before the comparison fails as a percentage of the total pixels.
* 0 = no difference, 100 = 100% difference.
*
* Since this is a relative value, it is affected by the size of the images. A 100px image with a 10% difference
* is 10 pixels different, but a 1000px image with a 10% difference is 100 pixels different. On very large full page screenshots
* this can mean that small changes still slip through.
*/
maxDiffPercentage?: number;
}
/**
* Config used in `cappa.config.ts`
*
* @example
* import { defineConfig } from '@cappa/core'
* export default defineConfig({
* ...
* })
*/
type UserConfig = {
/**
* The directory to save screenshots and other files in
*/
outputDir?: string;
/**
* Configuration for the comparison of images
*/
diff?: DiffConfig;
/**
* The number of times to retry a screenshot if it fails
*/
retries?: number;
/**
* The number of parallel browser contexts to use for taking screenshots
*/
concurrency?: number;
/**
* An array of Cappa plugins used for generation.
* Each plugin may have additional configurable options (defined within the plugin itself).
*/
plugins?: Array<Plugin | PluginDef>;
};
type Viewport = {
width: number;
height: number;
};
type ScreenshotSettings = {
fullPage?: boolean;
delay?: number;
skip?: boolean;
mask?: Locator[];
omitBackground?: boolean;
viewport?: Viewport;
};
type ScreenshotVariant = {
id: string;
label?: string;
filename?: string;
options?: ScreenshotSettings;
};
type ScreenshotOptions = ScreenshotSettings & {
variants?: ScreenshotVariant[];
};
interface Screenshot {
id: string;
name: string;
category: "new" | "deleted" | "changed" | "passed";
actualPath?: string;
expectedPath?: string;
diffPath?: string;
approved?: boolean;
}
//#endregion
//#region src/config.d.ts
/**
* Type helper to make it easier to use cappa.config.ts, or a function that returns it. The function receives a ConfigEnv object.
*/
declare function defineConfig(options: PossiblePromise<UserConfig | Array<UserConfig>> | (() => PossiblePromise<UserConfig | Array<UserConfig>>)): typeof options;
//#endregion
export { type Plugin, type PluginDef, type PluginFunction, type Screenshot, type ScreenshotCaptureDetails, type ScreenshotCaptureExtras, type ScreenshotCaptureResult, ScreenshotFileSystem, type ScreenshotOptions, type ScreenshotSettings, ScreenshotTool, type ScreenshotVariant, type ScreenshotVariantCaptureDetails, type UserConfig, type Viewport, defineConfig };
//# sourceMappingURL=index.d.ts.map