3.8 KiB
3.8 KiB
name, description
| name | description |
|---|---|
| dankvoice-bundle-swap-red-proof | Prove a dankvoice behavior test is red-before/green-after by pointing DV_EXT at the previously committed dist bundle, with a pinned scratch fixture dir. |
Use when a new black-box tests/behavior.bats assertion in dankvoice must be shown to be red-capable (fails on the pre-change code) without git stash/worktree juggling, or when the old bundle must be compared to the new one.
Why
The bats suite drives dist/index.js only (nothing imports src/), and the bundle is self-contained. So the previous commit's behavior is one git show away: write it to a file, point DV_EXT at it, run the same driver, and read the same PLAYS n / CALL / NOTIFY lines the test asserts.
Procedure
- Build the new bundle and export the old one:
cd ~/Projects/<dankvoice-checkout> bun run build >/dev/null 2>&1 git show HEAD:dist/index.js > /tmp/old-dist.js - Stand up the fixtures in a pinned scratch dir — never
$(ls -dt /tmp/tmp.* | head -1): other live sessions on the box createtmp.*dirs continuously, and a glob picks theirs, which is how a red-proof silently becomes "Module not found" and then a falsePLAYS 0.W=/tmp/dv-redproof; rm -rf "$W"; mkdir -p "$W/bin" - Copy the real player stub, not a simplification. The driver counts plays from the stub log; a stub that only
sleeps records nothing and reportsPLAYS 0for every build, red and green alike. Mirrorsetup()intests/behavior.bats:(Re-check those line bounds against the current file; the driver lives insidecat > "$W/player.sh" <<'SH' #!/usr/bin/env bash printf '%s\n' "$*" >> "$DV_STUB_LOG" for arg in "$@"; do case "$arg" in *.wav) cp "$arg" "$DV_COPY" ;; esac; done sleep "${DV_HOLD:-0.1}" SH chmod +x "$W/player.sh" ln -s "$W/player.sh" "$W/bin/pw-play" # PATH fallback player printf '#!/usr/bin/env bash\nprintf "116\\talsa_output.usb-KT.0\\taudio/sink\\t*\\n"\n' > "$W/bin/wpctl" chmod +x "$W/bin/wpctl" sed -n '86,408p' tests/behavior.bats > "$W/driver.ts" # the inline heredoc driversetup().) - Export the env the driver expects and run old vs new against the SAME scenario:
The driver sets its own fixture server URL and prepends
export DV_STUB="$W/player.sh" DV_STUB_LOG="$W/player.log" DV_COPY="$W/played.wav" \ DV_OMPCONFIG=/dev/null DANKVOICE_CONFIG="$W/settings.json" DV_MODELS="$W/models.yml" DV_WPCTL=x for ext in /tmp/old-dist.js "$PWD/dist/index.js"; do rm -f "$W/player.log" DV_EXT="$ext" DV_PLAYER_BIN="$W/no-such-player" bun "$W/driver.ts" speak | grep -E '^PLAYS|^NOTIFY' donedirname "$DV_STUB")/bintoPATH(see itsDANKVOICE_*block), so the discovered-player fallback has somewhere real to land. - Add a control: same scenario with a valid player path. Old-vs-new differences that the control also shows are harness bugs, not behavior changes.
Reading the result
- old
PLAYS 0+ newPLAYS 1+ controlPLAYS 1→ the assertion is red-capable and the fix is real. - identical results old vs new → the harness is lying (stub too thin, wrong scratch dir, or the scenario never reaches the changed path). Fix the harness before believing any green.
- File-mode assertions: pre-seed the file with the old mode (
printf … > file; chmod 644 file) — a fresh write withmode:inwriteFileSynconly applies at creation, so a fresh file can look green while the old code is equally green.
Gotchas
- Never poll the bats suite while doing this;
setup()runsbun run build, so a concurrentsrc/edit gets compiled into someone else's run (seedankvoice-bats-serialization). bun run builddoes not typecheck; a stale identifier reference survives bundling and only fails at runtime — the suite, not the build, is the gate.