summaryrefslogtreecommitdiff
path: root/apps/web/src/services/storage/migrations/__tests__
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-29 10:37:39 +0200
committerMaze Winther <mazewinther@gmail.com>2026-05-02 03:27:23 +0200
commit401cc35743aafc4c8bdfb8055501650390bde88b (patch)
tree98385fb2f252ff6bb227a844d96b664a8fe87835 /apps/web/src/services/storage/migrations/__tests__
parentb8d08df244b97b1d3131cb2d076166838189eeb0 (diff)
downloadopencut-401cc35743aafc4c8bdfb8055501650390bde88b.tar.gz
refactor: animate params over time
Diffstat (limited to 'apps/web/src/services/storage/migrations/__tests__')
-rw-r--r--apps/web/src/services/storage/migrations/__tests__/v29-to-v30.test.ts139
1 files changed, 139 insertions, 0 deletions
diff --git a/apps/web/src/services/storage/migrations/__tests__/v29-to-v30.test.ts b/apps/web/src/services/storage/migrations/__tests__/v29-to-v30.test.ts
new file mode 100644
index 00000000..c68f8dce
--- /dev/null
+++ b/apps/web/src/services/storage/migrations/__tests__/v29-to-v30.test.ts
@@ -0,0 +1,139 @@
+import { describe, expect, test } from "bun:test";
+import { transformProjectV29ToV30 } from "../transformers/v29-to-v30";
+import { asRecord, asRecordArray } from "./helpers";
+
+describe("V29 to V30 Migration", () => {
+ test("flattens animation bindings and channels by path", () => {
+ const result = transformProjectV29ToV30({
+ project: {
+ id: "project-v29-animations",
+ version: 29,
+ scenes: [
+ {
+ id: "scene-1",
+ tracks: {
+ main: {
+ id: "main",
+ type: "video",
+ elements: [
+ {
+ id: "text-1",
+ type: "text",
+ animations: {
+ bindings: {
+ opacity: {
+ path: "opacity",
+ kind: "number",
+ components: [
+ { key: "value", channelId: "opacity:value" },
+ ],
+ },
+ color: {
+ path: "color",
+ kind: "color",
+ colorSpace: "srgb-linear",
+ components: [
+ { key: "r", channelId: "color:r" },
+ { key: "g", channelId: "color:g" },
+ { key: "b", channelId: "color:b" },
+ { key: "a", channelId: "color:a" },
+ ],
+ },
+ "params.label": {
+ path: "params.label",
+ kind: "discrete",
+ components: [
+ {
+ key: "value",
+ channelId: "params.label:value",
+ },
+ ],
+ },
+ },
+ channels: {
+ "opacity:value": {
+ kind: "scalar",
+ keys: [{ id: "o1", time: 0, value: 0.5 }],
+ },
+ "color:r": {
+ kind: "scalar",
+ keys: [{ id: "c1", time: 0, value: 1 }],
+ },
+ "color:g": {
+ kind: "scalar",
+ keys: [{ id: "c1", time: 0, value: 0.5 }],
+ },
+ "color:b": {
+ kind: "scalar",
+ keys: [{ id: "c1", time: 0, value: 0 }],
+ },
+ "color:a": {
+ kind: "scalar",
+ keys: [{ id: "c1", time: 0, value: 1 }],
+ },
+ "params.label:value": {
+ kind: "discrete",
+ keys: [{ id: "d1", time: 0, value: "Title" }],
+ },
+ },
+ },
+ },
+ ],
+ },
+ overlay: [],
+ audio: [],
+ },
+ },
+ ],
+ },
+ });
+
+ expect(result.skipped).toBe(false);
+ expect(result.project.version).toBe(30);
+ const scene = asRecordArray(result.project.scenes)[0];
+ const tracks = asRecord(scene.tracks);
+ const main = asRecord(tracks.main);
+ const element = asRecordArray(main.elements)[0];
+ const animations = asRecord(element.animations);
+ expect(animations.bindings).toBeDefined();
+ expect(animations.channels).toBeDefined();
+ expect(animations).toMatchObject({
+ opacity: {
+ keys: [{ id: "o1", time: 0, value: 0.5 }],
+ },
+ color: {
+ r: { keys: [{ id: "c1", time: 0, value: 1 }] },
+ g: { keys: [{ id: "c1", time: 0, value: 0.5 }] },
+ b: { keys: [{ id: "c1", time: 0, value: 0 }] },
+ a: { keys: [{ id: "c1", time: 0, value: 1 }] },
+ },
+ "params.label": {
+ keys: [{ id: "d1", time: 0, value: "Title" }],
+ },
+ });
+ });
+
+ test("leaves elements without animations unchanged", () => {
+ const result = transformProjectV29ToV30({
+ project: {
+ id: "project-v29-no-animations",
+ version: 29,
+ scenes: [
+ {
+ tracks: {
+ main: {
+ elements: [{ id: "image-1", type: "image" }],
+ },
+ },
+ },
+ ],
+ },
+ });
+
+ const scene = asRecordArray(result.project.scenes)[0];
+ const tracks = asRecord(scene.tracks);
+ const main = asRecord(tracks.main);
+ const element = asRecordArray(main.elements)[0];
+ expect(element).toEqual({ id: "image-1", type: "image" });
+ });
+});