# Test DSL

> Look up agentTest, describe and defineAgentTest and the types a browser check spec file uses.

The functions and types a [browser check](/reference/glossary/#browser-check) spec file uses, imported from `@blopai/test`.

```ts
import { agentTest, describe } from "@blopai/test";

describe("auth", () => {
  agentTest("login with valid credentials", async ({ agent }) => {
    await agent.goto("/login");
    await agent.goal("Sign in as qa@example.com and verify the dashboard heading appears.");
  });
});
```

## DSL functions

| Function | Purpose |
|---|---|
| `describe(name, fn)` | Named scope; nested names join with ` > `, as in `auth > login with valid credentials` |
| `agentTest(name, handler)` | Register a check; the handler receives a `BlopAgentTestContext` |
| `defineAgentTest(test)` | Validate and return a `BlopAgentTest` object |

`agent.goto()` and `agent.goal()` do not act when called: they queue steps the agent works through when the check runs. A spec can combine registered `agentTest` checks with exported objects: `default` (one check or an array), `tests`, or any other exported array of `BlopAgentTest`. Registered checks come first, and an object exported twice runs once.

## DSL types

| Type | Shape |
|---|---|
| `BlopAgent` | `goto(url)`: queue a navigation, relative to `baseUrl`; `goal(text)`: queue a natural-language goal |
| `BlopAgentTestContext` | `{ agent: BlopAgent; baseUrl?: string }` |
| `BlopAgentTestHandler` | `(context) => void \| Promise<void>` |
| `BlopAgentTest` | `{ name: string; goal: string; baseUrl?: string; timeoutMs?: number }`; `name` and `goal` must be non-empty, `timeoutMs` a positive integer |
| `BlopAgentStep` | `{ type: "goto"; url }` or `{ type: "goal"; goal }`, one queued step |
