# @probitas/scenario > Version: 0.2.9 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](https://github.com/jsr-probitas/probitas) - [@probitas/probitas](https://jsr.io/@probitas/probitas) - Main package (recommended for most users) ## Related Packages | Package | Description | |---------|-------------| | [@probitas/builder](https://jsr.io/@probitas/builder) | Uses these types to build scenarios | | [@probitas/runner](https://jsr.io/@probitas/runner) | Executes scenario definitions | | [@probitas/discover](https://jsr.io/@probitas/discover) | Discovers scenario files to load | ## Type Definitions The type system is designed around immutable data structures: - {@linkcode ScenarioDefinition} - Complete scenario with name, options, and entries - {@linkcode StepDefinition} - Individual step with function, options, and source - {@linkcode SetupDefinition} - Setup hook with cleanup function support - {@linkcode ResourceDefinition} - Named resource with fn function - {@linkcode StepContext} - Context object passed to all functions - {@linkcode Entry} - Discriminated union of step, setup, or resource ## Options Types - {@linkcode ScenarioOptions} - Scenario-level configuration (tags, default step options) - {@linkcode StepOptions} - Step execution settings (timeout, retry strategy) - {@linkcode Source} - File and line number for error reporting ## Function Types - {@linkcode StepFunction} - Signature for step execution functions - {@linkcode SetupFunction} - Signature for setup hooks (returns cleanup) - {@linkcode ResourceFunction} - Signature for resource creation functions - {@linkcode SetupCleanup} - Return type of setup functions ## Loader Utilities - {@linkcode loadScenarios} - Load scenario definitions from file paths - {@linkcode LoadScenariosOptions} - Options for the loader ## Selector Utilities Selectors provide powerful filtering capabilities: - {@linkcode applySelectors} - Filter scenarios using selector strings - {@linkcode parseSelector} - Parse selector string into Selector objects - {@linkcode matchesSelector} - Check if a scenario matches a single selector - {@linkcode Selector} - Parsed selector object - {@linkcode SelectorType} - Type of selector ("tag" or "name") ## Interfaces ### `ScenarioOptions` ```typescript interface ScenarioOptions ``` Configuration options for scenario execution. Defines metadata and default behavior for an entire scenario. **Properties:** - [readonly] `tags?`: `readonly string[]` — Tags for filtering and organizing scenarios. Tags can be used with the CLI to run specific subsets: ```bash 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 ``` - [readonly] `stepOptions?`: `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. **Example:** ```ts const options: ScenarioOptions = { tags: ["api", "integration", "slow"], stepOptions: { timeout: 60000, retry: { maxAttempts: 2, backoff: "linear" } } }; ``` --- ### `ScenarioDefinition` ```typescript 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). **Properties:** - [readonly] `name`: `string` — Human-readable scenario name (displayed in reports and CLI) - [readonly] `tags`: `readonly string[]` — Tags for filtering and organizing scenarios. Tags can be used with the CLI to run specific subsets: ```bash 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 ``` - [readonly] `steps`: `readonly StepDefinition[]` — Ordered sequence of entries (resources → setups → steps) - [readonly] `source?`: `Source` — Source source where the scenario was defined **Example:** Typical scenario structure ```ts // Created by: scenario("Login Flow").step(...).build() const definition: ScenarioDefinition = { name: "Login Flow", options: { tags: ["auth", "smoke"], stepOptions: { timeout: 30000, retry: { maxAttempts: 1, backoff: "linear" } } }, entries: [ { kind: "resource", value: { name: "api", fn: ... } }, { kind: "step", value: { name: "Login", fn: ..., options: ... } }, { kind: "step", value: { name: "Verify", fn: ..., options: ... } } ], source: { file: "/tests/auth.probitas.ts", line: 5 } }; ``` --- ### `ScenarioMetadata` ```typescript 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. **Properties:** - [readonly] `name`: `string` — Scenario name - [readonly] `tags`: `readonly string[]` — Tags for filtering and organizing scenarios. Tags can be used with the CLI to run specific subsets: ```bash 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 ``` - [readonly] `steps`: `readonly StepMetadata[]` — Entry metadata (functions omitted for serialization) - [readonly] `source?`: `Source` — Source source where the scenario was defined **Example:** JSON reporter output ```json { "name": "Login Flow", "options": { "tags": ["auth"], "stepOptions": { ... } }, "entries": [ { "kind": "step", "value": { "name": "Login", "options": { ... } } } ], "source": { "file": "/tests/auth.probitas.ts", "line": 5 } } ``` --- ### `Source` ```typescript interface Source ``` Source source in a file for error reporting and debugging. Captured automatically when defining scenarios, steps, and setups. Used by reporters to show meaningful stack traces. **Properties:** - [readonly] `file`: `string` — Absolute file path where the element was defined - [readonly] `line?`: `number` — Line number in the file (1-indexed) - [readonly] `column?`: `number` — Column number in the file (1-indexed) **Example:** ```ts // Example source object const source: Source = { file: "/project/tests/auth.probitas.ts", line: 42 }; ``` --- ### `StepOptions` ```typescript 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) **Properties:** - [readonly] `timeout?`: `number` — Maximum execution time in milliseconds. If the step takes longer, a {@linkcode TimeoutError} is thrown. Default: 30000 (30 seconds) - [readonly] `retry?`: `{ maxAttempts?: number; backoff?: "linear" | "exponential" }` — Retry configuration for handling transient failures **Example:** ```ts const options: StepOptions = { timeout: 60000, // 60 seconds retry: { maxAttempts: 3, backoff: "exponential" // Waits 1s, 2s, 4s between retries } }; ``` --- ### `StepContext` ```typescript 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 **Properties:** - [readonly] `index`: `number` — Current step index (0-based). Useful for conditional logic based on position in the scenario. - [readonly] `previous`: `unknown` — Result from the previous step. Fully typed based on what the previous step returned. For the first step, this is `unknown`. - [readonly] `results`: `readonly unknown[]` — All accumulated results as a typed tuple. Allows accessing any previous result by index: ```ts ctx.results[0] // First step's result ctx.results[1] // Second step's result ``` - [readonly] `store`: `Map` — 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. - [readonly] `resources`: `Record` — Named resources registered with `.resource()`. Resources are typed based on their registration: ```ts .resource("db", () => createDbConnection()) .step((ctx) => ctx.resources.db.query(...)) ``` - [readonly] `signal?`: `AbortSignal` — Abort signal that fires on timeout or manual cancellation. Pass this to fetch() or other APIs that support AbortSignal for proper timeout handling. **Example:** Accessing previous result ```ts scenario("Chained Steps") .step("First", () => ({ id: 123 })) .step("Second", (ctx) => { console.log(ctx.previous.id); // 123 (typed as number) }) .build(); ``` Using shared store ```ts scenario("Store Example") .setup((ctx) => { ctx.store.set("startTime", Date.now()); }) .step("Check duration", (ctx) => { const start = ctx.store.get("startTime") as number; console.log(`Elapsed: ${Date.now() - start}ms`); }) .build(); ``` --- ### `StepDefinition` ```typescript interface StepDefinition ``` Immutable definition of a scenario step. Contains all information needed to execute a single step: the step function, its options, and debugging metadata. **Properties:** - [readonly] `kind`: `"step" | "resource" | "setup"` - [readonly] `name`: `string` — Human-readable step name (displayed in reports) - [readonly] `fn`: `StepFunction` — Step function to execute - [readonly] `timeout`: `number` — Maximum execution time in milliseconds. If the step takes longer, a {@linkcode TimeoutError} is thrown. Default: 30000 (30 seconds) - [readonly] `retry`: `{ maxAttempts: number; backoff: "linear" | "exponential" }` — Retry configuration for handling transient failures - [readonly] `source?`: `Source` — Source source where the step was defined (for error messages) --- ### `LoadScenariosOptions` ```typescript interface LoadScenariosOptions ``` Options for loading scenarios from files. **Properties:** - `onImportError?`: `(scenarioFile: string | URL, err: unknown) => unknown` — Callback invoked when a scenario file fails to import. Use this for custom error handling or logging. If not provided, import errors are logged but otherwise silently ignored (the file is skipped and loading continues with other files). **Example:** Handling import errors ```ts const scenarios = await loadScenarios(files, { onImportError: (file, err) => { console.error(`Failed to load ${file}:`, err); } }); ``` --- ### `Selector` ```typescript interface Selector ``` Parsed selector for filtering scenarios. Created by {@linkcode parseSelector}. Used by {@linkcode matchesSelector} and {@linkcode applySelectors} to filter scenarios. **Properties:** - [readonly] `type`: `SelectorType` — Type of match: "tag" for tags, "name" for scenario name - [readonly] `value`: `RegExp` — Regular expression pattern for matching (case-insensitive) - [readonly] `negated`: `boolean` — If true, selector matches scenarios that do NOT match the pattern **Example:** ```ts // Result of parseSelector("tag:api") const selector: Selector = { type: "tag", value: /api/i, negated: false }; ``` --- ## Functions ### `loadScenarios` ```typescript async function loadScenarios( scenarioFiles: readonly unknown[], options?: LoadScenariosOptions, ): Promise ``` Load scenario definitions from file paths. Dynamically imports scenario files and extracts their default exports. Supports both single scenario exports and arrays of scenarios. **Parameters:** - `scenarioFiles`: `readonly unknown[]` — - Absolute file paths or file:// URLs to load - `options`: `LoadScenariosOptions` (optional) — - Optional error handling configuration **Returns:** `Promise` Array of loaded scenario definitions **Example:** Loading discovered files ```ts import { discoverScenarioFiles } from "@probitas/discover"; import { loadScenarios } from "@probitas/scenario"; const files = await discoverScenarioFiles({ includes: ["**\/*.probitas.ts"] }); const scenarios = await loadScenarios(files); ``` Loading specific files ```ts const scenarios = await loadScenarios([ "/project/tests/auth.probitas.ts", "/project/tests/api.probitas.ts" ]); ``` --- ### `parseSelector` ```typescript function parseSelector(input: string): Selector[] ``` Parse a selector string into an array of Selector objects. Selector syntax: - `tag:pattern` - Match scenarios with a tag matching the pattern - `name:pattern` - Match scenarios with a name matching the pattern - `pattern` - Shorthand for `name:pattern` - `!selector` - Negate the selector (exclude matches) - `sel1,sel2` - Combine selectors with AND logic **Parameters:** - `input`: `string` — - Selector string to parse **Returns:** `Selector[]` Array of parsed Selector objects (comma-separated = multiple selectors) **Example:** Basic selectors ```ts parseSelector("tag:api"); // → [{ type: "tag", value: /api/i, negated: false }] parseSelector("login"); // Shorthand for name:login // → [{ type: "name", value: /login/i, negated: false }] ``` Negation ```ts parseSelector("!tag:slow"); // → [{ type: "tag", value: /slow/i, negated: true }] ``` Combined selectors (AND logic) ```ts parseSelector("tag:api,!tag:slow"); // → [ // { type: "tag", value: /api/i, negated: false }, // { type: "tag", value: /slow/i, negated: true } // ] ``` --- ### `matchesSelector` ```typescript function matchesSelector( scenario: ScenarioDefinition, selector: Selector, ): boolean ``` Check if a scenario matches a single selector. Tests whether the scenario's name or tags match the selector's pattern. Does not apply negation - returns the raw match result. **Parameters:** - `scenario`: `ScenarioDefinition` — - Scenario definition to test - `selector`: `Selector` — - Selector containing the pattern to match **Returns:** `boolean` `true` if the scenario matches the pattern (before negation) **Example:** ```ts const scenario = { name: "Login Test", options: { tags: ["auth"] } }; matchesSelector(scenario, { type: "tag", value: /auth/i, negated: false }); // → true matchesSelector(scenario, { type: "name", value: /login/i, negated: false }); // → true matchesSelector(scenario, { type: "tag", value: /api/i, negated: false }); // → false ``` --- ### `applySelectors` ```typescript function applySelectors( scenarios: ScenarioDefinition[], selectorInputs: readonly string[], ): ScenarioDefinition[] ``` Filter scenarios using selector strings with AND/OR/NOT logic. This is the main entry point for scenario filtering. It combines multiple selector strings with the following logic: - **Multiple strings**: OR condition (match any) - **Comma-separated in string**: AND condition (match all) - **`!` prefix**: NOT condition (exclude matches) **Parameters:** - `scenarios`: `ScenarioDefinition[]` — - Array of scenarios to filter - `selectorInputs`: `readonly string[]` — - Selector strings from CLI `-s` flags **Returns:** `ScenarioDefinition[]` Filtered scenarios matching the selector criteria **Example:** OR logic - match any selector string ```ts // Scenarios with "api" tag OR "db" tag applySelectors(scenarios, ["tag:api", "tag:db"]); ``` AND logic - match all within comma-separated ```ts // Scenarios with BOTH "api" AND "critical" tags applySelectors(scenarios, ["tag:api,tag:critical"]); ``` Combined AND/OR/NOT ```ts // (api AND critical) OR (db AND !slow) applySelectors(scenarios, [ "tag:api,tag:critical", "tag:db,!tag:slow" ]); ``` Exclude by name pattern ```ts // All scenarios except those with "wip" in name applySelectors(scenarios, ["!wip"]); ``` --- ## Types ### `SetupCleanup` ```typescript 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`: Async cleanup function - `Disposable`: Object with `[Symbol.dispose]()` method - `AsyncDisposable`: Object with `[Symbol.asyncDispose]()` method --- ### `StepFunction` ```typescript type StepFunction = (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. --- ### `StepMetadata` ```typescript type StepMetadata = Omit ``` Serializable step metadata (without the function). Used for JSON output, tooling, and inspection without executing code. --- ### `SelectorType` ```typescript type SelectorType = "tag" | "name" ``` Type of selector for filtering scenarios. - `"tag"`: Match against scenario tags - `"name"`: Match against scenario name --- ## Related Links ### This Package - [`LoadScenariosOptions`](https://probitas-test.github.io/documents/api/scenario#LoadScenariosOptions) - [`ScenarioDefinition`](https://probitas-test.github.io/documents/api/scenario#ScenarioDefinition) - [`Selector`](https://probitas-test.github.io/documents/api/scenario#Selector) - [`SelectorType`](https://probitas-test.github.io/documents/api/scenario#SelectorType) - [`Source`](https://probitas-test.github.io/documents/api/scenario#Source) - [`StepContext`](https://probitas-test.github.io/documents/api/scenario#StepContext) - [`StepDefinition`](https://probitas-test.github.io/documents/api/scenario#StepDefinition) - [`StepFunction`](https://probitas-test.github.io/documents/api/scenario#StepFunction) - [`StepMetadata`](https://probitas-test.github.io/documents/api/scenario#StepMetadata) - [`StepOptions`](https://probitas-test.github.io/documents/api/scenario#StepOptions) ### Built-in Types - [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) - [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) - [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) - [`Record`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type) - [`RegExp`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) --- *Last updated: 2026-01-12*