Skip to content

Auth flow

A common smoke test: confirm a known user can sign in and land in the authenticated dashboard. The agent handles the form fields itself — your job is to spell out the verification.

tests/auth.blop.ts
import { agentTest, describe } from "blop";
describe("auth", () => {
agentTest("seeded user can sign in", async ({ agent }) => {
await agent.goto("/sign-in");
await agent.goal(`
Sign in as test@test.com with password admin123.
After submitting:
- Verify the URL becomes /dashboard.
- Verify the heading "My projects" is visible.
- Verify the user's email "test@test.com" appears in the top nav.
Finish the test as passed only if all three checks succeed.
Otherwise finish as failed and explain which check failed.
`);
});
});
  • Concrete credentials. The agent doesn’t have to guess.
  • Explicit verifications. Three named checks, each addressable by a browser-tool call.
  • Strict pass condition. “Only if all three” stops the agent from optimistically passing on partial state.
Terminal window
bunx blop test tests/auth.blop.ts --base-url http://localhost:3000

If most of your tests start signed in, run the sign-in flow once and reuse its storageState. With Playwright, write the state in a setup script and load it via browserContext:

blop.config.ts
import type { BlopConfig } from "blop";
export default {
baseUrl: "http://localhost:3000",
browserContext: {
storageState: "tests/.auth/state.json",
},
} satisfies BlopConfig;

Each test now opens a session that already has the cookie set. Tests can skip the sign-in step and start directly at /dashboard.

agentTest("invalid password is rejected", async ({ agent }) => {
await agent.goto("/sign-in");
await agent.goal(`
Try to sign in as test@test.com with password "wrong".
Verify:
- The URL does NOT change to /dashboard.
- An error message containing "incorrect" or "invalid" is visible.
Finish as passed only if both are true.
`);
});