@inngest/test
Version:
Tooling for testing Inngest functions.
229 lines (228 loc) • 8.33 kB
TypeScript
import { Context, EventPayload, InngestFunction } from "inngest";
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;
/**
* Request arguments that will be passed to the function execution.
*
* These can be used by middleware that relies on particular serve handler usage.
* If not provided, an empty array will be used.
*/
reqArgs?: unknown[];
/**
* 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 cache for storing mock handler execution results across multiple executions.
* This ensures handlers are only called once per test run.
*/
interface MockHandlerCache {
[stepId: string]: {
executed: boolean;
promise?: Promise<void>;
data?: any;
error?: any;
lazyHandlers: Array<(state: {
data?: any;
error?: any;
}) => Promise<void>>;
};
}
/**
* 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;
protected mockHandlerCache: MockHandlerCache;
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>;
}
export {};