#1746·bubbletea

TestViewModel is flaky under the Taskfile's test flags

Author: xevrionCreated Jul 27, 2026Updated Aug 4, 2026

task test fails most of the time on main for me, currently fc707bb. Over 15 consecutive runs of go test -race -count 4 -cpu 1,4 ./... I get 13 failures. It's always TestViewModel, but a different subset of subtests each run, and the race detector doesn't report a data race.

Smallest reproducer I found, which fails consistently:

go test -race -cpu 1 -run TestViewModel ./...

Both flags matter. -race alone passes and -cpu 1 alone passes; it needs the two together, presumably because -race slows things down enough and GOMAXPROCS=1 removes the parallelism that was hiding the ordering.

A representative diff, from mouse_allmotion:

-\x1b[?25l\x1b[?2004h\x1b[?1003h\x1b[?1006h\x1b[>4;2m\x1b[=1;1u\r\x1b[Jsuccess...
+\x1b[?25l\x1b[?2004h\x1b[>4;2m\x1b[=1;1u\x1b[?u\r\x1b[Jsuccess\x1b[?1003h\x1b[?1006h...

As far as I can tell the renderer's flush ticker in startRenderer runs at the program's FPS, so an intermediate flush(false) can land before Quit is handled. When that happens the output picks up the \x1b[?u keyboard enhancements request, which cursed_renderer.go only writes when closing is false, and the mouse mode sequences move into a later frame. The golden files record the ordering where no intermediate flush happened.

This doesn't look like a recent regression: it reproduces the same way at c60f0c5, where the -race/-count/-cpu flags were added in #1691.

Setting WithFPS(1) in the test keeps the ticker from firing while these tests run, which fixes it for me at 15/15 with the golden files unchanged. Happy to send that as a PR if it's the direction you'd want, though you may prefer something that removes the timing dependency outright rather than widening the window.