import type { Worker as ClusterWorker } from 'cluster';
import type { expect } from 'chai';
import type EventEmitter from 'events';
import type { ODiffOptions } from 'odiff-bin';
import type { LaunchOptions } from 'playwright-core';
import type { PixelmatchOptions } from 'pixelmatch';
import type { StoryContextForEnhancers, DecoratorFunction } from 'storybook/internal/types';
export interface SetStoriesData {
    v?: number;
    globalParameters: {
        creevey?: CreeveyStoryParams;
    };
    kindParameters: Partial<Record<string, {
        fileName: string;
        creevey?: CreeveyStoryParams;
    }>>;
    stories: StoriesRaw;
}
export type StoriesRaw = Record<string, StoryContextForEnhancers>;
export type StoryInput = StoriesRaw extends Record<string, infer S> ? S : never;
export interface StoryMeta {
    title: string;
    component?: unknown;
    decorators?: DecoratorFunction[];
    parameters?: {
        creevey?: CreeveyStoryParams;
        [name: string]: unknown;
    };
}
export declare enum StorybookEvents {
    SET_STORIES = "setStories",
    SET_CURRENT_STORY = "setCurrentStory",
    FORCE_REMOUNT = "forceRemount",
    STORY_RENDERED = "storyRendered",
    STORY_ERRORED = "storyErrored",
    STORY_THREW_EXCEPTION = "storyThrewException",
    UPDATE_STORY_ARGS = "updateStoryArgs",
    SET_GLOBALS = "setGlobals",
    UPDATE_GLOBALS = "updateGlobals"
}
export interface CreeveyMeta {
    parameters?: {
        creevey?: CreeveyStoryParams;
        [name: string]: unknown;
    };
}
export interface CSFStory<StoryFnReturnType = unknown> {
    (): StoryFnReturnType;
    /**
     * @deprecated
     * CSF .story annotations deprecated; annotate story functions directly:
     * - StoryFn.story.name => StoryFn.storyName
     * - StoryFn.story.(parameters|decorators) => StoryFn.(parameters|decorators)
     * See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#hoisted-csf-annotations for details and codemod.
     */
    story?: {
        name?: string;
        decorators?: DecoratorFunction[];
        parameters?: {
            creevey?: CreeveyStoryParams;
            [name: string]: unknown;
        };
    };
    storyName?: string;
    decorators?: DecoratorFunction[];
    parameters?: {
        creevey?: CreeveyStoryParams;
        [name: string]: unknown;
    };
}
export interface CreeveyStory {
    parameters?: {
        creevey?: CreeveyStoryParams;
        [name: string]: unknown;
    };
}
export interface BrowserConfigObject {
    browserName: string;
    limit?: number;
    /**
     * Selenium grid url
     * @default config.gridUrl
     */
    gridUrl?: string;
    storybookUrl?: string;
    /**
     * Storybook's globals to set in a specific browser
     * @see https://github.com/storybookjs/storybook/blob/v6.0.0/docs/essentials/toolbars-and-globals.md
     */
    storybookGlobals?: StorybookGlobals;
    /**
     * @deprecated Use `storybookGlobals` instead
     */
    _storybookGlobals?: StorybookGlobals;
    /**
     * Specify custom docker image. Used only with `useDocker == true`
     * @default `selenoid/${browserName}:${browserVersion ?? 'latest'}` or `mcr.microsoft.com/playwright:${playwrightVersion}`
     */
    dockerImage?: string;
    /**
     * Command to start standalone webdriver
     * Used only with `useDocker == false`
     */
    webdriverCommand?: string[];
    viewport?: {
        width: number;
        height: number;
    };
    /**
     * Connection timeout for this specific browser in milliseconds.
     * Overrides global connectionTimeout
     */
    connectionTimeout?: number;
    seleniumCapabilities?: {
        /**
         * Browser version. Ignored with Playwright webdriver
         */
        browserVersion?: string;
        /**
         * Operation system name. Ignored with Playwright webdriver
         */
        platformName?: string;
        [name: string]: unknown;
    };
    playwrightOptions?: Omit<LaunchOptions, 'logger'> & {
        trace?: {
            screenshots?: boolean;
            snapshots?: boolean;
            sources?: boolean;
        };
    };
}
export type StorybookGlobals = Record<string, unknown>;
export type BrowserConfig = boolean | string | BrowserConfigObject;
export type CreeveyWebdriverConstructor = new (browser: string, gridUrl: string, config: Config, debug: boolean) => CreeveyWebdriver;
export interface CreeveyWebdriver {
    getSessionId(): Promise<string>;
    openBrowser(fresh?: boolean): Promise<CreeveyWebdriver | null>;
    closeBrowser(): Promise<void>;
    loadStoriesFromBrowser(): Promise<StoriesRaw>;
    switchStory(story: StoryInput, context: BaseCreeveyTestContext): Promise<CreeveyTestContext>;
    afterTest(test: ServerTest): Promise<void>;
}
export interface HookConfig {
    before?: () => unknown;
    after?: () => unknown;
}
export interface DockerAuth {
    key?: string;
    username?: string;
    password?: string;
    auth?: string;
    email?: string;
    serveraddress?: string;
}
export type BaseReporter = new (runner: EventEmitter, options: {
    reportDir: string;
    reporterOptions: any;
}) => void;
export interface Config {
    /**
     * Url to Selenium grid hub or standalone selenium.
     * By default creevey will use docker containers
     */
    gridUrl: string;
    /**
     * Url where storybook hosted on
     * @default 'http://localhost:6006'
     */
    storybookUrl: string;
    /**
     * Url where storybook hosted on
     */
    resolveStorybookUrl?: () => Promise<string>;
    /**
     * Command to automatically start Storybook if it is not running.
     * For example, `npm run storybook` or `yarn storybook` etc.
     */
    storybookAutorunCmd?: string;
    /**
     * Absolute path to directory with reference images
     * @default path.join(process.cwd(), './images')
     */
    screenDir: string;
    /**
     * Absolute path where test reports and diff images would be saved
     * @default path.join(process.cwd(), './report')
     */
    reportDir: string;
    /**
     * Specify a custom reporter for test results. Creevey accepts only mocha-like reporters
     * @optional
     * @default 'creevey'
     */
    reporter: BaseReporter | 'creevey' | 'teamcity' | 'junit';
    /**
     * Options which are used by reporter
     */
    reporterOptions?: Record<string, any>;
    /**
     * How much test would be retried
     * @default 0
     */
    maxRetries: number;
    /**
     * How much time should be spent on each test
     * @default 30000
     */
    testTimeout: number;
    /**
     * Connection timeout for Selenium/Playwright Grid in milliseconds
     * @default 60000
     */
    connectionTimeout?: number;
    /**
     * Define pixelmatch diff options
     * @default { threshold: 0.1, includeAA: false }
     */
    diffOptions: PixelmatchOptions;
    /**
     * Define odiff diff options
     * @default { threshold: 0.1, antialiasing: true }
     */
    odiffOptions: ODiffOptions;
    /**
     * Browser capabilities
     * @default { chrome: true }
     */
    browsers: Record<string, BrowserConfig>;
    /**
     * Hooks that allow run custom script before and after creevey start
     */
    hooks: HookConfig;
    /**
     * Creevey automatically download latest selenoid binary. You can define path to different verison.
     * Works only with `useDocker == false`
     */
    selenoidPath?: string;
    /**
     * @deprecated The `storiesProvider` config property is deprecated and will be removed in a future version.
     * Creevey will use only the `hybrid` stories provider going forward.
     *
     * Currently allows you to specify how Creevey will extract stories from Storybook:
     *
     * `browserStoriesProvider` - Extracts stories directly from Storybook UI. Note that this provider doesn't support interaction tests unless you use CSFv3 with `play` method.
     *
     * `hybridStoriesProvider` - Combines stories from Storybook with tests from separate files. This is the default provider and will be the only option in future versions.
     *
     * Usage
     * ``` typescript
     * import { browserStoriesProvider as provider } from 'creevey'
     * // or
     * import { hybridStoriesProvider as provider } from 'creevey'
     *
     * // Creevey config
     * module.exports = {
     *   storiesProvider: provider
     * }
     * ```
     */
    storiesProvider: StoriesProvider;
    /**
     *
     */
    webdriver: CreeveyWebdriverConstructor;
    /**
     * Allows you to start selenoid without docker
     * and use standalone browsers
     * @default true
     */
    useDocker: boolean;
    /**
     * Custom selenoid docker image
     * @default 'aerokube/selenoid:latest-release'
     */
    dockerImage: string;
    /**
     * Should Creevey pull docker images or use local ones
     * @default true
     */
    pullImages: boolean;
    /**
     * Define auth config for private docker registry
     */
    dockerAuth?: DockerAuth;
    /**
     * Enable to stop tests running right after the first failed test.
     * The `--ui` CLI option ignores this option
     */
    failFast: boolean;
    /**
     * Start workers in sequential queue
     * @default false
     */
    useWorkerQueue: boolean;
    /**
     * Specify platform for docker images
     */
    dockerImagePlatform: string;
    testsRegex?: RegExp;
    testsDir?: string;
    /**
     * Telemetry contains information about Creevey and Storybook versions, used Creevey config, browsers and tests meta.
     * It's being sent only for projects from git.skbkontur.ru
     * @default false
     */
    disableTelemetry?: boolean;
    /**
     * Define a host where is creevey-server hosting.
     * It can be used for networks behind NAT
     */
    host?: string;
    /**
     * Experimental features use with caution
     */
    experimental?: {
        /**
         * Doesn't work with odiff comparison library
         * @default false
         */
        reportOnlyFailedTests: boolean;
        /**
         * Use npm registry for installing playwright-core inside docker container
         */
        npmRegistry?: string;
    };
}
export interface StoriesProvider {
    (config: Config, storiesListener: (stories: Map<string, StoryInput[]>) => void, webdriver?: CreeveyWebdriver): Promise<StoriesRaw>;
    providerName?: string;
}
export type CreeveyConfig = Partial<Config>;
export type WorkerError = 'browser' | 'test' | 'unknown';
export type WorkerMessage = {
    type: 'ready';
    payload?: never;
} | {
    type: 'port';
    payload: {
        port: number;
    };
} | {
    type: 'error';
    payload: {
        subtype: WorkerError;
        error: string;
    };
};
export type StoriesMessage = {
    type: 'get';
    payload?: never;
} | {
    type: 'set';
    payload: {
        stories: StoriesRaw;
        oldTests: string[];
    };
} | {
    type: 'update';
    payload: [string, StoryInput[]][];
} | {
    type: 'capture';
    payload?: CaptureOptions;
};
export type TestMessage = {
    type: 'start';
    payload: {
        id: string;
        path: string[];
        retries: number;
    };
} | {
    type: 'update';
    payload: CreeveyUpdate['tests'];
} | {
    type: 'end';
    payload: TestResult;
};
export type ShutdownMessage = object;
export type ProcessMessage = (WorkerMessage & {
    scope: 'worker';
}) | (StoriesMessage & {
    scope: 'stories';
}) | (TestMessage & {
    scope: 'test';
}) | (ShutdownMessage & {
    scope: 'shutdown';
});
export type WorkerHandler = (message: WorkerMessage) => void;
export type StoriesHandler = (message: StoriesMessage) => void;
export type TestHandler = (message: TestMessage) => void;
export type ShutdownHandler = (message: ShutdownMessage) => void;
export interface Worker extends ClusterWorker {
    isRunning?: boolean;
    isShuttingDown?: boolean;
}
export interface Images {
    actual: string;
    expect?: string;
    diff?: string;
    error?: string;
}
export type TestStatus = 'unknown' | 'pending' | 'running' | 'failed' | 'approved' | 'success' | 'retrying';
export interface TestResult {
    status: 'failed' | 'success';
    retries: number;
    images?: Partial<Record<string, Images>>;
    error?: string;
    duration?: number;
    attachments?: string[];
    sessionId?: string;
    browserName?: string;
    workerId?: number;
}
export declare class ImagesError extends Error {
    images?: string | Partial<Record<string, string>>;
}
export interface TestMeta {
    id: string;
    storyPath: string[];
    browser: string;
    testName?: string;
    storyId: string;
}
export interface TestData extends TestMeta {
    skip?: boolean | string;
    retries?: number;
    status?: TestStatus;
    results?: TestResult[];
    approved?: Partial<Record<string, number>> | null;
}
export interface BaseCreeveyTestContext {
    browserName: string;
    webdriver: any;
    /**
     * @deprecated Usually for screenshot testing you don't need other type of assertions except matching images, but if you really need it, please use external `expect` libs
     */
    expect: typeof expect;
    /**
     * @internal
     */
    screenshots: {
        imageName?: string;
        screenshot: Buffer;
    }[];
    matchImage: (image: Buffer | string, imageName?: string) => Promise<void>;
    matchImages: (images: Record<string, Buffer | string>) => Promise<void>;
}
export interface CreeveyTestContext extends BaseCreeveyTestContext {
    takeScreenshot: (options?: any) => Promise<Buffer>;
    updateStoryArgs: (updatedArgs: Record<string, unknown>) => Promise<void>;
    captureElement: string | null;
}
export declare enum TEST_EVENTS {
    RUN_BEGIN = "start",
    RUN_END = "end",
    SUITE_BEGIN = "suite",
    SUITE_END = "suite end",
    TEST_BEGIN = "test",
    TEST_END = "test end",
    TEST_FAIL = "fail",
    TEST_PASS = "pass"
}
export interface ServerTest extends TestData {
    story: StoryInput;
    fn: CreeveyTestFunction;
}
export interface FakeSuite {
    title: string;
    fullTitle: () => string;
    titlePath: () => string[];
    tests: FakeTest[];
}
export interface FakeTest {
    parent: FakeSuite;
    title: string;
    fullTitle: () => string;
    titlePath: () => string[];
    currentRetry: () => number | undefined;
    retires: () => number;
    slow: () => number;
    duration?: number;
    state?: 'failed' | 'passed';
    speed?: 'slow' | 'medium' | 'fast';
    err?: string;
    attachments?: string[];
    creevey: {
        testId: string;
        sessionId: string;
        browserName: string;
        workerId: number;
        willRetry: boolean;
        images: Partial<Record<string, Partial<Images>>>;
    };
}
export interface CreeveyStatus {
    isRunning: boolean;
    tests: Partial<Record<string, TestData>>;
    browsers: string[];
    isUpdateMode: boolean;
}
export interface CreeveyUpdate {
    isRunning?: boolean;
    tests?: Partial<Record<string, TestData>>;
    removedTests?: TestMeta[];
}
export interface SkipOption {
    in?: string | string[] | RegExp;
    kinds?: string | string[] | RegExp;
    stories?: string | string[] | RegExp;
    tests?: string | string[] | RegExp;
}
export type SkipOptions = boolean | string | Record<string, SkipOption | SkipOption[]>;
export type CreeveyTestFunction = (context: CreeveyTestContext) => Promise<void>;
export interface CaptureOptions {
    imageName?: string;
    captureElement?: string | null;
    ignoreElements?: string | string[] | null;
}
export interface CreeveyStoryParams extends CaptureOptions {
    delay?: number | {
        for: string[];
        ms: number;
    };
    skip?: SkipOptions;
    tests?: Record<string, CreeveyTestFunction>;
}
export interface ApprovePayload {
    id: string;
    retry: number;
    image: string;
}
export type Request = {
    type: 'status';
} | {
    type: 'start';
    payload: string[];
} | {
    type: 'stop';
} | {
    type: 'approve';
    payload: ApprovePayload;
} | {
    type: 'approveAll';
};
export type Response = {
    type: 'status';
    payload: CreeveyStatus;
} | {
    type: 'update';
    payload: CreeveyUpdate;
} | {
    type: 'capture';
};
export interface CreeveyTest extends TestData {
    checked: boolean;
}
export interface CreeveySuite {
    path: string[];
    skip: boolean;
    status?: TestStatus;
    opened: boolean;
    checked: boolean;
    indeterminate: boolean;
    children: Partial<Record<string, CreeveySuite | CreeveyTest>>;
}
export type ImagesViewMode = 'side-by-side' | 'swap' | 'slide' | 'blend';
export declare function noop(): void;
export declare function isDefined<T>(value: T | null | undefined): value is T;
export declare function isTest(x?: CreeveySuite | CreeveyTest): x is CreeveyTest;
export declare function isObject(x: unknown): x is Record<string, unknown>;
export declare function isString(x: unknown): x is string;
export declare function isFunction(x: unknown): x is (...args: any[]) => any;
export declare function isImageError(error: unknown): error is ImagesError;
export declare function isProcessMessage(message: unknown): message is ProcessMessage;
export declare function isWorkerMessage(message: unknown): message is WorkerMessage;
export declare function isStoriesMessage(message: unknown): message is StoriesMessage;
export declare function isTestMessage(message: unknown): message is TestMessage;
