import { readFile } from "node:fs/promises"; import { describe, expect, it } from "vitest"; import { hasCompleteSeedreamLayerMetadata } from "@/lib/seedream/layer-composition"; describe("Seedream layer composition persistence contract", () => { it("only enables the editable layer project for complete provider layer metadata", () => { expect(hasCompleteSeedreamLayerMetadata([ { z_index: 0, size: "2048x2048" }, { z_index: 1, size: "600x300" } ], 2)).toBe(true); expect(hasCompleteSeedreamLayerMetadata([ { size: "2048x2048" }, { size: "600x300" } ], 2)).toBe(false); expect(hasCompleteSeedreamLayerMetadata([{ z_index: 0 }], 2)).toBe(false); expect(hasCompleteSeedreamLayerMetadata([{ z_index: 0 }], 1)).toBe(false); }); it("ships a versioned PostgreSQL document table that follows generation-job deletion", async () => { const migration = await readFile(new URL("../database/migrations/0005_seedream_layer_compositions.sql", import.meta.url), "utf8"); expect(migration).toContain("create table if not exists public.seedream_layer_compositions"); expect(migration).toContain("references public.generation_jobs(id) on delete cascade"); expect(migration).toContain("layers jsonb not null"); expect(migration).toContain("version bigint not null"); expect(migration).toContain("jsonb_typeof(layers) = 'array'"); }); it("exposes owner-scoped GET/PUT routes and provisions application-role privileges", async () => { const [surface, privileges, handler] = await Promise.all([ readFile(new URL("../contracts/http/route-surface.v1.json", import.meta.url), "utf8"), readFile(new URL("../scripts/migrate-postgres.mjs", import.meta.url), "utf8"), readFile(new URL("../backend/internal/httpapi/layer_compositions.go", import.meta.url), "utf8") ]); expect(surface).toContain('"GET", "path": "/api/layer-compositions/{id}"'); expect(surface).toContain('"PUT", "path": "/api/layer-compositions/{id}"'); expect(privileges).toContain('["seedream_layer_compositions", "SELECT, INSERT, UPDATE, DELETE"]'); expect(handler).toContain("handler.platform.Authorize"); expect(handler).toContain("jobs.Scope{OwnerID: session.User.ID}"); }); });