.agents/skills/wox-generate-smoke-test-case/SKILL.md
Understand the feature before choosing coverage. Recommend the smallest high-value real-process smoke flow, then reuse the current smoke harness and product automation surface instead of building test-only paths.
AGENTS.md and relevant README.md files. Inspect git status, unstaged changes, staged changes, and relevant untracked files without modifying unrelated work.wox.core/test/smoke/harness.gowox.core/test/automationdriver/client.gowox.core/test/smoke/For every settings smoke case, determine why the setting exists and trace the runtime path that consumes it before writing the test.
When the target is a plugin:
SettingDefinitions, dynamic setting callbacks, and query/action forms. Record its key, type, default, validators, options, and visibility conditions.GetSetting calls, initialization, reload callbacks, and persistence code. Map the setting to the behavior it actually changes.When the user asks for coverage design, present:
When the user already specified the exact flow, keep the pre-edit design brief: present only the code map, one observable behavior contract, and any automation gap. Do not expand an approved flow into an unnecessary candidate list or full setting matrix.
Recommend smoke coverage only for real-process native UI, lifecycle, persistence, plugin integration, platform, accessibility, or rendering boundaries. Prefer unit tests for local pure logic and skip behavior already covered at the same boundary.
If the user asked only for design, stop after the recommendation. If the user already named or approved an exact flow, continue. Otherwise ask which recommended case to generate before editing product or test code.
State one observable behavior contract for the selected flow.
Search all smoke packages for an existing helper before adding a local one. Promote a helper to automationdriver or smoke when a second consumer uses the same interaction contract; keep plugin-specific behavior in the leaf package. Avoid page-object layers or table-editor DSLs until repeated cases justify them.
Reuse existing automation IDs, actions, smoke.Case, and helpers. Before driving a control, confirm its semantics expose a stable ID, role, label, current value or checked state, selected state when relevant, and the correct action. If that contract is missing, modify the smallest shared owning UI component to add a stable automation ID or semantic action, then add a focused component test for that contract. The semantic action must follow the real user interaction path; do not add a test-only bypass around product behavior.
Add the case under the owning functional path. Reserve wox.core/test/smoke/setting/ for Wox's own settings sections, such as setting/ui/. Every plugin-owned case must live under wox.core/test/smoke/launcher/plugin/<plugin>/, including flows that configure the plugin through its Settings page before exercising Launcher behavior. Classify by product owner rather than the UI route used during the flow; for example, place Calculator coverage under launcher/plugin/calculator/. Use the next unused three-digit number without renumbering existing cases:
NNN_descriptive_name_test.goTestNNNDescriptiveName//go:build wox_ui_smokeImmediately above every generated TestNNN... function, add a concise English doc comment that states the user-visible intent, the ordered UI flow, and the final evidence that proves the behavior. Mention prerequisites or cleanup only when they are part of the contract. Describe product behavior rather than automation implementation details. Use this shape:
// TestNNNDescriptiveName verifies <user-visible behavior and boundary>.
// Flow: <entry> -> -> <observable result>.
// Evidence: <real UI, runtime, persisted artifact, or log assertion that proves success>.
func TestNNNDescriptiveName(t *testing.T) {
Drive the UI through automationdriver.Client. Wait for stable semantic state with client.WaitFor; never use fixed sleeps to guess readiness. Use explicit semantic actions and postconditions such as Selected, Checked, Value, status, or disappearance. Do not use node bounds, pointer coordinates, or screenshot pixels when the owning UI can expose a semantic route. Coordinate interaction is allowed only for an unavoidable native or platform surface that cannot expose semantics; document why, resolve coordinates from a current semantic node instead of hard-coding them, and assert the resulting functional state rather than geometry.
Treat query and result state as generation-bound. Setting the same query value may be a no-op, and refreshes may replace dynamic result IDs. Force a real query transition when freshness matters, wait for both the input value and launcher.results=complete, and resolve dynamic IDs again after refresh instead of retaining them across generations.
Treat every command executed by a smoke case as interpreter- and platform-dependent input. Confirm the interpreter the case actually selects or inherits on Windows, macOS, and Linux. Prefer the simplest syntax shared by all targeted interpreters; do not assume Bash operators such as &&, export, Unix paths, or Unix-only tools work in Windows PowerShell. When no shared command exists, select the command with runtime.GOOS and, when configurable, the chosen interpreter, while keeping output and side effects equivalent. Normalize path separators and line endings in assertions. If the behavior is intentionally platform-specific, skip it explicitly with the reason instead of waiting for an impossible state.
Let smoke.Case own before/after reset and the shared client, but do not assume reset restores plugin settings or desktop side effects. Explicitly restore changed settings and clean external state. Reopen settings or inspect persisted data before exercising runtime behavior; a locally updated control does not prove an asynchronous save completed.
Keep assertions user-visible and deterministic. Prefer evidence in this order: real runtime artifact or fresh log slice, reloaded persisted value, then live semantic state. Treat relevant snapshot diagnostics as failures. Do not weaken assertions or add retries merely to hide a race.
Do not launch another Wox process or create a second data directory inside a case. Use automationdriver.SharedDataDirectoryEnvironment only when the behavior must inspect real persisted output, and poll artifacts independently of UI generation changes.
Format every touched Go file with the repository formatter. Run the new case from the repository root:
make smoke <functional/path/NNN>
make smoke to catch leaked state and shared-process cleanup failures. If the full suite fails in an existing case, distinguish that baseline failure from the new selector instead of attributing it to the new coverage. If execution is blocked by the environment, report the exact blocker and do not claim runtime coverage.Report the behavior covered, the created case selector, every production or automation file changed to support it, and the exact verification commands with pass or failure status.