@probitas-test/core
Core scenario definition types and utilities.
This package provides the fundamental type definitions that represent scenario structures, along with utilities for loading scenario files and filtering scenarios using selectors. It serves as the foundation layer that other Probitas packages build upon.
Links
- GitHub Repository
- @probitas-test/probitas - Main package (recommended for most users)
Related Packages
| Package | Description |
|---|---|
| @probitas-test/builder | Uses these types to build scenarios |
| @probitas-test/runner | Executes scenario definitions |
| @probitas-test/discover | Discovers scenario files to load |
Type Definitions
The type system is designed around immutable data structures:
ScenarioDefinition- Complete scenario with name, options, and entriesStepDefinition- Individual step with function, options, and sourceSetupDefinition- Setup hook with cleanup function supportResourceDefinition- Named resource with fn functionStepContext- Context object passed to all functionsEntry- Discriminated union of step, setup, or resource
Options Types
ScenarioOptions- Scenario-level configuration (tags, default step options)StepOptions- Step execution settings (timeout, retry strategy)- Import
Originfrom@probitas-test/core/originfor file and line information
Function Types
StepFunction- Signature for step execution functionsSetupFunction- Signature for setup hooks (returns cleanup)ResourceFunction- Signature for resource creation functionsSetupCleanup- Return type of setup functions
Loader Utilities
loadScenarios- Load scenario definitions from file pathsLoadScenariosOptions- Options for the loader
Selector Utilities
Selectors provide powerful filtering capabilities:
applySelectors- Filter scenarios using selector stringsparseSelector- Parse selector string into Selector objectsmatchesSelector- Check if a scenario matches a single selectorSelector- Parsed selector objectSelectorType- Type of selector ("tag" or "name")
Installation
npm install @probitas-test/coreInterfaces
#ScenarioDefinition
interface ScenarioDefinitionComplete, immutable definition of a scenario.
This is the core type produced by the builder and consumed by the runner. It contains everything needed to execute a scenario: its name, options, and ordered sequence of entries (steps, resources, setups).
Scenario definitions are:
- Immutable: The entries array is frozen after creation
- Self-contained: All options have defaults applied
- Portable: Can be serialized (minus functions) for tooling
Examples
Typical scenario structure
import type { ScenarioDefinition } from "@probitas-test/core";
// Created by: scenario("Login Flow").step(...).build()
const definition: ScenarioDefinition = {
name: "Login Flow",
tags: ["auth", "smoke"],
steps: [
{
kind: "resource",
name: "api",
fn: () => fetch,
timeout: 30000,
retry: { maxAttempts: 1, backoff: "linear" },
},
{
kind: "step",
name: "Login",
fn: () => {},
timeout: 30000,
retry: { maxAttempts: 1, backoff: "linear" },
},
{
kind: "step",
name: "Verify",
fn: () => {},
timeout: 30000,
retry: { maxAttempts: 1, backoff: "linear" },
},
],
origin: { path: "/tests/auth.probitas.ts", line: 5 },
};
console.log(definition);
| Name | Description |
|---|---|
name | Human-readable scenario name (displayed in reports and CLI) |
origin | Origin where the scenario was defined |
steps | Ordered sequence of entries (resources → setups → steps) |
tags | Tags for filtering and organizing scenarios. |
timeout | Maximum time in milliseconds for the entire scenario to complete. |
Properties
- readonly
namestringHuman-readable scenario name (displayed in reports and CLI)
- readonly
origin?OriginOrigin where the scenario was defined
Ordered sequence of entries (resources → setups → steps)
- readonly
timeout?numberMaximum time in milliseconds for the entire scenario to complete.
When set, overrides the RunOptions timeout for this specific scenario. When timeout occurs, a
ScenarioTimeoutErroris thrown.
#ScenarioMetadata
interface ScenarioMetadataSerializable scenario metadata (without executable functions).
Used by the JSON reporter and tooling to output scenario information without including non-serializable function references.
Examples
JSON reporter output
{
"name": "Login Flow",
"options": { "tags": ["auth"], "stepOptions": { ... } },
"entries": [
{ "kind": "step", "value": { "name": "Login", "options": { ... } } }
],
"origin": { "path": "/tests/auth.probitas.ts", "line": 5 }
}
| Name | Description |
|---|---|
name | Scenario name |
origin | Origin where the scenario was defined |
steps | Entry metadata (functions omitted for serialization) |
tags | Tags for filtering and organizing scenarios. |
timeout | Maximum time in milliseconds for the entire scenario to complete. |
Properties
- readonly
namestringScenario name
- readonly
origin?OriginOrigin where the scenario was defined
Entry metadata (functions omitted for serialization)
- readonly
timeout?numberMaximum time in milliseconds for the entire scenario to complete.
When set, overrides the RunOptions timeout for this specific scenario.
#ScenarioOptions
interface ScenarioOptionsConfiguration options for scenario execution.
Defines metadata and default behavior for an entire scenario.
Examples
const options: ScenarioOptions = {
tags: ["api", "integration", "slow"],
timeout: 30000,
stepOptions: {
timeout: 60000,
retry: { maxAttempts: 2, backoff: "linear" }
}
};
| Name | Description |
|---|---|
stepOptions | Default options applied to all steps in this scenario. |
tags | Tags for filtering and organizing scenarios. |
timeout | Maximum time in milliseconds for the entire scenario to complete. |
Properties
Default options applied to all steps in this scenario.
Individual steps can override these defaults by specifying their own options in the
.step()call.- readonly
timeout?numberMaximum time in milliseconds for the entire scenario to complete.
When specified, this timeout applies to the total execution time of all steps in the scenario. If the scenario exceeds this limit, a
ScenarioTimeoutErroris thrown.Priority: scenario timeout > RunOptions timeout
#StepContext
interface StepContextExecution context provided to steps, resources, and setup hooks.
The context provides access to:
- Previous step results with full type inference
- All accumulated results as a typed tuple
- Named resources registered with
.resource() - Shared storage for cross-step communication
- Abort signal for timeout and cancellation handling
Examples
Accessing previous result
import type { StepContext } from "@probitas-test/core";
// Steps receive context with the previous step's result
const stepFn = (ctx: StepContext) => {
// ctx.previous contains the result from the previous step
const prev = ctx.previous as { id: number };
console.log(prev.id); // Access typed result
};
console.log(stepFn);
Using shared store
import type { StepContext } from "@probitas-test/core";
// The store is shared across all steps in a scenario
const setupFn = (ctx: StepContext) => {
ctx.store.set("startTime", Date.now());
};
const stepFn = (ctx: StepContext) => {
const start = ctx.store.get("startTime") as number;
console.log(`Elapsed: ${Date.now() - start}ms`);
};
console.log(setupFn, stepFn);
| Name | Description |
|---|---|
index | Current step index (0-based). |
previous | Result from the previous step. |
resources | Named resources registered with `.resource()`. |
results | All accumulated results as a typed tuple. |
signal | Abort signal that fires on timeout or manual cancellation. |
store | Shared key-value storage for cross-step communication. |
Properties
- readonly
indexnumberCurrent step index (0-based).
Useful for conditional logic based on position in the scenario.
- readonly
previousunknownResult from the previous step.
Fully typed based on what the previous step returned. For the first step, this is
unknown. - readonly
resourcesRecord<string, unknown>Named resources registered with
.resource().Resources are typed based on their registration:
import type { StepContext } from "@probitas-test/core"; interface DbResource { query(sql: string): unknown; } // Access resources registered with .resource() const stepFn = (ctx: StepContext) => { const db = ctx.resources["db"] as DbResource; return db.query("SELECT 1"); }; console.log(stepFn); - readonly
resultsreadonly unknown[]All accumulated results as a typed tuple.
Allows accessing any previous result by index:
import type { StepContext } from "@probitas-test/core"; const stepFn = (ctx: StepContext) => { ctx.results[0]; // First step's result ctx.results[1]; // Second step's result }; console.log(stepFn); - readonly
signal?AbortSignalAbort signal that fires on timeout or manual cancellation.
Pass this to fetch() or other APIs that support AbortSignal for proper timeout handling.
- readonly
storeMap<string, unknown>Shared key-value storage for cross-step communication.
Use this for data that doesn't fit the step result pattern, such as metadata or configuration set during setup.
#StepDefinition
interface StepDefinition<T = unknown>Immutable definition of a scenario step.
Contains all information needed to execute a single step: the step function, its options, and debugging metadata.
Step definitions are created by the builder and consumed by the runner. They are immutable and should not be modified after creation.
| Name | Description |
|---|---|
fn | Step function to execute |
kind | — |
name | Human-readable step name (displayed in reports) |
origin | Origin where the step was defined (for error messages) |
retry | Retry configuration for handling transient failures |
timeout | Maximum execution time in milliseconds. |
Properties
Step function to execute
- readonly
kind"step" | "resource" | "setup" - readonly
namestringHuman-readable step name (displayed in reports)
- readonly
origin?OriginOrigin where the step was defined (for error messages)
- readonly
retry?{ readonly backoff?: "linear" | "exponential"; readonly maxAttempts?: number }Retry configuration for handling transient failures
- readonly
timeout?numberMaximum execution time in milliseconds.
If the step takes longer, a
TimeoutErroris thrown. Default: 30000 (30 seconds)
#StepOptions
interface StepOptionsConfiguration options for individual step execution.
Controls timeout and retry behavior for a step. These options can be set at:
- Step level (highest priority)
- Scenario level (applies to all steps in scenario)
- Default values (30s timeout, no retry)
Examples
const options: StepOptions = {
timeout: 60000, // 60 seconds
retry: {
maxAttempts: 3,
backoff: "exponential" // Waits 1s, 2s, 4s between retries
}
};
| Name | Description |
|---|---|
retry | Retry configuration for handling transient failures |
timeout | Maximum execution time in milliseconds. |
Properties
- readonly
retry?{ readonly backoff?: "linear" | "exponential"; readonly maxAttempts?: number }Retry configuration for handling transient failures
- readonly
timeout?numberMaximum execution time in milliseconds.
If the step takes longer, a
TimeoutErroris thrown. Default: 30000 (30 seconds)
Types
#SetupCleanup
type SetupCleanup = void | (() => void | Promise<void>) | Disposable | AsyncDisposableCleanup handler returned by setup functions.
Setup functions can return various cleanup mechanisms that are automatically invoked after the scenario completes (regardless of success or failure).
Supported cleanup patterns:
void/undefined: No cleanup needed() => void: Synchronous cleanup function() => Promise<void>: Async cleanup functionDisposable: Object with[Symbol.dispose]()methodAsyncDisposable: Object with[Symbol.asyncDispose]()method
Examples
Cleanup function
import type { SetupCleanup } from "@probitas-test/core";
// Setup functions can return a cleanup function
const setupWithCleanup = (): SetupCleanup => {
const file = Deno.makeTempFileSync();
return () => Deno.removeSync(file); // Cleanup function
};
console.log(setupWithCleanup);
Disposable object
import type { SetupCleanup } from "@probitas-test/core";
// Setup functions can return an AsyncDisposable
const setupWithDisposable = async (): Promise<SetupCleanup> => {
const conn: AsyncDisposable = {
async [Symbol.asyncDispose]() {
// cleanup logic
},
};
return conn;
};
console.log(setupWithDisposable);
#StepFunction
type StepFunction<T = unknown> = (ctx: StepContext) => T | Promise<T>Function signature for step execution.
A step function receives the execution context and returns a value (sync or async) that becomes available to subsequent steps.
Examples
Sync step returning data
import type { StepFunction } from "@probitas-test/core";
const step: StepFunction<{ name: string }> = (_ctx) => {
return { name: "Alice" };
};
Async step with API call
import type { StepFunction } from "@probitas-test/core";
interface User {
id: number;
name: string;
}
const step: StepFunction<User> = async (ctx) => {
const response = await fetch("/api/user", { signal: ctx.signal });
return response.json();
};
#StepMetadata
type StepMetadata = Omit<StepDefinition, "fn">Serializable step metadata (without the function).
Used for JSON output, tooling, and inspection without executing code.
