import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, test } from "bun:test";
import { resolveActiveCanvasMediaNodeId } from "../src/lib/canvas/canvas-performance-mode";
import { videoMetadata } from "../src/lib/canvas/canvas-generation-task-sync";
import { canvasNodeVideoPreviewUrl, canvasVideoAssetPreviewUrl } from "../src/lib/canvas/canvas-media-preview";
import { collectImageStorageKeys } from "../src/services/image-storage";
import { CanvasNodeType, type CanvasNodeData } from "../src/types/canvas";
import { detectVideoAudioTrack, detectVideoAudioTrackFromBlob, detectVideoAudioTrackFromUrl } from "../src/lib/video-poster";
const canvasNodeContentSource = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-node-content.tsx"), "utf8");
const canvasAudioPlayerSource = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-audio-player.tsx"), "utf8");
const canvasMentionSource = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-resource-mention-textarea.tsx"), "utf8");
const canvasNodeSource = readFileSync(resolve(import.meta.dir, "../src/components/canvas/canvas-node.tsx"), "utf8");
const videoPlayerSource = readFileSync(resolve(import.meta.dir, "../src/components/video-player.tsx"), "utf8");
function node(id: string, type: CanvasNodeType): CanvasNodeData {
return { id, type, title: id, position: { x: 0, y: 0 }, width: 320, height: 180, metadata: {} };
}
describe("canvas media activation", () => {
const nodes = [node("video", CanvasNodeType.Video), node("audio", CanvasNodeType.Audio), node("image", CanvasNodeType.Image)];
const nodeById = new Map(nodes.map((item) => [item.id, item]));
test("activates exactly one selected video or audio node", () => {
expect(resolveActiveCanvasMediaNodeId(new Set(["video"]), nodeById)).toBe("video");
expect(resolveActiveCanvasMediaNodeId(new Set(["audio"]), nodeById)).toBe("audio");
});
test("keeps media inactive for empty, multi-selection, and non-media selection", () => {
expect(resolveActiveCanvasMediaNodeId(new Set(), nodeById)).toBeNull();
expect(resolveActiveCanvasMediaNodeId(new Set(["video", "audio"]), nodeById)).toBeNull();
expect(resolveActiveCanvasMediaNodeId(new Set(["image"]), nodeById)).toBeNull();
expect(resolveActiveCanvasMediaNodeId(new Set(["missing"]), nodeById)).toBeNull();
});
});
describe("canvas dimension header rendering", () => {
test("tracks live viewport scale without React width commits", () => {
expect(canvasNodeSource).toContain("calc(var(--canvas-node-width) * var(--canvas-live-scale, 1))");
expect(canvasNodeSource).toContain('"--canvas-node-width": `${node.width}px`');
});
});
describe("audio canvas interaction", () => {
test("uses a lightweight player without a native audio element or inactive mask", () => {
expect(canvasNodeContentSource).toContain("");
expect(canvasNodeContentSource).not.toContain("