createTestRuntime
Stable · since 0.1.0
Constructs a Runtime extended with three test helpers — mockCondition, mockAction, and flushMicrotasks. This is the standard entry point for writing trigger tests without React: every test gets its own runtime, every condition and action is stubbed explicitly, and the microtask queue is drained on demand.
The base runtime accepts the same RuntimeOptions as createRuntime.
Import
Section titled “Import”import { createTestRuntime } from '@triggery/testing';
Signature
Section titled “Signature”function createTestRuntime(options?: TestRuntimeOptions): TestRuntime;
type TestRuntimeOptions = RuntimeOptions;
type TestRuntime = Runtime & {
mockCondition<S, K>(
trigger: Trigger<S>,
name: K,
valueOrGetter: ConditionMap<S>[K] | (() => ConditionMap<S>[K]),
): RegistrationToken;
mockAction<S, K>(
trigger: Trigger<S>,
name: K,
handler: ActionFn<ActionMap<S>[K]>,
): RegistrationToken;
flushMicrotasks(): Promise<void>;
};Parameters
Section titled “Parameters”| Param | Type | Default | Description |
|---|---|---|---|
options | RuntimeOptions | {} | Same options as createRuntime. |
Returns
Section titled “Returns”A TestRuntime — Runtime plus three helpers. See mockCondition, mockAction, flushMicrotasks.
Examples
Section titled “Examples”Basic test
Section titled “Basic test”import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
import { createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime } from '@triggery/testing';
import { describe const describe: SuiteAPICreates a suite of tests, allowing for grouping and hierarchical organization of tests.
Suites can contain both tests and other suites, enabling complex test structures. , expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options. , vi const vi: VitestUtils } from 'vitest';
describe describe<object>(name: string | Function, fn?: SuiteFactory<object> | undefined, options?: number): SuiteCollector<object> (+1 overload)Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
Suites can contain both tests and other suites, enabling complex test structures. ('demo trigger', () => {
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options. ('fires the action when the condition matches', () => {
const rt const rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ();
const t const t: Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>
= createTrigger createTrigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>(config: CreateTriggerConfig<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>, runtime?: Runtime): Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
tick: number;
}
: { tick tick: number : number };
conditions conditions: {
enabled: boolean;
}
: { enabled enabled: boolean : boolean };
actions actions: {
log: number;
}
: { log log: number : number };
}>(
{
id id: string : 'demo',
events events: readonly "tick"[] : ['tick'],
required required?: readonly "enabled"[] | undefinedRequired condition keys. The trigger will not run unless all of them are registered. : ['enabled'],
handler handler: TriggerHandler<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}, never>
({ event event: {
readonly name: "tick";
readonly payload: number;
}
, conditions conditions: ConditionsCtx<{
enabled: boolean;
}, never>
, actions actions: ActionsCtx<{
log: number;
}>
}) {
if (!conditions conditions: ConditionsCtx<{
enabled: boolean;
}, never>
.enabled enabled?: boolean | undefined ) return;
actions actions: ActionsCtx<{
log: number;
}>
.log log?: ((payload: number) => void) | undefined ?.(event event: {
readonly name: "tick";
readonly payload: number;
}
.payload payload: number );
},
},
rt const rt: TestRuntime ,
);
rt const rt: TestRuntime .mockCondition mockCondition<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}, "enabled">(trigger: Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>, name: "enabled", valueOrGetter: boolean | (() => boolean)): RegistrationToken
Register a condition for a trigger.
Accepts either a static value or a zero-argument getter. When the
condition's value type is itself a zero-argument function, pass an
explicit getter so the runtime knows which one you mean — otherwise the
heuristic below would call your value as if it were the getter. (t const t: Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>
, 'enabled', true);
const log const log: Mock<Procedure> = vi const vi: VitestUtils .fn VitestUtils.fn: <Procedure>(originalImplementation?: Procedure | undefined) => Mock<Procedure>Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](https://vitest.dev/api/mock).
If no function is given, mock will return `undefined`, when invoked. ();
rt const rt: TestRuntime .mockAction mockAction<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}, "log">(trigger: Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>, name: "log", handler: (payload: number) => void): RegistrationToken
Register an action handler — typically a `vi.fn()`. (t const t: Trigger<{
events: {
tick: number;
};
conditions: {
enabled: boolean;
};
actions: {
log: number;
};
}>
, 'log', log const log: Mock<Procedure> );
rt const rt: TestRuntime .fireSync function fireSync(eventName: string, payload?: unknown): voidRun dispatch synchronously (for tests and benchmarks). ('tick', 42);
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (log const log: Mock<Procedure> ).toHaveBeenCalledWith JestAssertion<Mock<Procedure>>.toHaveBeenCalledWith: <[number]>(args_0: number) => voidEnsure that a mock function is called with specific arguments.
Also under the alias `expect.toBeCalledWith`. (42);
});
});Async dispatch with microtask flush
Section titled “Async dispatch with microtask flush”import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
import { createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime } from '@triggery/testing';
import { expect const expect: ExpectStatic , it const it: TestAPIDefines a test case with a given name and test function. The test function can optionally be configured with test options. , vi const vi: VitestUtils } from 'vitest';
it it<object>(name: string | Function, fn?: TestFunction<object> | undefined, options?: number): void (+1 overload)Defines a test case with a given name and test function. The test function can optionally be configured with test options. ('drains microtasks before assertion', async () => {
const rt const rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ();
const t const t: Trigger<{
events: {
tick: void;
};
actions: {
log: void;
};
}>
= createTrigger createTrigger<{
events: {
tick: void;
};
actions: {
log: void;
};
}>(config: CreateTriggerConfig<{
events: {
tick: void;
};
actions: {
log: void;
};
}>, runtime?: Runtime): Trigger<{
events: {
tick: void;
};
actions: {
log: void;
};
}>
Create a trigger and register it in a runtime (the default runtime if none is passed). <{
events events: {
tick: void;
}
: { tick tick: void : void };
actions actions: {
log: void;
}
: { log log: void : void };
}>(
{
id id: string : 'demo',
events events: readonly "tick"[] : ['tick'],
handler handler: TriggerHandler<{
events: {
tick: void;
};
actions: {
log: void;
};
}, never>
({ actions actions: ActionsCtx<{
log: void;
}>
}) {
actions actions: ActionsCtx<{
log: void;
}>
.log log?: (() => void) | undefined ?.();
},
},
rt const rt: TestRuntime ,
);
const log const log: Mock<Procedure> = vi const vi: VitestUtils .fn VitestUtils.fn: <Procedure>(originalImplementation?: Procedure | undefined) => Mock<Procedure>Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](https://vitest.dev/api/mock).
If no function is given, mock will return `undefined`, when invoked. ();
rt const rt: TestRuntime .mockAction mockAction<{
events: {
tick: void;
};
actions: {
log: void;
};
}, "log">(trigger: Trigger<{
events: {
tick: void;
};
actions: {
log: void;
};
}>, name: "log", handler: () => void): RegistrationToken
Register an action handler — typically a `vi.fn()`. (t const t: Trigger<{
events: {
tick: void;
};
actions: {
log: void;
};
}>
, 'log', log const log: Mock<Procedure> );
rt const rt: TestRuntime .fire function fire(eventName: string, payload?: unknown): voidFire an event asynchronously (through the scheduler). ('tick'); // microtask scheduler — handler not yet ran
await rt const rt: TestRuntime .flushMicrotasks function flushMicrotasks(): Promise<void>Flush pending microtasks. The default scheduler uses `queueMicrotask` —
after `rt.fire(...)` you await `flushMicrotasks()` before asserting.
`fireSync` does not need this: it runs handlers immediately. ();
expect expect<Mock<Procedure>>(actual: Mock<Procedure>, message?: string): Assertion<Mock<Procedure>> (+1 overload) (log const log: Mock<Procedure> ).toHaveBeenCalledTimes JestAssertion<Mock<Procedure>>.toHaveBeenCalledTimes: (times: number) => voidEnsures that a mock function is called an exact number of times.
Also under the alias `expect.toBeCalledTimes`. (1);
});Cleanup between tests
Section titled “Cleanup between tests”import { createTrigger function createTrigger<S extends TriggerSchema>(config: CreateTriggerConfig<S>, runtime?: Runtime): Trigger<S>Create a trigger and register it in a runtime (the default runtime if none is passed). } from '@triggery/core';
import { createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime , type TestRuntime type TestRuntime = Runtime & {
mockCondition<S extends TriggerSchema, K extends ConditionKey<S>>(trigger: Trigger<S>, name: K, valueOrGetter: ConditionMap<S>[K] | (() => ConditionMap<S>[K])): RegistrationToken;
mockAction<S extends TriggerSchema, K extends ActionKey<S>>(trigger: Trigger<S>, name: K, handler: ActionFn<ActionMap<S>[K]>): RegistrationToken;
flushMicrotasks(): Promise<void>;
}
} from '@triggery/testing';
import { afterEach function afterEach<ExtraContext = object>(fn: AfterEachListener<ExtraContext>, timeout?: number): voidRegisters a callback function to be executed after each test within the current suite has completed.
This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.
**Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. , beforeEach function beforeEach<ExtraContext = object>(fn: BeforeEachListener<ExtraContext>, timeout?: number): voidRegisters a callback function to be executed before each test within the current suite.
This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.
**Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. } from 'vitest';
let rt let rt: TestRuntime : TestRuntime type TestRuntime = Runtime & {
mockCondition<S extends TriggerSchema, K extends ConditionKey<S>>(trigger: Trigger<S>, name: K, valueOrGetter: ConditionMap<S>[K] | (() => ConditionMap<S>[K])): RegistrationToken;
mockAction<S extends TriggerSchema, K extends ActionKey<S>>(trigger: Trigger<S>, name: K, handler: ActionFn<ActionMap<S>[K]>): RegistrationToken;
flushMicrotasks(): Promise<void>;
}
;
beforeEach beforeEach<object>(fn: BeforeEachListener<object>, timeout?: number): voidRegisters a callback function to be executed before each test within the current suite.
This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.
**Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. (() => {
rt let rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ();
});
afterEach afterEach<object>(fn: AfterEachListener<object>, timeout?: number): voidRegisters a callback function to be executed after each test within the current suite has completed.
This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.
**Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. (() => {
rt let rt: TestRuntime .dispose function dispose(): voidTear down the runtime completely. (); // aborts in-flight handlers, drops registrations
});With middleware
Section titled “With middleware”import { createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime } from '@triggery/testing';
import type { Middleware type Middleware = {
readonly name: string;
onFire?(ctx: FireContext): void | {
cancel: true;
reason: string;
};
onBeforeMatch?(ctx: MatchContext): void;
onSkip?(ctx: SkipContext): void;
onActionStart?(ctx: ActionContext): void;
onActionEnd?(ctx: ActionContext & {
durationMs: number;
result?: unknown;
}): void;
onError?(ctx: ActionContext & {
error: unknown;
}): void;
onCascade?(ctx: CascadeContext): void;
}
} from '@triggery/core';
const trace const trace: Middleware : Middleware type Middleware = {
readonly name: string;
onFire?(ctx: FireContext): void | {
cancel: true;
reason: string;
};
onBeforeMatch?(ctx: MatchContext): void;
onSkip?(ctx: SkipContext): void;
onActionStart?(ctx: ActionContext): void;
onActionEnd?(ctx: ActionContext & {
durationMs: number;
result?: unknown;
}): void;
onError?(ctx: ActionContext & {
error: unknown;
}): void;
onCascade?(ctx: CascadeContext): void;
}
= {
name name: string : 'trace',
onActionEnd onActionEnd?(ctx: ActionContext & {
durationMs: number;
result?: unknown;
}): void
({ actionName actionName: string , durationMs durationMs: number }) {
console var console: Console .log Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) (actionName actionName: string , durationMs durationMs: number );
},
};
const rt const rt: TestRuntime = createTestRuntime function createTestRuntime(options?: TestRuntimeOptions): TestRuntime ({ middleware middleware?: readonly Middleware[] | undefinedGlobal middleware applied to every trigger in this runtime. : [trace const trace: Middleware ] });Related
Section titled “Related” mockCondition Stub a condition for tests.
mockAction Stub an action handler.
flushMicrotasks Drain pending microtasks.
createFakeScheduler Virtual-clock scheduler for debounce / throttle tests.