Models the real controller's stopped-loop semantics: the rAF loop
starts STOPPED (the viewer idle-stops after ~2s of no interaction,
which is the normal state by the time a user has read the Recording
panel and confirmed a dialog), only startAnimation() flips it to
running, and per-frame callbacks fire only while it runs. Registering
a continuous callback KEEPS a running loop alive but never restarts
a stopped one — so a double that fires callbacks unconditionally is
structurally blind to the whole "capture emits N identical frames"
class of bug (a deleted startAnimation() would fail nothing).
The options argument of each registration is recorded by vi.fn()
itself, so { continuous: true } is assertable with
toHaveBeenCalledWith.
Note the fidelity limit: this double runs a callback at REGISTRATION
time (once, if the loop is running), not on a simulated frame — its
consumers have no frame pump. offline-capture-strategy.test.ts has a
local double that instead QUEUES callbacks and runs them from a
__tick() driven by its requestAnimationFrame spy, which is what
catches "registered and removed with no tick in between". A consumer
that needs frame-tick fidelity should adopt that shape.
Build the test double for AnimationController.
Models the real controller's stopped-loop semantics: the rAF loop starts STOPPED (the viewer idle-stops after ~2s of no interaction, which is the normal state by the time a user has read the Recording panel and confirmed a dialog), only
startAnimation()flips it to running, and per-frame callbacks fire only while it runs. Registering acontinuouscallback KEEPS a running loop alive but never restarts a stopped one — so a double that fires callbacks unconditionally is structurally blind to the whole "capture emits N identical frames" class of bug (a deletedstartAnimation()would fail nothing).The options argument of each registration is recorded by
vi.fn()itself, so{ continuous: true }is assertable withtoHaveBeenCalledWith.Note the fidelity limit: this double runs a callback at REGISTRATION time (once, if the loop is running), not on a simulated frame — its consumers have no frame pump.
offline-capture-strategy.test.tshas a local double that instead QUEUES callbacks and runs them from a__tick()driven by itsrequestAnimationFramespy, which is what catches "registered and removed with no tick in between". A consumer that needs frame-tick fidelity should adopt that shape.