--- name: bats-output-glob-red-proof-traps description: "Write red bats tests over command output: [[ ]] glob adjacency (quoted * is literal), run-capture vs test stdout in failure dumps, and proving red against pre-fix code before trusting green." --- Three traps hit while writing red-then-green bats tests for `remote-job.sh` (Refs #60, `dank/command-center` PR #61). Each one cost a detour because it makes a test look like a bug report when it is an assertion bug. ## 1. In `[[ $s == pat ]]` a quoted `*` is LITERAL — and it eats the wildcard beside it ```bash s=' x* DONE rc=0 1 lines' [[ "$s" == *"x*"DONE*"rc=0"* ]] # NOMATCH — and it looks like the tool under test broke [[ "$s" == " x*"*"DONE rc=0"* ]] # MATCH — quoted literals, UNQUOTED separators ``` `*"x*"DONE*` means: anything, then the literal substring `x*DONE`, then anything. Quoting only makes the `*` inside the quotes literal; it does **not** keep the next unquoted token from butting up against it. When the subject has whitespace between the two facts, the pattern must carry an **unquoted** `*` between the quoted literals: ``` "literal-a"*"literal-b" # a, then anything, then b ``` Existing suites in the repo write `*"a"*DONE*rc=0*` — unquoted separators throughout — precisely for this reason. Copy that shape; do not quote for "clarity". Discriminate before believing the test: run the pattern against BOTH the expected line and the line the buggy code produced (`correct-red` / `NOMATCH` on the second is the pass condition). A pattern that matches the old output was never a regression test. ## 2. A bats failure dump prints the TEST's stdout, not `$output` ``` not ok 1 status treats a job name as a name, not a pattern # `[[ "$output" == *"x*"DONE* ]]` failed # started x* ``` `started x*` is the stdout the test body itself printed (from a `start` call several lines earlier), **not** what `run` captured. Reading it as the captured value sends you to debug the tool. To see the real capture, echo it: ```bash run some-command echo "CAP:[${output}]" ``` in a scratch copy of the test (`/tmp/dbg.bats`, same `setup`/harness) rather than adding diagnostics to the committed test. ## 3. Reproduce outside bats when green refuses to arrive When a test fails but the same command works by hand, replicate the *exact* bats call shape in `/tmp` with the same env exports (`REMOTE_JOBS_DIR` etc.) and the same `run bash -c '…' _ "$A" "$B" "$C"` argument mapping. If the scratch copy passes and the committed one fails, the difference is the assertion, not the system — go back to trap 1. ## Red-proof rule Run the new test against the pre-fix code and read *why* it failed. Both traps above produced a failure that looked meaningful while proving nothing (one matched the buggy output; one printed the wrong stream). Keep the test only when the failure reason is the defect you set out to pin. Related: `bats-assertion-trust` (vacuous assertions), `red-verify-without-stash` (proving red in a shared worktree).