Public: anyone can read this; the crew can change it.

forked from trevato/cs

One AudioContext fake, behind the door: the sound device's test double stops being written three times #369

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

There were three copies of the fake `AudioContext`, and now there is one: `fakeAudioContext` in the new `src/engine/context.ts`, exported from `src/engine/index.ts` and listed in `surface.json` (which moves to 0.10.0). The engine's sound tests, the range's audio tests and the range's stage helper all use it now, and all three moved in one commit. No `expect` line changed in `sound.test.ts`, `src/r…

shipped production is serving it deploy ae07c2d

opened this

There were three copies of the fake AudioContext, and now there is one: fakeAudioContext in the new src/engine/context.ts, exported from src/engine/index.ts and listed in surface.json (which moves to 0.10.0). The engine's sound tests, the range's audio tests and the range's stage helper all use it now, and all three moved in one commit. No expect line changed in sound.test.ts, src/range/audio.test.ts or boot.test.ts, and bun run test (typecheck plus 1490 tests) passes.

How it records. Everything goes into one list, log, in order: a param assigned (panner.pan.value), set or ramped at a time, a connect with the node it reached, and a start or stop with its scheduled time. Each entry names its node, and nodes are numbered in the order they were made (gain1, limiter2, …). The fake also keeps the nodes it handed out, the buffers it created, and counts of contexts opened and resume() calls. The two other views, edges (the graph) and scheduled (sets, ramps, starts and stops), are read straight off log. Each node still connects to exactly one thing, so sound.test.ts can still walk a sound's route as a straight path.

Options.

  • panner and compressor both default to true. False removes the method from the context entirely, which is how sound.ts checks for a browser that lacks it.
  • The clock starts at currentTime: 2 by default, so a sound scheduled at 0 instead of "now" shows up in the times.
  • The state defaults to "suspended", which is what makes the device call resume().

These defaults are what sound.test.ts was already tested against. The range passes currentTime: 0 and state: "running".

The range's voices. This is now a fold over the log (voicesOf in src/range/stage.test-helper.ts) rather than a second fake. The panner trick still works: the device assigns pan.value directly, so the fake writes that down as a panner.pan.value event, and the fold gives the side to the next sound started. The boot tests that check left and right pass unchanged.

What changed in the callers, none of it an assertion:

  • sound.test.ts keeps its fakeContext name as a thin wrapper that adds panners, read off the nodes.
  • src/range/audio.test.ts's log is now the recorder's scheduled view. Its full log would include the setup the device does when the context opens, and expect(a.log).toEqual([]) means "no sound was scheduled", which is what that view says.

New test file. src/engine/context.test.ts checks that:

  • the fake answers every context member sound.ts reads, found by reading its source;
  • the defaults are as stated, and a missing panner or compressor means the method is absent rather than one that answers null;
  • one noise burst's complete log matches a hand trace of sound.ts;
  • no built bundle contains the fake, and only tests and index.ts import it;
  • nothing outside the engine defines its own createBufferSource fake.

Guide. GUIDE.md has a new ### context section with its measured weight (1.7 kB raw, 0.9 kB gzipped). The whole-engine weight line is now 47.4 kB raw, 18.9 kB gzipped. The sound section names the fake as something a game gets for its tests, and the page section and the seam table no longer say a game brings its own AudioContext. The bundle-size ceiling tests pass.

Not done: the fake does not pretend to play sound. A param's value is only what was last assigned to it, and scheduling a change is written down but moves nothing.

🤖 Generated with Claude Code

Closes #332

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs