From b52bdedf83779e8c9c20bd91e4e586caa0f9f5a6 Mon Sep 17 00:00:00 2001 From: wiiiii123 Date: Sun, 24 May 2026 21:33:58 +0700 Subject: [PATCH] test(editor): cover clip speed edge cases --- .../video-editor/clipSpeedChange.test.ts | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/components/video-editor/clipSpeedChange.test.ts b/src/components/video-editor/clipSpeedChange.test.ts index f54a6644..d4f2b6c1 100644 --- a/src/components/video-editor/clipSpeedChange.test.ts +++ b/src/components/video-editor/clipSpeedChange.test.ts @@ -10,12 +10,39 @@ describe("formatClipSpeedLabel", () => { it("returns labels only for non-default positive speeds", () => { expect(formatClipSpeedLabel(1)).toBeNull(); expect(formatClipSpeedLabel(0)).toBeNull(); + expect(formatClipSpeedLabel(-1)).toBeNull(); + expect(formatClipSpeedLabel(Number.POSITIVE_INFINITY)).toBeNull(); + expect(formatClipSpeedLabel(Number.NaN)).toBeNull(); expect(formatClipSpeedLabel(0.5)).toBe("0.5x"); expect(formatClipSpeedLabel(2)).toBe("2x"); }); }); describe("planClipSpeedChange", () => { + it("returns null for missing clips and invalid speeds", () => { + const clipRegions = [{ id: "clip-1", startMs: 0, endMs: 5_000, speed: 1 }]; + + expect( + planClipSpeedChange({ + clipRegions, + zoomRegions: [], + selectedClipId: "missing", + speed: 0.5, + }), + ).toBeNull(); + + for (const speed of [0, -1, Number.NaN, Number.POSITIVE_INFINITY]) { + expect( + planClipSpeedChange({ + clipRegions, + zoomRegions: [], + selectedClipId: "clip-1", + speed, + }), + ).toBeNull(); + } + }); + it("extends an isolated clip when slowing it down", () => { const result = planClipSpeedChange({ clipRegions: [{ id: "clip-1", startMs: 0, endMs: 5_000, speed: 1 }], @@ -30,6 +57,34 @@ describe("planClipSpeedChange", () => { }); }); + it("shortens an isolated clip when speeding it up", () => { + const result = planClipSpeedChange({ + clipRegions: [{ id: "clip-1", startMs: 0, endMs: 6_000, speed: 1 }], + zoomRegions: [], + selectedClipId: "clip-1", + speed: 2, + }); + + expect(result).toEqual({ + clipRegions: [{ id: "clip-1", startMs: 0, endMs: 3_000, speed: 2 }], + zoomRegions: [], + }); + }); + + it("treats invalid stored clip speed as 1x", () => { + const result = planClipSpeedChange({ + clipRegions: [{ id: "clip-1", startMs: 0, endMs: 4_000, speed: Number.NaN }], + zoomRegions: [], + selectedClipId: "clip-1", + speed: 0.5, + }); + + expect(result).toEqual({ + clipRegions: [{ id: "clip-1", startMs: 0, endMs: 8_000, speed: 0.5 }], + zoomRegions: [], + }); + }); + it("blocks slow speed changes that would overlap the next clip", () => { const result = planClipSpeedChange({ clipRegions: [ @@ -62,6 +117,26 @@ describe("planClipSpeedChange", () => { }); }); + it("does not scale zoom regions that start outside the changed clip", () => { + const result = planClipSpeedChange({ + clipRegions: [{ id: "clip-1", startMs: 2_000, endMs: 6_000, speed: 1 }], + zoomRegions: [ + { id: "zoom-before", startMs: 1_000, endMs: 1_500, depth: 2, focus: { cx: 0.5, cy: 0.5 } }, + { id: "zoom-after", startMs: 6_000, endMs: 6_500, depth: 2, focus: { cx: 0.5, cy: 0.5 } }, + ], + selectedClipId: "clip-1", + speed: 0.5, + }); + + expect(result).toEqual({ + clipRegions: [{ id: "clip-1", startMs: 2_000, endMs: 10_000, speed: 0.5 }], + zoomRegions: [ + { id: "zoom-before", startMs: 1_000, endMs: 1_500, depth: 2, focus: { cx: 0.5, cy: 0.5 } }, + { id: "zoom-after", startMs: 6_000, endMs: 6_500, depth: 2, focus: { cx: 0.5, cy: 0.5 } }, + ], + }); + }); + it("blocks speed changes that would make scaled zooms overlap unchanged zooms", () => { const result = planClipSpeedChange({ clipRegions: [{ id: "clip-1", startMs: 0, endMs: 5_000, speed: 1 }],