import type { InngestFunction } from "inngest/components/InngestFunction";
import { Context, EventPayload } from "inngest/types";
import { InngestTestRun } from "./InngestTestRun.js";
import type { Mock } from "./spy.js";
import { type DeepPartial } from "./util.js";
/**
 * A test engine for running Inngest functions in a test environment, providing
 * the ability to assert inputs, outputs, and step usage, as well as mocking
 * with support for popular testing libraries.
 */
export declare namespace InngestTestEngine {
    /**
     * Options for creating a new {@link InngestTestEngine} instance.
     */
    interface Options {
        /**
         * The function to test.
         *
         * TODO Potentially later allow many functions such that we can invoke and
         * send events.
         */
        function: InngestFunction.Like;
        /**
         * The event payloads to send to the function. If none is given, an
         * "inngest/function.invoked" event will be mocked.
         */
        events?: [EventPayload, ...EventPayload[]];
        /**
         * Previous step state to use for this execution. If not provided, none will
         * be used. It's recommended to use `run.waitFor()`, where this will be
         * filled automatically as the run progresses.
         */
        steps?: MockedStep[];
        /**
         * The human-readable ID of the step that this execution is attempting to
         * run. This is mostly an internal detail; it's recommended to use
         * `run.waitFor()`, where this will be filled automatically as the run
         * progresses.
         */
        targetStepId?: string;
        /**
         * An internal option to disable immediate execution of steps during
         * parallelism. It's recommended to use `run.waitFor()`, where this will be
         * filled automatically as the run progresses.
         */
        disableImmediateExecution?: boolean;
        /**
         * A function that can transform the context sent to the function upon
         * execution, useful for mocking steps, events, or tracking property
         * accesses with proxies.
         *
         * By default, this will change all `step.*` tools to be mocked functions so
         * that you can assert their usage, input, and output. If you specify this
         * option yourself, you'll overwrite this behavior.
         *
         * If you wish to keep this behaviour and make additional changes, you can
         * use the `mockContext` function exported from this module.
         *
         * @example Transforming in addition to the defaults
         * ```ts
         * import { mockCtx } from "@inngest/test";
         *
         * {
         *   transformCtx: (rawCtx) => {
         *     const ctx = mockCtx(rawCtx);
         *
         *     // your other changes
         *
         *     return ctx;
         *   },
         * }
         * ```
         */
        transformCtx?: (ctx: Context.Any) => Context.Any;
    }
    interface MockedStep {
        id: string;
        idIsHashed?: boolean;
        handler: () => any;
    }
    type DeepMock<T> = T extends (...args: any[]) => any ? Mock<T> : T extends object ? {
        [K in keyof T]: DeepMock<T[K]>;
    } : T;
    /**
     * A mocked context object that allows you to assert step usage, input, and
     * output.
     */
    interface MockContext extends Omit<Context.Any, "step"> {
        step: DeepMock<Context.Any["step"]>;
    }
    /**
     * Options that can be passed to an existing execution or run to continue
     * execution.
     */
    type InlineOptions = Omit<Options, "function">;
    /**
     * Options that can be passed to an initial execution that then waits for a
     * particular checkpoint to occur.
     */
    type ExecuteOptions<T extends InngestTestRun.CheckpointKey = InngestTestRun.CheckpointKey> = InlineOptions & {
        /**
         * An optional subset of the checkpoint to match against. Any checkpoint of
         * this type will be matched.
         *
         * When providing a `subset`, use `expect` tooling such as
         * `expect.stringContaining` to match partial values.
         */
        subset?: DeepPartial<InngestTestRun.Checkpoint<T>>;
    };
    type ExecuteStepOptions = InlineOptions & {
        subset?: DeepPartial<InngestTestRun.Checkpoint<"steps-found">>;
    };
    /**
     * A mocked state object that allows you to assert step usage, input, and
     * output.
     */
    type MockState = Record<string, Promise<unknown>>;
    /**
     * The output of an individual function execution.
     */
    interface ExecutionOutput<T extends InngestTestRun.CheckpointKey = InngestTestRun.CheckpointKey> {
        /**
         * The result of the execution.
         */
        result: InngestTestRun.Checkpoint<T>;
        /**
         * The mocked context object that allows you to assert step usage, input,
         * and output.
         *
         * @TODO This type may vary is `transformCtx` is given.
         */
        ctx: InngestTestEngine.MockContext;
        /**
         * The mocked state object that allows you to assert step usage, input, and
         * output.
         */
        state: InngestTestEngine.MockState;
        /**
         * An {@link InngestTestRun} instance that allows you to wait for specific
         * checkpoints in the execution.
         */
        run: InngestTestRun;
    }
}
/**
 * A test engine for running Inngest functions in a test environment, providing
 * the ability to assert inputs, outputs, and step usage, as well as mocking
 * with support for popular testing libraries.
 */
export declare class InngestTestEngine {
    protected options: InngestTestEngine.Options;
    constructor(options: InngestTestEngine.Options);
    /**
     * Create a new test engine with the given inline options merged with the
     * existing options.
     */
    clone(inlineOpts?: InngestTestEngine.InlineOptions): InngestTestEngine;
    /**
     * Start a run from the given state and keep executing the function until a
     * specific checkpoint is reached.
     *
     * Is a shortcut for and uses `run.waitFor()`.
     */
    execute<T extends InngestTestRun.CheckpointKey>(
    /**
     * Options and state to start the run with.
     */
    inlineOpts?: InngestTestEngine.ExecuteOptions<T>): Promise<InngestTestRun.RunOutput>;
    /**
     * Start a run from the given state and keep executing the function until the
     * given step has run.
     */
    executeStep(
    /**
     * The ID of the step to execute.
     */
    stepId: string, 
    /**
     * Options and state to start the run with.
     */
    inlineOpts?: InngestTestEngine.ExecuteOptions): Promise<InngestTestRun.RunStepOutput>;
    /**
     * Start a run from the given state and keep executing the function until a
     * specific checkpoint is reached.
     *
     * Is a shortcut for and uses `run.waitFor()`.
     *
     * @TODO This is a duplicate of `execute` and will probably be removed; it's a
     * very minor convenience method that deals too much with the internals.
     */
    protected executeAndWaitFor<T extends InngestTestRun.CheckpointKey>(
    /**
     * The checkpoint to wait for.
     */
    checkpoint: T, 
    /**
     * Options and state to start the run with.
     */
    inlineOpts?: InngestTestEngine.ExecuteOptions<T>): Promise<InngestTestEngine.ExecutionOutput<T>>;
    /**
     * Execute the function with the given inline options.
     */
    protected individualExecution(inlineOpts?: InngestTestEngine.InlineOptions): Promise<InngestTestEngine.ExecutionOutput>;
}
