import { Expect, Page, TestType, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, Locator, FrameLocator, Dialog, } from "@playwright/test"; interface ChecksumAIMethod { (title: string): IChecksumPage; ( title: string, body: () => T | Promise, options?: ChecksumAIOptions ): Promise; } type EnumValues = T[keyof T]; export interface IVariableStore { [key: string]: any; } // backward compatibility export type IVariablesStore = IVariableStore; type ModifyLocatorMethodToChecksumLocator = { [K in keyof T]: T[K] extends (...args: any[]) => Locator // Check if the property is a function returning Locator ? (...args: Parameters) => ChecksumLocator // Change its return type to ChecksumLocator : T[K]; // Keep the rest of the fields as they are }; type ModifyFrameLocatorMethodToChecksumFrameLocator = { [K in keyof T]: T[K] extends (...args: any[]) => FrameLocator // Check if the property is a function returning Locator ? (...args: Parameters) => ChecksumFrameLocator // Change its return type to ChecksumLocator : T[K]; // Keep the rest of the fields as they are }; type ModifyPlaywrightLocatorMethods = ModifyFrameLocatorMethodToChecksumFrameLocator< ModifyLocatorMethodToChecksumLocator >; export interface IChecksumPage extends ModifyPlaywrightLocatorMethods, CompoundSelectionInterface { checksumSelector: (id: string) => IChecksumPage; checksumAI: ChecksumAIMethod; resolveAssetsFolder: (assets: string[]) => string[]; getPage(index: number): Promise; reauthenticate: (role: string) => Promise; waitForDialog: (timeout?: number) => Promise; /** * Returns the underlying Playwright page. Interactions performed through it * skip the Checksum action wrapper entirely (execution-timeout guard and * auto-recovery fallback). Use it for housekeeping interactions that must * not trigger auto-recovery for the current step. * * Note: actions inside `page.addLocatorHandler()` callbacks are * automatically exempt from auto-recovery, and chaining an explicit * `.catch(...)` onto any Checksum locator action also skips auto-recovery * for that action. */ bypassChecksum(): Page; } export interface CompoundSelectionInterface { /** * Will create a compound selection that selects elements by grouping multiple locators as anchors * and finding the target elements, if specified, from their common root parent. * If no target is provided, the compound selection will return a locator to the common parents that were calculated from the anchors. * * **Usage example** * * ```js * await page.compoundSelection( * (base) => [base.getByText("""), page.locator("selector to second anchor"), ""], * (base) => base.locator("") * ]).first().click(); * ``` * * @param anchors Method that returns array of locators and/or text context, to group and calculate the common parent from. * The method receives the base locator as an argument, which is the relative locator or page that the compound selection is called on. * The method should return an array of locators or strings that point at the anchor elements. * @param target [optional] Method that returns the relative locator or string content that will point at the target element from the common parent * that was calculated from the anchors. * If no target is provided, the compound selection will return a locator pointing at the common parents. * @returns Locator to the common parent(s) or the target element(s) if specified. */ compoundSelection( anchors: (base: Locator) => Array, target?: (base: Locator) => Locator | string ): ChecksumLocator; /** * Will create a compound selection that selects elements by grouping multiple locators as anchors * and finding the target elements, if specified, from their common root parent. * If no target is provided, the compound selection will return a locator to the common parents that were calculated from the anchors. * * **Usage example** * * ```js * await page.compoundSelection({ * anchors: (base) => [base.getByText("""), page.locator("selector to second anchor"), ""], * target?: (base) => base.locator("") * }).first().click(); * ``` * @returns Locator to the common parent(s) or the target element(s) if specified. */ compoundSelection(selection: { /** * Method that returns array of locators and/or text context, to group and calculate the common parent from. * The method receives the base locator as an argument, which is the relative locator or page that the compound selection is called on. * The method should return an array of locators or strings that point at the anchor elements. * * @param base Base locator that the compound selection is called on. */ anchors: (base: Locator) => Array; /** * Method that returns the relative locator or string content that will point at the target element from the common parent * that was calculated from the anchors. * If the target is null, the compound selection will return a locator pointing at the common parents. * * @param base Base locator that the compound selection is called on. */ target?: (base: Locator) => Locator | string; }): ChecksumLocator; } export interface ChecksumFrameLocator extends ModifyPlaywrightLocatorMethods, CompoundSelectionInterface {} export interface ChecksumLocator extends ModifyPlaywrightLocatorMethods, CompoundSelectionInterface { canvasClick: (canvasText: string, rectSizeIndex?: number) => Promise; /** * Returns the underlying Playwright locator. Interactions performed through * it skip the Checksum action wrapper entirely (execution-timeout guard and * auto-recovery fallback). Use it for housekeeping interactions that must * not trigger auto-recovery for the current step: * * ```js * await page.getByLabel("Close").bypassChecksum().click({ timeout: 3000 }); * ``` * * Notes: * - Actions inside `page.addLocatorHandler()` callbacks are automatically * exempt from auto-recovery — `bypassChecksum()` is not required there. * - Chaining an explicit `.catch(...)` onto a Checksum locator action * (e.g. `locator.click().catch(() => {})`) also skips auto-recovery for * that action: an explicit catch declares the failure as expected. * - On `compoundSelection()` chains the underlying locator is resolved * asynchronously — `await` the result. * - Not available after `.or()` / `.and()` (those chains already return * the raw Playwright locator). */ bypassChecksum(): Locator; } type Apply_MakeMatchers = ReturnType< ExpectWrapper["apply"] >; type Soft_MakeMatchers = ReturnType< ExpectWrapper["soft"] >; type Poll_MakeMatchers = ReturnType< ExpectWrapper["poll"] >; type ChecksumMakeMatchers = MakeMatchers & { checksumAI: (thought: string) => MakeMatchers; withChecksumAI: () => Promise; }; export interface IChecksumExpect> extends Expect { checksumAI: (thought: string) => IChecksumExpect; skipAutoRecovery: IChecksumExpect & (( actual: T, messageOrOptions?: string | { message?: string } ) => MakeMatchers); ( actual: T, messageOrOptions?: | string | { message?: string; checksumAI?: boolean | string } ): ChecksumMakeMatchers>; soft: ( actual: T, messageOrOptions?: | string | { message?: string; checksumAI?: boolean | string } ) => ChecksumMakeMatchers>; poll: ( actual: () => T | Promise, messageOrOptions?: | string | { message?: string; timeout?: number; intervals?: number[]; checksumAI?: boolean | string; } ) => ChecksumMakeMatchers>; } export enum RunMode { Normal = "normal", Heal = "heal", Refactor = "refactor", } export enum AutoRecoveryMode { Regular = "regular", Fast = "fast", ExtraFast = "extra_fast", // SYNC: mirror of packages/nodejs-lib/src/runtime/types.ts AutoRecoveryMode OneShot = "one_shot", } export type RuntimeOptions = { /** * Whether to use Checksum Smart Selector when trying to locate an element to perform an action */ useChecksumSelectors: boolean; /** * Whether to use Checksum AI when trying to perform an action or an assertion * @param arVersion - Whether to use the new auto recovery system. If not provided, it will use the old AR system. * 1- basic AR, 2 - new AR */ useChecksumAI: | boolean | { actions: boolean; assertions: boolean; visualComparison?: boolean; skipTestsWithKnownBugs?: boolean; arMode?: AutoRecoveryMode; arVersion?: 1 | 2; /** * When true (the default), auto-recovery applies the corrective action * and marks the failing step as recovered. Set to false for suggest-only: * the agent returns the proposed fix without mutating the browser. * Applies to all arModes. */ markRecovered?: boolean; /** * Override the auto-recovery model for the selected arMode. Useful to * make OneShot accuracy-first, e.g. modelName: "claude_opus_4_8". * SYNC: values mirror modelSelectionName in * packages/nodejs-lib/src/agent-flow/types.ts. */ modelName?: | "claude_4" | "claude_3.7" | "claude_sonnet_4_6" | "claude_sonnet_5" | "claude_opus_4_8" | "gemini_2.5_pro" | "gemini_2.0_flash" | "gemini_2.5_flash" | "gemini_2.5_flash_lite" | "gemini_3.5_flash" | "gemini_3.1_flash_lite" | "gpt_4o_mini" | "gpt_4o_nano" | "gpt_41_nano" | "gpt_41_mini" | "gpt_41" | "o4_mini" | "o3_mini" | "gpt_5_mini" | "gpt_5_nano"; }; /** * Add new assertions */ newAssertionsEnabled: boolean; /** * Use mocked data */ useMockData: boolean; /** * Print logs to console */ printLogs: boolean; /** * Save reports on checksum hosting servers */ hostReports?: boolean; /** * Create a PR with healed tests. Only relevant when in Heal mode. */ autoHealPRs?: boolean; /** * Delay in ms between consecutive actions (e.g. click→click). * Prevents race conditions where onclick handlers aren't registered yet. * Set to 0 to disable. Default: 100 */ consecutiveActionDelay?: number; /** * Model configuration */ modelConfig?: Partial<{ skipCompleteOriginHeaderOnDisableWebSecurity?: boolean; browserArgs?: Partial<{ skipDisableWebSecurity?: boolean; skipAllowFileAccessFromFiles?: boolean; skipDisableSiteIsolationTrials?: boolean; skipAllowRunningInsecureContent?: boolean; }>; }>; /** * Time to wait before adding the browser script [ms] */ browserScriptAddWait?: number; /** * Time to wait before initializing the browser script [ms] */ browserScriptInitWait?: number; }; export type ChecksumConfig = { /** * Checksum runtime running mode - * normal - tests run normally * heal - checksum will attempt to heal tests that failed using fallback * refactor - checksum will attempt to refactor and improve your tests */ runMode: RunMode; /** * Checksum API key */ apiKey: string; /** * Names which environment below a run uses when nothing selects one for it. * Outranks the `default: true` flag, and must match an environment declared * here — a name that matches nothing fails the run rather than falling back. */ defaultEnvironmentName?: string; environments?: ChecksumConfigEnvironment[]; /** * Checksum runtime options */ options?: Partial; }; export type ChecksumConfigEnvironment = { name: string; users?: EnvironmentUser[]; baseURL: string; loginURL?: string; default?: boolean; }; export type EnvironmentUser = { role: string; username?: string; password?: string; default?: boolean; }; export type ChecksumLoginFunctionParams = { environment: ChecksumConfigEnvironment; user: EnvironmentUser; config?: ChecksumConfig; payload?: PayloadType; }; export type ChecksumLoginFunction = ( page: IChecksumPage, params: ChecksumLoginFunctionParams ) => Promise; export function getLogin(): ( page: Page | IChecksumPage, { role, environment }?: { role?: string; environment?: string } ) => Promise; export function getChecksumConfig( config: Partial ): ChecksumConfig; type ChecksumPlaywrightTestArgs = Omit & { page: IChecksumPage; variablesStore: IVariableStore; variableStore: IVariableStore; vs: IVariableStore; }; type ChecksumTestType = TestType< TestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs & PlaywrightWorkerOptions >; export type ChecksumAIOptions = { withDialog?: boolean; skipAutoRecovery?: boolean; }; export type ChecksumAI = { ( description: string, testFunction: (...args: unknown[]) => unknown, options?: ChecksumAIOptions ): Promise; } & { [K in keyof ChecksumAIOptions]: ChecksumAI; }; interface DefineChecksumIdMethod { (title: string, testId: undefined, flowId: string): string; (title: string, testId: string, flowId?: string): string; } /** * Initialize Checksum runtime * * @param base Optional Playwright test object to extend * @param config Optional checksum config (defaults to loading checksum.config.ts) */ export function init( base?: ChecksumTestType, config?: ChecksumConfig ): { test: ChecksumTestType; login: ReturnType; defineChecksumTest: DefineChecksumIdMethod; expect: IChecksumExpect; checksumAI: ChecksumAI; getEnvironment: ({ name, userRole, }: { name?: string; userRole?: string; }) => { environment: ChecksumConfigEnvironment; user: EnvironmentUser; login: ReturnType; }; }; export enum Locators { Locator = "locator", GetByRole = "getByRole", GetByText = "getByText", GetByLabel = "getByLabel", GetByPlaceholder = "getByPlaceholder", GetByAltText = "getByAltText", GetByTitle = "getByTitle", GetByTestId = "getByTestId", FrameLocator = "frameLocator", } export class ExpectWrapper { expecter: Expect; apply(e: T) { return this.expecter(e); } soft(e: T) { return this.expecter.soft(e); } poll(e: T) { return this.expecter.poll(() => e); } } declare global { const repl: (cliMode?: boolean, messageFileSuffix?: string) => string; }