Make the strip preview show the effect it claims to (#14) #134
No reviewers
Labels
No labels
area/ai
area/backend
area/frontend
area/infra
area/scheduler
area/wled
good-first-issue
priority/high
priority/low
priority/medium
type/bug
type/chore
type/ci-cd
type/docs
type/feature
type/qa
v1.0.0
v1.1.0
v1.2.0
v2.0.0
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/Iris-WLED!134
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/14-simulator"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #14.
Two of the three acceptance criteria already passed before this PR — the side panel animated a virtual strip, and it worked with no
WLED_HOSTbecause nothing in it touches the controller. What was missing was any relationship between the animation and the effect.The mapping was wrong, and unfalsifiable by looking
It keyed on effect IDs 57, 65, 66 and 9 believing them to be a comet, a wave, traffic lanes and a chase. They are Lightning, Palette, Fire 2012 and Rainbow.
Nothing caught it because the only way to check a render loop is to look at it, and looking at a shimmering strip tells you nothing about which effect it claims to be. (The same class of error in the backend is #132, fixed just before this.)
Effects are now grouped into twelve families — solid, breathe, wipe, chase, twinkle, sparkle, fire, gradient, rainbow, comet, strobe, aurora — built from the names a real 16.0.0 controller reports, and pinned by a test against the captured catalogue exactly as the backend's guard is.
It approximates; it does not emulate
WLED ships 220 effects, many 2D or audio-reactive. Reproducing them would be a second implementation of someone else's firmware, one that drifted the moment they changed anything. The goal is narrower and achievable: a reviewer approving a year of schemes can tell them apart and see roughly what each will look like.
An unrecognised ID animates as a generic shimmer — deliberately moving, because a still frame would read as "solid", which is a specific claim it cannot make.
Extracting it found two real bugs immediately
The maths moved out of the component's draw loop into a pure function, which is the only reason any of it is testable. It had no tests at all before. Within minutes of there being some:
One of my test premises was also wrong
I asserted every non-solid family renders differently at t=0 and t=1.3. Strobe is periodic and happened to be lit at both, so an honest implementation failed the test. It now samples six instants and asserts the frames aren't all identical, which is the property actually worth having.
The duplicated fixture
vitest can't read a file outside the frontend package, so the captured catalogue exists in both trees. Two copies is exactly the arrangement that rots — the backend's guard would keep passing against a stale frontend copy while the simulator's mapping quietly drifted. So a backend test asserts the two files are identical, checked from there because that run can see both trees and the frontend's cannot.
Verification
26 new vitest cases asserting what each family visibly does — solid must not animate, breathe must swing brightness without shifting hue, strobe must light the whole strip together, rainbow must sweep hue regardless of the scheme's colours, twinkle must differ per LED — because "it produced a colour" is true of every possible implementation including a broken one.
Frontend in
node:22:tsc -bclean,eslintclean, 107 vitest passing,npm run buildsucceeds. Backendruff/mypyclean, 761 tests passing.🤖 Generated with Claude Code