rule()
Docs for Vitest SDK v0.3.3
rule defines a single testable requirement inside a specification(). Unlike BDD
steps, rules contain direct assertions — no Given/When/Then ceremony. Rules also
support async callbacks, quoted value extraction, and named parameters.
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("Math Operations", () => {
rule("Adding '5' and '3' returns '8'", (ctx) => {
const [a, b, expected] = ctx.rule.values;
expect(a + b).toBe(expected);
});
});
Reference
rule(title, fn)
Registers a rule that maps to a Vitest it() call.
function rule(title: string, fn: (ctx: RuleCtx) => void | Promise<void>): void
Parameters
-
title:string— The rule description. Can contain:- Quoted values:
'value'→ extracted toctx.rule.values[] - Named parameters:
<name:value>→ extracted toctx.rule.params - Tags and descriptions (same multi-line parsing as
feature()/scenario())
- Quoted values:
-
fn:(ctx: RuleCtx) => void | Promise<void>— The rule implementation. Supportsasync.
The ctx Parameter
| Property | Type | Description |
|---|---|---|
ctx.specification | SpecificationContext | { filename, title, description, tags } |
ctx.rule | RuleContext | { title, description, tags, specification, values, valuesRaw, params, paramsRaw } |
RuleContext Properties
| Property | Type | Description |
|---|---|---|
title | string | The rule title |
description | string | Description text (from multi-line title) |
tags | string[] | Tags extracted from the title |
specification | SpecificationContext | Reference to the parent specification context |
values | any[] | Type-coerced quoted values from the title |
valuesRaw | string[] | Raw string values before coercion |
params | Record<string, any> | Type-coerced named parameters from <name:value> |
paramsRaw | Record<string, string> | Raw string named parameters |
attachments | Attachment[] | Evidence collected for this rule execution |
attach(base64, options?) | void | Add base64 data; options: mimeType, kind, title |
attachScreenshot(base64, title?) | void | Add a PNG screenshot |
attachJSON(data, title?) | void | Add UTF-8 JSON data (objects are pretty-printed) |
Returns
void — Rules are registered as Vitest it() calls.
Caveats
- Rules support
async— unlikefeature,scenario, andspecificationcallbacks. - Rules must be nested inside a
specification()call. - Use
ctx.rulefor values, parameters, and attachments;ctx.stepis only available inside BDD steps. - Do not use Given/When/Then steps inside a rule — use direct assertions.
Modifiers
rule.skip(title, fn)
Skip this rule. It appears as pending in test output.
rule.skip("Feature not yet implemented", () => {
// This test body is not executed
});
rule.only(title, fn)
Run only this rule.
rule.only("Debugging this specific rule", () => {
expect(calculate()).toBe(42);
});
Usage
Attach evidence to a rule
Attach evidence during the rule callback, not in the surrounding specification() declaration.
Evidence is included in the rule's execution.attachments in exported TestRunV1
JSON and server payloads, including when the rule throws after attaching it.
rule("The response contains an order number", async (ctx) => {
const response = await getOrder();
ctx.rule.attachJSON(response, "Order response");
expect(response.orderNumber).toBeTruthy();
});
rule("The receipt image is generated", async (ctx) => {
const pngBase64 = await generateReceipt();
ctx.rule.attachScreenshot(pngBase64, "Receipt");
ctx.rule.attach(pngBase64, {
mimeType: "image/png",
kind: "image",
title: "Receipt image",
});
});
Basic: Direct assertion
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("Email Validation", () => {
rule("Email addresses must contain @", () => {
expect(validateEmail("invalid")).toBe(false);
expect(validateEmail("user@example.com")).toBe(true);
});
rule("Empty strings are rejected", () => {
expect(validateEmail("")).toBe(false);
});
});
Quoted values with ctx.rule.values
Values in single quotes are auto-extracted and type-coerced.
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("Calculator", () => {
rule("Adding '5' and '3' returns '8'", (ctx) => {
const [a, b, expected] = ctx.rule.values;
// a = 5 (number), b = 3 (number), expected = 8 (number)
expect(a + b).toBe(expected);
});
rule("Concatenating 'hello' and 'world' returns 'helloworld'", (ctx) => {
const [a, b, expected] = ctx.rule.values;
// a = "hello" (string), b = "world" (string)
expect(a + b).toBe(expected);
});
rule("Boolean 'true' is truthy", (ctx) => {
const [value] = ctx.rule.values;
// value = true (boolean)
expect(value).toBe(true);
});
});
Named parameters with ctx.rule.params
Named parameters use <name:value> syntax for self-documenting rule titles.
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("String Operations", () => {
rule("Reversing <input:hello> returns <expected:olleh>", (ctx) => {
const { input, expected } = ctx.rule.params;
expect(reverse(input)).toBe(expected);
});
rule("Uppercasing <input:hello> returns <expected:HELLO>", (ctx) => {
expect(ctx.rule.params.input.toUpperCase()).toBe(ctx.rule.params.expected);
});
});
Async rules
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("API Endpoints", () => {
rule("GET /api/users returns a list of users", async () => {
const response = await fetch("/api/users");
const data = await response.json();
expect(Array.isArray(data)).toBe(true);
expect(data.length).toBeGreaterThan(0);
});
rule("POST /api/users creates a new user", async () => {
const response = await fetch("/api/users", {
method: "POST",
body: JSON.stringify({ name: "Alice", email: "alice@example.com" }),
});
expect(response.status).toBe(201);
});
});
Combining values and params
import { specification, rule } from "@swedevtools/livedoc-vitest";
specification("Price Calculation", () => {
rule("Item priced at '$100' with <tax:10>% tax costs '$110'", (ctx) => {
const [price, , total] = ctx.rule.values; // 100, 110
const taxRate = ctx.rule.params.tax; // 10
expect(price + (price * taxRate / 100)).toBe(total);
});
});
See Also
specification()— parent container for rulesruleOutline()— data-driven variant with Examples table- Data Extraction APIs — full reference for value extraction and type coercion
- Context Object — full reference for
ctx.ruleandctx.specification - Steps:
given/when/then— BDD alternative for structured step sequences