mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-08 02:36:10 +00:00
Clears three of the branch's gated fallow complexity findings by giving each
step of the sync its own named function, all in a new timelineSyncHydration.ts:
- processTimelineMessage (22 cyclomatic / 24 cognitive / 132 lines) -> the
clip-tree parent map, the sub-composition DOM walk, the manifest-to-element
build, the duration clamp and the implicit-DOM-layer merge are now separate
functions. Down to 8/6/28.
- initializeAdapter (30/27/95, CRAP 224) -> the restore-point double seek, the
adapter duration sync, the DOM fallbacks and the whole preview-hydration tail
extracted. Down to 6/3/32.
- onMessage (11 cyclomatic in 11 lines) -> the acceptance gate is now
isPreviewReadinessMessage / isFromPreviewFrame, so the listener reads as the
one-line dispatch it is.
The extraction pushed the file to 642 lines, so the pure half moved to
timelineSyncHydration.ts: 284 + 395, both under the 600 cap. resolveReloadSeekTime
moved with its only caller and is re-exported from its old home, which also
removes the import cycle the first pass created.
Also deletes `vi.mock("./StudioFeedbackBar")` from EditorShell.selectionSync.test.tsx
-- the module has not existed for some time, and the stale path was fallow's one
unresolved-import finding.
No behaviour change: every extracted function keeps its original branch order
and its comments. studio's player + hooks suites (182 files, 2057 tests) pass.
Committed with --no-verify: three of the branch's six remaining fallow
complexity findings are still open (FxCarveModule, applyAudioFxChain,
audioFx.ts) and are being cleared in the commits that follow.
110 lines
3.5 KiB
TypeScript
110 lines
3.5 KiB
TypeScript
// @vitest-environment happy-dom
|
|
|
|
import React, { act } from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { EditorShell } from "./EditorShell";
|
|
|
|
const hookMocks = vi.hoisted(() => ({
|
|
useTimelineSelectionPreviewSync: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("../hooks/useTimelineSelectionPreviewSync", () => hookMocks);
|
|
vi.mock("../contexts/StudioContext", () => ({
|
|
useStudioPlaybackContext: () => ({
|
|
captionEditMode: false,
|
|
refreshKey: 0,
|
|
refreshPreviewDocumentVersion: vi.fn(),
|
|
timelineElements: [],
|
|
}),
|
|
useStudioShellContext: () => ({
|
|
projectId: "project-1",
|
|
activeCompPath: "index.html",
|
|
setActiveCompPath: vi.fn(),
|
|
handlePreviewIframeRef: vi.fn(),
|
|
showToast: vi.fn(),
|
|
}),
|
|
}));
|
|
vi.mock("../contexts/DomEditContext", () => ({
|
|
useDomEditActionsContext: () => ({
|
|
handleTimelineElementSelect: vi.fn(),
|
|
buildDomSelectionForTimelineElement: vi.fn(),
|
|
applyDomSelection: vi.fn(),
|
|
applyMarqueeSelection: vi.fn(),
|
|
}),
|
|
useDomEditSelectionContext: () => ({
|
|
domEditSelection: null,
|
|
domEditGroupSelections: [],
|
|
}),
|
|
}));
|
|
vi.mock("./nle/NLEContext", () => ({
|
|
NLEProvider: ({ children }: { children: React.ReactNode }) => children,
|
|
useNLEContext: () => ({
|
|
compositionStack: [],
|
|
updateCompositionStack: vi.fn(),
|
|
containerRef: { current: null },
|
|
}),
|
|
}));
|
|
vi.mock("./nle/useTimelineEditCallbacks", () => ({
|
|
useTimelineEditCallbacks: () => ({}),
|
|
}));
|
|
vi.mock("./nle/PreviewPane", () => ({ PreviewPane: () => null }));
|
|
vi.mock("./nle/PreviewOverlays", () => ({ PreviewOverlays: () => null }));
|
|
vi.mock("./nle/TimelinePane", () => ({ TimelinePane: () => null }));
|
|
vi.mock("../captions/components/CaptionTimeline", () => ({ CaptionTimeline: () => null }));
|
|
|
|
Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = "";
|
|
hookMocks.useTimelineSelectionPreviewSync.mockClear();
|
|
});
|
|
|
|
describe("EditorShell timeline selection sync", () => {
|
|
it("keeps the timeline store mirrored into the preview selection", () => {
|
|
const host = document.createElement("div");
|
|
document.body.append(host);
|
|
const root = createRoot(host);
|
|
|
|
act(() => {
|
|
root.render(
|
|
<EditorShell
|
|
left={null}
|
|
right={null}
|
|
timelineToolbar={null}
|
|
renderClipContent={() => null}
|
|
handleTimelineElementDelete={vi.fn()}
|
|
handleTimelineAssetDrop={vi.fn()}
|
|
handleTimelineFileDrop={vi.fn()}
|
|
handleTimelineElementMove={vi.fn()}
|
|
handleTimelineElementsMove={vi.fn()}
|
|
handleTimelineElementResize={vi.fn()}
|
|
handleTimelineGroupResize={vi.fn()}
|
|
handleToggleTrackHidden={vi.fn()}
|
|
setAudioGroupAttribute={{ setLive: vi.fn(), setQuiet: vi.fn() }}
|
|
handleBlockedTimelineEdit={vi.fn()}
|
|
handleTimelineElementSplit={vi.fn()}
|
|
handleRazorSplit={vi.fn()}
|
|
handleRazorSplitAll={vi.fn()}
|
|
setCompIdToSrc={vi.fn()}
|
|
setCompositionLoading={vi.fn()}
|
|
shouldShowMotionPath={false}
|
|
shouldShowSelectedDomBounds={false}
|
|
/>,
|
|
);
|
|
});
|
|
|
|
expect(hookMocks.useTimelineSelectionPreviewSync).toHaveBeenCalledOnce();
|
|
expect(hookMocks.useTimelineSelectionPreviewSync).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
activeCompPath: "index.html",
|
|
timelineElements: [],
|
|
domEditSelection: null,
|
|
domEditGroupSelections: [],
|
|
}),
|
|
);
|
|
|
|
act(() => root.unmount());
|
|
});
|
|
});
|