import assert from "node:assert/strict"; import { dbRun, withTransaction } from "../server/db.mjs"; const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787"; const scope = { "x-organization-id": "org-studio-lab", "x-workspace-id": "ws-local-aidrama", "x-project-id": "thunder-mouth" }; async function request(path, options = {}) { const response = await fetch(`${api}${path}`, { ...options, headers: { "content-type": "application/json", ...(options.headers || {}) } }); const payload = await response.json().catch(() => ({})); return { response, payload }; } const login = await request("/api/auth/login", { method: "POST", body: JSON.stringify({ email: "producer@local.test", password: "Demo@123456" }) }); assert.equal(login.response.ok, true, "catalog smoke login failed"); const headers = { authorization: `Bearer ${login.payload.session.token}`, ...scope }; let seasonId = ""; let episodeId = ""; try { const catalog = await request("/api/production/catalog", { headers }); assert.equal(catalog.response.ok, true, "production catalog must be readable"); assert.ok(catalog.payload.catalog.seasons.length >= 1, "catalog must include at least one season"); assert.ok(catalog.payload.catalog.seasons[0].episodes.length >= 1, "catalog must include at least one episode"); const createdSeason = await request("/api/production/seasons", { method: "POST", headers, body: JSON.stringify({ title: `Smoke Season ${Date.now()}` }) }); assert.equal(createdSeason.response.status, 201, "season creation must return 201"); seasonId = createdSeason.payload.season.id; const createdEpisode = await request("/api/production/episodes", { method: "POST", headers, body: JSON.stringify({ seasonId, title: "Smoke Episode" }) }); assert.equal(createdEpisode.response.status, 201, "episode creation must return 201"); episodeId = createdEpisode.payload.episode.id; assert.equal(createdEpisode.payload.episode.shotCount, 1, "new episode must initialize one shot draft"); const graph = await request(`/api/production/graph?episodeId=${encodeURIComponent(episodeId)}`, { headers }); assert.equal(graph.response.ok, true, "episode graph must be readable"); assert.equal(graph.payload.graph.episode.id, episodeId, "graph must switch to requested episode"); assert.equal(graph.payload.graph.shots.length, 1, "new episode graph must contain starter shot"); assert.equal(graph.payload.graph.catalog.activeEpisodeId, episodeId, "catalog must reflect active episode"); const updated = await request(`/api/production/episodes/${encodeURIComponent(episodeId)}`, { method: "PATCH", headers, body: JSON.stringify({ status: "production", hook: "Smoke hook" }) }); assert.equal(updated.response.ok, true, "episode update must succeed"); assert.equal(updated.payload.episode.status, "production", "episode status must persist"); console.log("production catalog smoke passed"); } finally { if (seasonId) { withTransaction(() => { dbRun("DELETE FROM review_comments WHERE review_id IN (SELECT id FROM reviews WHERE shot_id IN (SELECT id FROM shots WHERE episode_id = ?))", [episodeId]); dbRun("DELETE FROM reviews WHERE shot_id IN (SELECT id FROM shots WHERE episode_id = ?)", [episodeId]); dbRun("DELETE FROM voice_lines WHERE shot_id IN (SELECT id FROM shots WHERE episode_id = ?)", [episodeId]); dbRun("DELETE FROM shot_versions WHERE shot_id IN (SELECT id FROM shots WHERE episode_id = ?)", [episodeId]); dbRun("DELETE FROM shots WHERE episode_id = ?", [episodeId]); dbRun("DELETE FROM script_documents WHERE episode_id = ?", [episodeId]); dbRun("DELETE FROM episodes WHERE id = ?", [episodeId]); dbRun("DELETE FROM seasons WHERE id = ?", [seasonId]); dbRun("DELETE FROM audit_logs WHERE target_id IN (?, ?)", [seasonId, episodeId]); }); } }