Troubleshooting and Best Practices
Start with the semantic failure and generated diagnostics. Most flaky application tests come from an unobserved transition, shared state, changing content, or a target assumption—not from a Vitest assertion.
Flaky waits and timing
Symptom: a focus, screen, or control wait fails intermittently.
- Assert the result of the previous action before issuing the next action.
- Wait on
hs.wait.forScreen,forFocus,forControl,forProperty,forData,forImage, orforIdle. - Add
stableMswhen state may briefly pass through the expected value. - Give every complex wait a description; it appears in timeout diagnostics.
- Use
hs.pause(ms, reason)only for an external system with no observable state. - Do not increase the entire suite timeout to hide one missing readiness condition.
Unstable or ambiguous selectors
Symptom: no control matches, or multiple controls match the same ID.
- Add a stable application
idor explicittestIdat the relevant control boundary. - Do not select by label text that changes with localization/editorial content.
- Do not select a serialized child index or browser DOM path.
- For collection content, use semantic row metadata and content IDs, then assert minimum counts rather than mutable order.
- Treat an ambiguity error as an application test-contract issue; do not silently take the first result.
Animation and screenshot differences
Symptom: state assertions pass but PNG comparison changes.
- Wait for application hierarchy/focus stability and image readiness before capture.
- Disable or complete animation through an application-supported state.
- Keep fonts, Chromium revision, operating system, dimensions, and assets consistent.
- Use target-specific baselines.
- Mask only an explicitly dynamic bounded control.
- Prefer a report proof over pixel comparison for live editorial, clock, random, or network-driven content.
- Inspect baseline, actual, and
.diff.pngbefore updating.
Port conflicts and stale processes
Symptom: the launcher reports occupied ports or an existing runtime lock.
- Stop the other test or Hosanna dev run using that port set.
- Check for a still-running Vitest/hst process after an interrupted debug session.
- Configure a complete unique port set for concurrent suites or shards.
- Do not delete a live lock to force two runs onto the same debugger port.
The launcher waits for actual Vite and application readiness; a long startup sleep will not fix a port collision or mismatched test-run handshake.
Missing browser or system libraries
Symptom: Chromium cannot launch.
npx playwright install chromium
On supported Linux workers:
npx playwright install --with-deps chromium
Use the Playwright version in the lockfile. Reinstalling a different global browser version can create rendering and baseline differences.
Wrong application or startup timeout
Symptom: startup waits for the expected app/test-run ID and times out.
- Run the normal
hst runcommand to verify the application builds. - Restore required ignored build-config secret overlays.
- Verify
appNameand generated application ID. - Turn on
HOSANNA_TEST_VERBOSE=1and inspect the buffered launch/browser output. - Confirm the remote-debug and MCP test overlay is enabled for a non-production environment.
- On physical Roku, verify LAN reachability, device IP, developer password, ECP, debug-log port, and
HS_TEST_DEBUG_HOSTif automatic host selection is wrong.
Capability mismatch
Symptom: the client says a target does not support touch, text, deep links, or screenshots.
Use createHosannaTestTarget and test.runIf(...) for a truly target-specific scenario. Do not catch and ignore capability errors. See the current matrix in Devices, Browsers, and Input Methods.
Test independence
- Apply a default named precondition before every test.
- Clear or seed only application-owned test state, then relaunch and wait.
- Keep one worker/file sequence per owned runtime.
- Do not rely on another test to create a selected item or navigation history.
- Keep credentials and mutable remote accounts out of the default suite.
- Clean host-side data in precondition/teardown helpers if the scenario creates it.
- Verify that a single file and a single
-tfiltered test both pass alone.
Decide what to cover
Good default-suite candidates are startup, primary navigation, focus restoration, back/history, one remote path, one supported touch path, key rendering/focus states, and a few valuable failure/edge states.
Keep these elsewhere:
- exhaustive function/data branches: unit tests;
- all service response permutations: service/contract tests;
- rapidly changing editorial copy/order: structural minimum/readiness assertions;
- native rendering or hardware input claims: physical-device validation;
- low-value screenshots of every screen: omit them.
Keep the default suite fast
- Launch the app once per Vitest run.
- Reset through lightweight named preconditions.
- Capture proofs only at decision points.
- Keep visual assertions opt-in or limited to high-value stable states.
- Disable video during rapid local authoring when the project supports it.
- Run a small browser suite on pull requests and broader/device matrices on schedule.
- Remove redundant UI cases already protected by lower-level tests.
Return to Regression Testing Overview or review Writing and Running Tests.