test(core): cover the group-bus routing, and clear the last five oversized files

Two loose ends from the rebase.

**The routing had no test.** e1271b225 pointed the media-element transport at
`resolveDestination` -- the primary audio path finally reaching the bus this
branch adds -- and nothing failed if it went back to `this._masterGain`. Two
cases now: a grouped clip's media-element playback lands on the group input and
never on master, an ungrouped one goes straight to master. Verified they FAIL on
a revert of that one line. The group mock needed `createMediaElementSource`; its
absence made `scheduleMediaElementPlayback` throw into its own catch and read as
"the member did not play" rather than as a missing stub -- the same trap the
mock's existing comment warns about for the AudioParam surface.

**Five studio files were over the 600-line cap.** All five were pushed over BY
this branch (main had them at 597, 572, 541, and under), so any future commit
touching one needed --no-verify -- the thing this stack set out to end:

- TimelineLanes.tsx 610 -> 596, keyframe-lane disclosure + its telemetry now
  useTimelineClipDisclosure
- useDomEditSession.ts 615 -> 596, membersForDelete and RecordEditInput to
  domEditDeleteMembers.ts (re-exported, its test imports from the old home)
- useTimelineEditing.ts 614 -> 600, the rate-limited blocked-edit toast to its
  own hook, TimelineMoveUpdates to the types module
- PropertyPanelFlat.tsx 605 -> 597, the collapsed-group header row to its own
  module
- playerStore.ts 604 -> 594, the dev-build console handle to its own module

Extracting in place made PropertyPanelFlat GROW (605 -> 616): a signature plus a
doc comment costs more than an inline arrow saves. Only a move to a sibling
module actually removes lines.

Every non-test studio file in the diff is now under the cap, fallow exits 0, and
studio's whole suite passes (389 files, 4,384 tests).
This commit is contained in:
Vance Ingalls
2026-08-20 16:40:36 -07:00
parent bbee47cfb1
commit fdf0cf3125
12 changed files with 211 additions and 85 deletions
@@ -642,6 +642,7 @@ describe("WebAudioTransport", () => {
getFloatTimeDomainData: ReturnType<typeof vi.fn>;
}[] = [];
const masterGain = { gain: { value: 1 }, connect: vi.fn(), disconnect: vi.fn() };
const mediaElementSource = { connect: vi.fn(), disconnect: vi.fn() };
const ctx = {
currentTime,
state: "running",
@@ -687,10 +688,14 @@ describe("WebAudioTransport", () => {
analysers.push(node);
return node;
}),
// The media-element route needs this as much as the decoded one: without
// it `scheduleMediaElementPlayback` throws and its catch returns null,
// which reads as "the member did not play" rather than a missing stub.
createMediaElementSource: vi.fn(() => mediaElementSource),
destination: {},
close: vi.fn(),
};
return { ctx, gainNodes, analysers, masterGain };
return { ctx, gainNodes, analysers, masterGain, mediaElementSource };
}
function setupGroupTransport(currentTime = 100) {
@@ -743,6 +748,30 @@ describe("WebAudioTransport", () => {
expect(clipGain!.connect).toHaveBeenCalledWith(mock.masterGain);
});
// The media-element transport is the PRIMARY path for audio — the runtime
// tries it first and only falls back to a decoded buffer. It has to reach
// the same bus, or grouping silently applies to nothing that actually plays.
it("routes a grouped clip's MEDIA-ELEMENT playback to the group bus, not master", async () => {
const { transport, mock, gen } = setupGroupTransport();
const el = groupedAudioEl("vo-1", "vo");
await transport.scheduleMediaElementPlayback(el, 0, 0, 0, 1, gen, 1);
const clipGain = mock.gainNodes[0]!;
expect(clipGain.connect).toHaveBeenCalledWith(firstGroupInput(mock));
expect(clipGain.connect).not.toHaveBeenCalledWith(mock.masterGain);
});
it("routes an UNGROUPED clip's media-element playback straight to master", async () => {
const { transport, mock, gen } = setupGroupTransport();
const el = groupedAudioEl("lone");
await transport.scheduleMediaElementPlayback(el, 0, 0, 0, 1, gen, 1);
expect(mock.gainNodes).toHaveLength(1);
expect(mock.gainNodes[0]!.connect).toHaveBeenCalledWith(mock.masterGain);
});
it("two members of the same group land on ONE shared group gain, not master directly", async () => {
const { transport, mock, gen } = setupGroupTransport();