e2e-testing
E2E test conventions — semantic selectors, arrange-steps that prove the process started, runtime markers that cannot match the shell echo, and absolute-path tool invocations. Use when writing or chang
SKILL.mddev/skills/e2e-testing/SKILL.md
GitHubE2E Tests
Use semantic selectors: Never match on CSS classes (
class*="bg-...") in test selectors — classes are styling concerns and break when visual design changes. Usedata-testid,data-active, or other semanticdata-*attributes instead.A step that starts a process must prove the process started. Typing a command into a PTY and waiting a frame is not an arrangement — it is an unconditional pass. Wait for a marker the process itself prints once it is up (e.g. from a
listencallback), and on timeout quote the terminal's own last lines. Otherwise every environmental way the start can fail —EADDRINUSEfrom a leftover process, a missing tool, a shell still initializing — surfaces much later as a missing UI value and reads as a broken product. In #1982 that cost a CI cycle: the listener never started and the failure said "the Ports section showed[]", pointing at the port sensor.A marker you wait for must not appear literally in the command you type. The shell echoes the command line, so a
waitForBufferContains("kolu-e2e-listening")matches the echo before the process runs — the same #1982 guard passed against/nonexistent/node. Build the marker at runtime ("kolu-e2e" + "-listening") so only the process's own output can satisfy it, and prove it: point the step at a broken binary and confirm it now fails at the start step, quoting the shell's own error. Any new wait/guard gets that negative test before you trust it.Never depend on a tool being on the PTY's PATH. Run it by absolute path —
process.execPathfor node. A barenoderesolves on every dev box and can fail only on a host where node lives solely in the dev shell, so the difference presents as a phantom product bug on one machine. Whether the shell resolvesnodeis a different question from the one the scenario is asking.