import { describe, expect, it } from 'vitest';
import { normalizeScenes, VideoTimelineCompileError } from '@/lib/video-export';
import { act, quiz, slide, speech, spotlight } from './helpers';
describe('normalizeScenes — ordering', () => {
it('orders scenes by `order`, tie-broken by input index (stable)', () => {
const scenes = [
slide('c', [], { order: 2 }),
slide('a', [], { order: 1 }),
slide('b', [], { order: 1 }),
];
const { scenes: out } = normalizeScenes(scenes);
expect(out.map((s) => s.id)).toEqual(['a', 'b', 'c']);
});
it('falls back to input index when `order` is absent, preserving input order', () => {
const scenes = [
{ ...slide('x', []), order: undefined },
{ ...slide('y', []), order: undefined },
];
const { scenes: out } = normalizeScenes(scenes as never);
expect(out.map((s) => s.id)).toEqual(['x', 'y']);
});
it('throws on an empty scene list', () => {
expect(() => normalizeScenes([])).toThrow(VideoTimelineCompileError);
});
});
describe('normalizeScenes — action validation', () => {
it('drops an unknown action type with an unknown-action diagnostic', () => {
const scenes = [slide('s', [act({ id: 'bad', type: 'teleport' }), speech('ok', 'hi')])];
const { scenes: out, diagnostics } = normalizeScenes(scenes);
expect(out[0].actions).toHaveLength(1);
expect(out[0].actions?.[0].id).toBe('ok');
expect(diagnostics).toEqual([
expect.objectContaining({ code: 'unknown-action', sceneId: 's', actionId: 'bad' }),
]);
});
it('drops an action missing a required field with an invalid-action diagnostic', () => {
const scenes = [slide('s', [act({ id: 'sp', type: 'spotlight' }), spotlight('good', 'e1')])];
const { scenes: out, diagnostics } = normalizeScenes(scenes);
expect(out[0].actions?.map((a) => a.id)).toEqual(['good']);
expect(diagnostics[0]).toMatchObject({ code: 'invalid-action', actionId: 'sp' });
});
it('keeps an empty-text speech (a legal dwell beat)', () => {
const { scenes: out, diagnostics } = normalizeScenes([slide('s', [speech('e', '')])]);
expect(out[0].actions).toHaveLength(1);
expect(diagnostics).toHaveLength(0);
});
it('does not mutate the input scenes', () => {
const scenes = [slide('b', [], { order: 2 }), slide('a', [], { order: 1 })];
normalizeScenes(scenes);
expect(scenes.map((s) => s.id)).toEqual(['b', 'a']);
});
it('validates quiz scene actions too', () => {
const { diagnostics } = normalizeScenes([quiz('q', [act({ id: 'z', type: 'nope' })])]);
expect(diagnostics[0].code).toBe('unknown-action');
});
});