Skip to main content

Context Object (ctx)

Every callback in LiveDoc receives a ctx parameter — a dynamic context object that provides read-only metadata about the current feature, scenario, step, rule, or specification. The available properties depend on where the callback is used.

import { feature, scenario, given } from "@swedevtools/livedoc-vitest";

feature("Shopping Cart @ecommerce", (ctx) => {
// ctx.feature is available here
scenario("Add an item", (ctx) => {
// ctx.feature + ctx.scenario available here
given("an empty cart", (ctx) => {
// ctx.feature + ctx.scenario + ctx.step available here
console.log(ctx.feature.title); // "Shopping Cart"
console.log(ctx.feature.tags); // ["ecommerce"]
console.log(ctx.step.title); // "an empty cart"
});
});
});

Reference

Context Availability by Location

PropertyfeaturescenariostepsbackgroundscenarioOutlinespecificationruleruleOutline
ctx.feature
ctx.scenario
ctx.step✓ (steps)✓ (steps)
ctx.example
ctx.background
ctx.afterBackground(fn)
ctx.specification
ctx.rule

ctx.feature

FeatureContext

Available in feature(), scenario(), scenarioOutline(), background(), and all step callbacks within a feature.

PropertyTypeDescription
filenamestringFile path of the .Spec.ts file
titlestringFeature title (first line of title string)
descriptionstringDescription text (non-tag, non-title lines)
tagsstring[]Tags extracted from @-prefixed lines
feature(`Shopping Cart
@ecommerce @critical
As a customer I want to manage my cart
`, (ctx) => {
scenario("Metadata", () => {
given("we inspect the feature", () => {
expect(ctx.feature.title).toBe("Shopping Cart");
expect(ctx.feature.tags).toEqual(["ecommerce", "critical"]);
expect(ctx.feature.description).toContain("manage my cart");
expect(ctx.feature.filename).toContain(".Spec.ts");
});
});
});

ctx.scenario

ScenarioContext

Available in scenario(), scenarioOutline(), and all step callbacks within them.

PropertyTypeDescription
titlestringScenario title
descriptionstringDescription text
tagsstring[]Tags extracted from the title
givenStepContext?The first given step context (if any)
andStepContext[]Array of and step contexts
stepsStepContext[]All steps in the scenario
scenario(`Process a refund
@payments @regression
Customer requests a refund within 30 days
`, (ctx) => {
given("a completed order", () => {
expect(ctx.scenario.title).toBe("Process a refund");
expect(ctx.scenario.tags).toEqual(["payments", "regression"]);
});
});

ctx.step

StepContext

Available in all step callbacks (given, when, then, and, but) and in rule() callbacks.

PropertyTypeDescription
titlestringThe step title as written
displayTitlestringTitle with secondary bindings resolved
typestringStep type: "given", "when", "then", "and", "but"
valuesany[]Type-coerced quoted values from the title
valuesRawstring[]Raw string values before coercion
paramsRecord<string, any>Type-coerced named parameters from <name:value>
paramsRawRecord<string, string>Raw string named parameters
docStringstringRaw doc string content (from """...""")
docStringAsEntityanyParsed JSON from doc string, or undefined
tableobject[]Multi-column table: array of row objects (header keys)
tableAsEntityobjectTwo-column table as key-value object
tableAsSingleListany[]Single-column table as flat array
dataTableany[][]Raw 2D array of table data
given("user has '100' items and active is 'true'", (ctx) => {
expect(ctx.step.values).toEqual([100, true]);
expect(ctx.step.valuesRaw).toEqual(["100", "true"]);
expect(ctx.step.type).toBe("given");
});

See Data Extraction APIs for complete details on each property.


ctx.example

Example Row Data

Available in scenarioOutline() and ruleOutline() callbacks. Contains the current row from the Examples table as a key-value object.

PropertyTypeDescription
[columnName]anyValue from the current row, keyed by header name. Auto-coerced.
scenarioOutline(`Pricing
Examples:
| quantity | price | total |
| 2 | 10.00 | 20.00 |
| 5 | 7.50 | 37.50 |
`, (ctx) => {
then("the total is '<total>'", () => {
// ctx.example.quantity = 2 (number)
// ctx.example.price = 10.00 (number)
// ctx.example.total = 20.00 (number)
expect(ctx.example.quantity * ctx.example.price).toBe(ctx.example.total);
});
});

ctx.background

BackgroundContext

Available inside background() callbacks. Extends ScenarioContext.

PropertyTypeDescription
titlestringBackground title
descriptionstringDescription text
tagsstring[]Tags (if any)
background("Common setup", (ctx) => {
given("a database connection", () => {
expect(ctx.background.title).toBe("Common setup");
});
});

ctx.afterBackground()

Cleanup Registration

Available only inside background() callbacks. Registers a function that runs after each scenario completes.

function ctx.afterBackground(fn: () => void): void
ParameterTypeDescription
fn() => voidCleanup function, called once after each scenario finishes
background("Database setup", (ctx) => {
let db: Database;

given("a database connection", () => {
db = openDatabase();
});

ctx.afterBackground(() => {
db.rollback();
db.close();
});
});

See background() for complete usage examples.


ctx.specification

SpecificationContext

Available in specification(), rule(), and ruleOutline() callbacks.

PropertyTypeDescription
filenamestringFile path of the .Spec.ts file
titlestringSpecification title
descriptionstringDescription text
tagsstring[]Tags extracted from @-prefixed lines
specification(`Password Rules
@security @auth
Requirements for password complexity
`, (ctx) => {
rule("Read specification metadata", () => {
expect(ctx.specification.title).toBe("Password Rules");
expect(ctx.specification.tags).toEqual(["security", "auth"]);
});
});

ctx.rule

RuleContext

Available in rule() and ruleOutline() callbacks.

PropertyTypeDescription
titlestringRule title
descriptionstringDescription text
tagsstring[]Tags
specificationSpecificationContextReference to the parent specification
valuesany[]Type-coerced quoted values from the rule title
valuesRawstring[]Raw string values before coercion
paramsRecord<string, any>Type-coerced named parameters from <name:value>
paramsRawRecord<string, string>Raw string named parameters
specification("Calculator", () => {
rule("Adding '5' and '3' returns '8'", (ctx) => {
expect(ctx.rule.values).toEqual([5, 3, 8]);
expect(ctx.rule.valuesRaw).toEqual(["5", "3", "8"]);
expect(ctx.rule.specification.title).toBe("Calculator");
});

rule("Reversing <input:hello> gives <expected:olleh>", (ctx) => {
expect(ctx.rule.params).toEqual({ input: "hello", expected: "olleh" });
expect(ctx.rule.paramsRaw).toEqual({ input: "hello", expected: "olleh" });
});
});

How Context is Built

The ctx object uses JavaScript getters that resolve dynamically based on the current execution state:

// Simplified internal implementation
const ctx = {
get feature() { return currentFeature?.getFeatureContext(); },
get scenario() { return currentScenario?.getScenarioContext(); },
get step() { return currentStep?.getStepContext(); },
// ...
};

This means:

  • Properties reflect the current execution scope, even in async code
  • Properties not relevant to the current scope return undefined
  • The context is read-only — modifying it has no effect

See Also