一键导入
create-app-e2e-test
// Create app e2e tests for the Goose desktop app using the Tauri app test driver. Use when the user wants to generate, write, or verify UI tests that run against the live app.
// Create app e2e tests for the Goose desktop app using the Tauri app test driver. Use when the user wants to generate, write, or verify UI tests that run against the live app.
Analyzes branch changes to find edge cases, error states, and untested user flow paths in UI code. Use when the user says "find edge cases", "what am I missing", "edge cases", "test my flows", "what could go wrong", or wants to harden a feature before shipping.
Senior engineer code review focused on catching issues before they become PR comments. Reviews only changed lines, categorizes issues by priority, and fixes them one by one. Use when the user says "code review", "review my code", "review this branch", or wants pre-PR feedback.
Create a GitHub PR from the current branch: handle uncommitted changes, generate a summary, and submit via gh CLI. Use when the user says "create PR", "open PR", "submit PR", "push PR", or wants to create a pull request.
| name | create-app-e2e-test |
| description | Create app e2e tests for the Goose desktop app using the Tauri app test driver. Use when the user wants to generate, write, or verify UI tests that run against the live app. |
You are an AI agent that creates app e2e tests for the Goose desktop app using the Tauri app test driver.
Given a test scenario in natural language, you will:
Do NOT read source code to understand the UI. Do not read .tsx, .ts, or .css files to find elements. Use snapshot to discover what is on the page — that is your only method. The one exception: read source code only when you need to add a data-testid attribute.
The Tauri app must already be running in dev mode with the app test driver enabled.
All exploration commands use the test driver client CLI:
pnpm test-driver <action> [selector] [value]
Available commands:
| Command | Description | Example |
|---|---|---|
snapshot | Get a text DOM of visible elements | pnpm test-driver snapshot |
getText <selector> | Get inner text of an element | pnpm test-driver getText "h1" |
count <selector> | Count matching elements | pnpm test-driver count "button" |
click <selector> | Click an element | pnpm test-driver click "button" |
fill <selector> <value> | Fill an input/textarea | pnpm test-driver fill "textarea" "hello" |
keypress <selector> <key> | Dispatch a keyboard event | pnpm test-driver keypress "textarea" Enter |
waitForText <text> | Wait for text to appear in body (30s default) | pnpm test-driver waitForText "Success" |
scroll <direction> | Scroll the page (up/down/top/bottom) | pnpm test-driver scroll down |
screenshot [path] | Take a screenshot | pnpm test-driver screenshot test.png |
The snapshot command returns a simplified text DOM:
[e1] input type="text" placeholder="Ask anything..."
[t1] label "Name:"
[e2] button "Send"
[t2] span "Click me"
[t3] h1 "Good afternoon"
[eN] — interactive elements (input, button, select, textarea, a) with auto-assigned data-tid[tN] — visible text nodesdata-tid attributes (e.g., [data-tid='e3']) are assigned dynamically during each snapshot and must not be used in test files — they change between runs.
Navigate to home first, then snapshot to see the current page state.
pnpm test-driver click '[data-testid="nav-home"]'
pnpm test-driver snapshot
Tests always start from the home screen (useTestDriver() navigates home in beforeEach), so exploration should too.
For each element you need to interact with or verify:
[e3] button "Send")data-tidcount with that stable selector to verify it matches exactly one elementgetText to verify text contentclick/fill to perform actions during explorationAfter each action, run snapshot again — the DOM may have changed.
Example exploration session:
# 1. See what's on the page
pnpm test-driver snapshot
# 2. Pick a selector for the element you need, verify it matches exactly 1
pnpm test-driver count 'textarea[placeholder="Ask anything..."]'
# 3. Interact
pnpm test-driver fill 'textarea[placeholder="Ask anything..."]' "hello world"
# 4. Snapshot again to see the result
pnpm test-driver snapshot
Create a Vitest test file at tests/app-e2e/<name>.test.ts.
Use useTestDriver() from tests/app-e2e/lib/setup.ts to get a shared test driver connection with automatic teardown and screenshot-on-failure. See tests/app-e2e/chat.test.ts as a reference:
import { describe, it, expect } from "vitest";
import { useTestDriver } from "./lib/setup";
describe("<Feature>", () => {
const testDriver = useTestDriver();
it("does something", async () => {
const text = await testDriver.getText('[data-testid="greeting"]');
expect(text).toContain("Good");
});
});
Test driver API methods available in tests:
testDriver.snapshot() → text DOM stringtestDriver.getText(selector, { timeout? }) → inner text stringtestDriver.count(selector) → number of matching elementstestDriver.click(selector, { timeout? }) → clicks elementtestDriver.fill(selector, value, { timeout? }) → fills input/textareatestDriver.keypress(selector, key, { timeout? }) → dispatches keyboard eventtestDriver.waitForText(text, { selector?, timeout? }) → waits for text to appear (default: body, 30s)testDriver.scroll(direction) → scrolls page ("up", "down", "top", "bottom")testDriver.screenshot(path) → saves screenshotAll timeout options default to 5 seconds. waitForText defaults to 30 seconds.
Run the test to make sure it passes:
pnpm test:app-e2e
If it fails, use the test driver CLI to re-explore. The issue could be a wrong selector, an incorrect assertion, or a bug in the app implementation.
Always verify uniqueness with count before using any selector in a test. If count > 1, the test will be flaky.
For each element, find a stable selector using this priority:
data-testid (preferred): if the element already has a data-testid, use '[data-testid="my-element"]'.
count that it's uniqueSemantic selector: combine attributes, hierarchy, or roles to target a specific element.
'input[placeholder="Ask anything..."]' — narrow by attribute value'.sidebar [role="navigation"] a' — narrow by parent contextcount that the selector matches exactly 1 elementAdd a data-testid (last resort): if no stable selector exists, add a data-testid to the source code.
home-greeting not greeting, sidebar-new-chat-button not button)data-testid attribute — do not change any other source codeNever use data-tid attributes ([data-tid='e3']) in test files — they are assigned dynamically by snapshot and change between runs.
home.test.ts, sidebar.test.ts, settings.test.ts)count === 1 for selectors before using them in assertionssnapshot in test assertions — it's for exploration only{ timeout }) for elements to appear before click, fill, getText, and keypresswaitForText to wait for specific text content to appear (e.g., after submitting a form or waiting for an LLM response)snapshot again to see the new state before writing assertions