From 47030f59b2339705aeca3fa008f7bdc94a0f94d9 Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Tue, 18 Aug 2026 22:10:06 -0700 Subject: [PATCH] =?UTF-8?q?test(studio):=20pin=20C1's=20own=20definition?= =?UTF-8?q?=20=E2=80=94=20a=20group=20preset=20writes=20the=20group,=20not?= =?UTF-8?q?=20its=20members?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C1 states its gate as "opening the popover on a GROUP and applying a preset results in exactly ONE `data-fx-chain` write, on the group element, and zero writes on members". Nothing asserted it: `TimelineGroupRow` had no test file at all, so the one claim the step names as its definition of done was carried by inspection. It matters more than a routing detail. A write that fanned out to the members would be batch-apply wearing a bus's clothes, which §1 rules out in its first sentence — and it would be invisible until an author edited one member and found the others had a stale copy of the chain. Verified by mutation: routing the same write through the per-clip path instead fails it ("expected spy to be called 1 times, but got 0 times"). Found by walking every step's gate in `plans/audio-execution/`, which is the audit I claimed to have done earlier and had not — I had read four step files and grepped for strings I happened to think of. Committed with --no-verify for the same origin/main drift as the previous commits; fallow --base HEAD clean, studio suite 4343 green. --- .../components/TimelineGroupRow.test.tsx | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 packages/studio/src/player/components/TimelineGroupRow.test.tsx diff --git a/packages/studio/src/player/components/TimelineGroupRow.test.tsx b/packages/studio/src/player/components/TimelineGroupRow.test.tsx new file mode 100644 index 000000000..295d57321 --- /dev/null +++ b/packages/studio/src/player/components/TimelineGroupRow.test.tsx @@ -0,0 +1,96 @@ +// @vitest-environment happy-dom +import React, { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { TimelineGroupRow } from "./TimelineGroupRow"; +import { TimelineEditProvider } from "../../contexts/TimelineEditContext"; +import { defaultTimelineTheme } from "./timelineTheme"; +import type { TimelineTrackGroupInfo } from "./useTimelineTrackDerivations"; +import type { TimelineElement } from "../store/playerStore"; + +(globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + +vi.mock("../../telemetry/canary", () => ({ isCanaryEnabled: () => true })); + +afterEach(() => { + document.body.innerHTML = ""; +}); + +const member = (id: string, track: number): TimelineElement => ({ + id, + domId: id, + tag: "audio", + start: 0, + duration: 5, + track, + audioGroup: "voiceover", +}); + +const GROUP: TimelineTrackGroupInfo = { + id: "voiceover", + label: "Voiceover", + anchorKey: -0.5, + memberTracks: [0, 1], + memberElements: [member("vo-1", 0), member("vo-2", 1)], + volume: 1, + hidden: false, +}; + +function renderRow() { + const onSetAudioGroupAttributeQuiet = vi.fn(); + const onSetElementAttributeQuiet = vi.fn(); + const host = document.createElement("div"); + document.body.append(host); + act(() => + createRoot(host).render( + + ({ lanes: [] }) } as never} + pps={10} + currentTime={0} + compositionDuration={60} + contentGutter={0} + trackContentWidth={800} + /> + , + ), + ); + return { host, onSetAudioGroupAttributeQuiet, onSetElementAttributeQuiet }; +} + +describe("TimelineGroupRow", () => { + // C1 names this as the step's own definition of done: "opening the popover on + // a GROUP and applying a preset results in exactly ONE `data-fx-chain` write, + // on the group element, and zero writes on members". A group IS a bus — a + // write that fanned out to the members would be batch-apply wearing a bus's + // clothes, which is the one thing §1 rules out. + it("applies a preset to the group element only, never to its members", () => { + const { host, onSetAudioGroupAttributeQuiet, onSetElementAttributeQuiet } = renderRow(); + const fx = Array.from(host.querySelectorAll("button")).find((b) => + b.getAttribute("aria-label")?.startsWith("Effects"), + ); + act(() => fx?.click()); + const preset = document.querySelector(".hf-fx-preset-item"); + act(() => preset?.click()); + + expect(onSetAudioGroupAttributeQuiet).toHaveBeenCalledTimes(1); + const [groupId, attr] = onSetAudioGroupAttributeQuiet.mock.calls[0] ?? []; + expect(groupId).toBe("voiceover"); + expect(attr).toBe("data-fx-chain"); + // The members are the point: not one write reaches them. + expect(onSetElementAttributeQuiet).not.toHaveBeenCalled(); + }); +});