summaryrefslogtreecommitdiff
path: root/apps/web/src/services/storage/migrations/__tests__
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-03-31 23:23:36 +0200
committerMaze Winther <mazewinther@gmail.com>2026-03-31 23:23:36 +0200
commitf1d5932c54178c4f8eac61d3d3e0e4a30101780f (patch)
tree73ebf833517b1f0a9925151a703f335bedf49216 /apps/web/src/services/storage/migrations/__tests__
parentd23be079cce6108482fc3e85401cccf949087174 (diff)
downloadopencut-f1d5932c54178c4f8eac61d3d3e0e4a30101780f.tar.gz
feat: separate audio from elements
Diffstat (limited to 'apps/web/src/services/storage/migrations/__tests__')
-rw-r--r--apps/web/src/services/storage/migrations/__tests__/v19-to-v20.test.ts141
1 files changed, 141 insertions, 0 deletions
diff --git a/apps/web/src/services/storage/migrations/__tests__/v19-to-v20.test.ts b/apps/web/src/services/storage/migrations/__tests__/v19-to-v20.test.ts
new file mode 100644
index 00000000..0e0cfbbe
--- /dev/null
+++ b/apps/web/src/services/storage/migrations/__tests__/v19-to-v20.test.ts
@@ -0,0 +1,141 @@
+import { describe, expect, test } from "bun:test";
+import { transformProjectV19ToV20 } from "../transformers/v19-to-v20";
+
+describe("V19 to V20 Migration", () => {
+ test("backfills source audio enabled state on video elements", () => {
+ const result = transformProjectV19ToV20({
+ project: {
+ id: "project-v19-source-audio",
+ version: 19,
+ metadata: {
+ id: "project-v19-source-audio",
+ name: "Project",
+ createdAt: "2024-01-01T00:00:00.000Z",
+ updatedAt: "2024-01-01T00:00:00.000Z",
+ },
+ settings: {
+ fps: 30,
+ canvasSize: { width: 1920, height: 1080 },
+ background: { type: "color", color: "#000000" },
+ },
+ currentSceneId: "scene-main",
+ scenes: [
+ {
+ id: "scene-main",
+ name: "Main",
+ isMain: true,
+ bookmarks: [],
+ createdAt: "2024-01-01T00:00:00.000Z",
+ updatedAt: "2024-01-01T00:00:00.000Z",
+ tracks: [
+ {
+ id: "track-video",
+ type: "video",
+ name: "Video",
+ isMain: true,
+ muted: false,
+ hidden: false,
+ elements: [
+ {
+ id: "video-1",
+ type: "video",
+ name: "Clip",
+ mediaId: "media-1",
+ duration: 5,
+ startTime: 0,
+ trimStart: 0,
+ trimEnd: 0,
+ transform: {
+ position: { x: 0, y: 0 },
+ scale: { x: 1, y: 1 },
+ rotation: 0,
+ },
+ opacity: 1,
+ },
+ ],
+ },
+ {
+ id: "track-audio",
+ type: "audio",
+ name: "Audio",
+ muted: false,
+ elements: [
+ {
+ id: "audio-1",
+ type: "audio",
+ sourceType: "upload",
+ mediaId: "media-audio-1",
+ name: "Audio",
+ duration: 5,
+ startTime: 0,
+ trimStart: 0,
+ trimEnd: 0,
+ volume: 0,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ });
+
+ expect(result.skipped).toBe(false);
+ expect(result.project.version).toBe(20);
+ expect(
+ ((result.project.scenes as Array<Record<string, unknown>>)[0]
+ .tracks as Array<Record<string, unknown>>)[0].elements,
+ ).toEqual([
+ expect.objectContaining({
+ id: "video-1",
+ isSourceAudioEnabled: true,
+ }),
+ ]);
+ expect(
+ (((result.project.scenes as Array<Record<string, unknown>>)[0]
+ .tracks as Array<Record<string, unknown>>)[1]
+ .elements as Array<Record<string, unknown>>)[0].isSourceAudioEnabled,
+ ).toBeUndefined();
+ });
+
+ test("preserves existing explicit source audio state", () => {
+ const result = transformProjectV19ToV20({
+ project: {
+ id: "project-v19-existing-state",
+ version: 19,
+ scenes: [
+ {
+ tracks: [
+ {
+ elements: [
+ {
+ type: "video",
+ isSourceAudioEnabled: false,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ });
+
+ expect(
+ (((result.project.scenes as Array<Record<string, unknown>>)[0]
+ .tracks as Array<Record<string, unknown>>)[0]
+ .elements as Array<Record<string, unknown>>)[0].isSourceAudioEnabled,
+ ).toBe(false);
+ });
+
+ test("skips projects already on v20", () => {
+ const result = transformProjectV19ToV20({
+ project: {
+ id: "project-v20",
+ version: 20,
+ },
+ });
+
+ expect(result.skipped).toBe(true);
+ expect(result.reason).toBe("already v20");
+ });
+});