# Browser check examples

> Copy complete browser checks for a sign-in flow, a form submission and a multi-page checkout.

Copy a complete browser check and adapt its paths, text and values to your app. Set up `@blopai/test` first with [Browser checks](/checks/).

## Sign-in flow example

```ts
// tests/auth.blop.ts
import { agentTest, describe } from "@blopai/test";

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.
    `);
  });

  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.
    `);
  });
});
```

The credentials belong to a seeded local user. Never put production credentials in a goal; production needs a secret-backed sign-in and a synthetic identity ([Production checks](/checks/production/)). Three named verifications and a strict pass condition stop the agent passing on partial state.

## Form submission example

```ts
// tests/create-project.blop.ts
import { agentTest, describe } from "@blopai/test";

describe("projects", () => {
  agentTest("can create a project", async ({ agent }) => {
    await agent.goto("/dashboard/projects/new");
    await agent.goal(`
      Fill out the new-project form:
      - Name: "Checkout QA"
      - Repository URL: "https://github.com/example/shop"
      - Default branch: "main"

      Submit the form.

      Verify:
      - The URL changes to /dashboard/projects/<some-id>.
      - The page heading reads "Checkout QA".
      - A toast or banner with "Project created" appears.

      Finish as passed only if all three checks succeed.
    `);
  });

  agentTest("missing name is rejected", async ({ agent }) => {
    await agent.goto("/dashboard/projects/new");
    await agent.goal(`
      Submit the form WITHOUT filling in any fields.

      Verify:
      - The URL still ends in /projects/new.
      - An error message near the "Name" field reads "Required" or similar.

      Finish as passed only if both are true.
    `);
  });

  agentTest("can upload an avatar", async ({ agent }) => {
    await agent.goto("/dashboard/general");
    await agent.goal(`
      Upload the file at "tests/fixtures/avatar.png" via the avatar input.
      Verify the avatar preview updates and a "Saved" toast appears.
      Finish as passed only if both are true.
    `);
  });
});
```

Give exact values and one check per failure mode. The agent uploads files with `browser_upload_file`; the fixture path is relative to the directory you run `blop test` from.

## Multi-page checkout example

```ts
// tests/checkout.blop.ts
import { agentTest, describe } from "@blopai/test";

describe("checkout", () => {
  agentTest("guest can complete a purchase", async ({ agent }) => {
    await agent.goto("/products/widget");
    await agent.goal(`
      Step 1 — Add to cart:
      - Click the "Add to cart" button.
      - Verify the cart counter reads "1".

      Step 2 — Open the cart:
      - Click the cart icon.
      - Verify the URL becomes /cart.
      - Verify "Widget" appears in the line items.

      Step 3 — Begin checkout:
      - Click "Checkout".
      - Verify the URL becomes /checkout.

      Step 4 — Fill shipping:
      - Email: "test@example.com"
      - Name: "Test User"
      - Address: "1 Main St"
      - City: "Austin"
      - Zip: "78701"
      - Click "Continue to payment".

      Step 5 — Pay with the test card 4242 4242 4242 4242,
      any future expiry, CVC 123. Submit.

      Step 6 — Verify success:
      - URL becomes /checkout/thanks.
      - Heading reads "Order confirmed".

      Finish as passed only if every step's verification succeeds.
      If any step fails, stop and finish as failed with a reason.
    `);
  });
});
```

Numbered steps give the agent checkpoints and make the result's `reason` easy to read. Model different starting states, such as guest and signed-in, as separate checks in the same `describe`. Set an explicit `--max-steps` for long flows; there is no default cap.
