Skip to content

Form submission

This pattern covers any “fill the form, submit, verify” flow — contact forms, project creation, settings updates.

tests/create-project.blop.ts
import { agentTest, describe } from "blop";
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.
`);
});
  • Spell out exact values. “Name: ‘Checkout QA’” is better than “any project name”.
  • Be specific about success state. Toast text, URL pattern, heading — whichever is most reliable in your UI.
  • Use one test per failure mode. Splitting positive and negative cases keeps the goal short and the result legible.

Blop’s browser_upload_file tool accepts a path. Reference real fixture files from your repo:

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

The fixture path is relative to the working directory the CLI was launched from.