Skip to content

Test DSL

Three exports cover every spec file. Imported from "blop".

function describe(name: string, fn: () => void): void

Creates a named test scope. Nested describe blocks stack their names with >.

describe("auth", () => {
describe("login", () => {
agentTest("with valid credentials", async ({ agent }) => {
// Full test name: "auth > login > with valid credentials"
});
});
});
function agentTest(
name: string,
handler: BlopAgentTestHandler,
): void

Registers a test inside a describe block. The handler receives a BlopAgentTestContext and builds a goal string from agent.goto() and agent.goal() calls.

agentTest("homepage loads", async ({ agent }) => {
await agent.goto("/");
await agent.goal("Verify the heading and CTA are visible.");
});

agent.goto() and agent.goal() don’t execute immediately — they queue steps on a goal list that the agent receives once the runner reaches this test.

function defineAgentTest(test: BlopAgentTest): BlopAgentTest

Validates and returns a BlopAgentTest object. Use for generated tests or array exports.

import { defineAgentTest } from "blop";
export default defineAgentTest({
name: "smoke test",
goal: "Open the app and verify the homepage is usable.",
});

Each spec file may export default (single test) and/or tests (array of BlopAgentTest).

The agent object passed to agentTest handlers.

type BlopAgent = {
goto: (url: string) => Promise<void>;
goal: (goal: string) => Promise<void>;
};
Method Purpose
agent.goto(url) Queue a page navigation. Resolves relative to baseUrl if provided.
agent.goal(goal) Describe a verification step in natural language.
type BlopAgentTestContext = {
agent: BlopAgent;
baseUrl?: string;
};
type BlopAgentTestHandler = (
context: BlopAgentTestContext,
) => void | Promise<void>;
type BlopAgentTest = {
name: string; // Test name (non-empty)
goal: string; // Natural-language goal (non-empty)
baseUrl?: string; // Per-test base URL override
timeoutMs?: number; // Per-test timeout override (positive integer)
};

Validated by Zod at runtime. Both name and goal must be non-empty strings.

Internal representation of a test step after materialization.

type BlopAgentStep =
| { type: "goto"; url: string }
| { type: "goal"; goal: string };