@probitas/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.

PackageDescription
@probitas/builderUses these types to build scenarios
@probitas/runnerExecutes scenario definitions
@probitas/discoverDiscovers scenario files to load

Type Definitions

The type system is designed around immutable data structures:

Options Types

  • ScenarioOptions - Scenario-level configuration (tags, default step options)
  • StepOptions - Step execution settings (timeout, retry strategy)
  • Import Origin from @probitas/core/origin for file and line information

Function Types

Loader Utilities

Selector Utilities

Selectors provide powerful filtering capabilities:

Installation

deno add jsr:@probitas/core

Interfaces

interface

#ScenarioDefinition

interface ScenarioDefinition

Complete, 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).

Examples

Typical scenario structure

import type { ScenarioDefinition } from "@probitas/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);
NameDescription
nameHuman-readable scenario name (displayed in reports and CLI)
tagsTags for filtering and organizing scenarios.
stepsOrdered sequence of entries (resources → setups → steps)
originOrigin where the scenario was defined
Properties
  • readonlynamestring

    Human-readable scenario name (displayed in reports and CLI)

  • readonlytagsreadonly string[]

    Tags for filtering and organizing scenarios.

    Tags can be used with the CLI to run specific subsets:

    probitas run -s "tag:api"           # Run scenarios tagged "api"
    probitas run -s "tag:api,tag:fast"  # Run scenarios with both tags
    probitas run -s "!tag:slow"         # Exclude slow scenarios
    
  • readonlystepsreadonly StepDefinition[]

    Ordered sequence of entries (resources → setups → steps)

  • readonlyorigin?Origin

    Origin where the scenario was defined

interface

#ScenarioMetadata

interface ScenarioMetadata

Serializable 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 }
}
NameDescription
nameScenario name
tagsTags for filtering and organizing scenarios.
stepsEntry metadata (functions omitted for serialization)
originOrigin where the scenario was defined
Properties
  • readonlynamestring

    Scenario name

  • readonlytagsreadonly string[]

    Tags for filtering and organizing scenarios.

    Tags can be used with the CLI to run specific subsets:

    probitas run -s "tag:api"           # Run scenarios tagged "api"
    probitas run -s "tag:api,tag:fast"  # Run scenarios with both tags
    probitas run -s "!tag:slow"         # Exclude slow scenarios
    
  • readonlystepsreadonly StepMetadata[]

    Entry metadata (functions omitted for serialization)

  • readonlyorigin?Origin

    Origin where the scenario was defined

interface

#ScenarioOptions

interface ScenarioOptions

Configuration options for scenario execution.

Defines metadata and default behavior for an entire scenario.

Examples
const options: ScenarioOptions = {
  tags: ["api", "integration", "slow"],
  stepOptions: {
    timeout: 60000,
    retry: { maxAttempts: 2, backoff: "linear" }
  }
};
NameDescription
tagsTags for filtering and organizing scenarios.
stepOptionsDefault options applied to all steps in this scenario.
Properties
  • readonlytags?readonly string[]

    Tags for filtering and organizing scenarios.

    Tags can be used with the CLI to run specific subsets:

    probitas run -s "tag:api"           # Run scenarios tagged "api"
    probitas run -s "tag:api,tag:fast"  # Run scenarios with both tags
    probitas run -s "!tag:slow"         # Exclude slow scenarios
    
  • readonlystepOptions?StepOptions

    Default options applied to all steps in this scenario.

    Individual steps can override these defaults by specifying their own options in the .step() call.

interface

#StepContext

interface StepContext

Execution 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/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/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);
NameDescription
indexCurrent step index (0-based).
previousResult from the previous step.
resultsAll accumulated results as a typed tuple.
storeShared key-value storage for cross-step communication.
resourcesNamed resources registered with `.resource()`.
signalAbort signal that fires on timeout or manual cancellation.
Properties
  • readonlyindexnumber

    Current step index (0-based).

    Useful for conditional logic based on position in the scenario.

  • readonlypreviousunknown

    Result from the previous step.

    Fully typed based on what the previous step returned. For the first step, this is unknown.

  • readonlyresultsreadonly unknown[]

    All accumulated results as a typed tuple.

    Allows accessing any previous result by index:

    import type { StepContext } from "@probitas/core";
    
    const stepFn = (ctx: StepContext) => {
      ctx.results[0]; // First step's result
      ctx.results[1]; // Second step's result
    };
    console.log(stepFn);
    
  • readonlystoreMap<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.

  • readonlyresourcesRecord<string, unknown>

    Named resources registered with .resource().

    Resources are typed based on their registration:

    import type { StepContext } from "@probitas/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);
    
  • readonlysignal?AbortSignal

    Abort signal that fires on timeout or manual cancellation.

    Pass this to fetch() or other APIs that support AbortSignal for proper timeout handling.

interface

#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.

NameDescription
kind
nameHuman-readable step name (displayed in reports)
fnStep function to execute
timeoutMaximum execution time in milliseconds.
retryRetry configuration for handling transient failures
originOrigin where the step was defined (for error messages)
Properties
  • readonlykind"step" | "resource" | "setup"
  • readonlynamestring

    Human-readable step name (displayed in reports)

  • readonlyfnStepFunction<T>

    Step function to execute

  • readonlytimeoutnumber

    Maximum execution time in milliseconds.

    If the step takes longer, a TimeoutError is thrown. Default: 30000 (30 seconds)

  • readonlyretry{ maxAttempts: number; backoff: "linear" | "exponential" }

    Retry configuration for handling transient failures

  • readonlyorigin?Origin

    Origin where the step was defined (for error messages)

interface

#StepOptions

interface StepOptions

Configuration options for individual step execution.

Controls timeout and retry behavior for a step. These options can be set at:

  1. Step level (highest priority)
  2. Scenario level (applies to all steps in scenario)
  3. 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
  }
};
NameDescription
timeoutMaximum execution time in milliseconds.
retryRetry configuration for handling transient failures
Properties
  • readonlytimeout?number

    Maximum execution time in milliseconds.

    If the step takes longer, a TimeoutError is thrown. Default: 30000 (30 seconds)

  • readonlyretry?{ maxAttempts?: number; backoff?: "linear" | "exponential" }

    Retry configuration for handling transient failures

Types

type

#SetupCleanup

type SetupCleanup = void | unknown | Disposable | AsyncDisposable

Cleanup 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 function
  • Disposable: Object with [Symbol.dispose]() method
  • AsyncDisposable: Object with [Symbol.asyncDispose]() method
type

#StepFunction

type StepFunction<T = unknown> = (ctx: StepContext) => unknown

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.

type

#StepMetadata

type StepMetadata = Omit<StepDefinition, "fn">

Serializable step metadata (without the function).

Used for JSON output, tooling, and inspection without executing code.

Search Documentation