Form submission
This pattern covers any “fill the form, submit, verify” flow — contact forms, project creation, settings updates.
The spec
Section titled “The spec”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. `); });});Validating client-side errors
Section titled “Validating client-side errors”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.
File uploads
Section titled “File uploads”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.