Files
openmaic/OpenMAIC/packages/@openmaic/generation/test/media-prompt-wiring.test.ts
2026-08-16 14:58:47 +08:00

144 lines
4.7 KiB
TypeScript

import { describe, expect, test } from 'vitest';
import { generateSceneOutlinesFromRequirements } from '@openmaic/generation';
import { generateSceneContent } from '@openmaic/generation';
import type { SceneOutline, UserRequirements } from '@openmaic/generation';
import type { AICallFn } from '@openmaic/generation';
describe('media prompt condition wiring', () => {
test('outline generation passes media enable flags into conditional snippets', async () => {
let capturedPrompt = '';
const aiCall: AICallFn = async (system, user) => {
capturedPrompt = `${system}\n${user}`;
return JSON.stringify({
languageDirective: 'Teach in English.',
courseTitle: 'Evaporation',
outlines: [],
});
};
const requirements: UserRequirements = {
requirement: 'Teach evaporation with an animation',
};
const result = await generateSceneOutlinesFromRequirements(
requirements,
undefined,
undefined,
aiCall,
{ imageGenerationEnabled: false, videoGenerationEnabled: true },
);
expect(result.success).toBe(true);
expect(capturedPrompt).toContain('gen_vid_1');
expect(capturedPrompt).not.toContain('gen_img_');
expect(capturedPrompt).not.toContain('suggestedImageIds');
expect(capturedPrompt).not.toContain('{{');
});
test('slide content generation exposes only media element rules backed by outline media', async () => {
let capturedPrompt = '';
const aiCall: AICallFn = async (system, user) => {
capturedPrompt = `${system}\n${user}`;
return JSON.stringify({
background: { type: 'solid', color: '#ffffff' },
elements: [
{
id: 'title',
type: 'text',
left: 60,
top: 80,
width: 880,
height: 76,
content: '<p style="font-size: 28px;">Evaporation</p>',
defaultFontName: '',
defaultColor: '#333333',
},
],
});
};
const outline: SceneOutline = {
id: 'scene_1',
type: 'slide',
title: 'Evaporation Motion',
description: 'Explain evaporation as a moving process',
keyPoints: ['Molecules gain energy', 'Water changes into vapor'],
order: 1,
mediaGenerations: [
{
type: 'video',
prompt: 'Animation of water molecules evaporating',
elementId: 'gen_vid_unique1',
aspectRatio: '16:9',
},
],
};
const result = await generateSceneContent(outline, aiCall);
expect(result).not.toBeNull();
expect(capturedPrompt).toContain('VideoElement');
expect(capturedPrompt).toContain('mediaRef');
expect(capturedPrompt).toContain('gen_vid_unique1');
expect(capturedPrompt).not.toContain('"src": "gen_vid_1"');
expect(capturedPrompt).not.toContain('ImageElement');
expect(capturedPrompt).not.toContain('gen_img_');
expect(capturedPrompt).not.toContain('{{');
});
});
describe('outline courseTitle parsing', () => {
const baseRequirements: UserRequirements = { requirement: 'Teach photosynthesis' };
async function runWith(raw: unknown) {
const aiCall: AICallFn = async (_system, _user) => JSON.stringify(raw);
return generateSceneOutlinesFromRequirements(baseRequirements, undefined, undefined, aiCall);
}
test('adopts a string courseTitle from the wrapper object', async () => {
const result = await runWith({
languageDirective: 'Teach in English.',
courseTitle: 'Photosynthesis Basics',
outlines: [],
});
expect(result.success).toBe(true);
expect(result.data?.courseTitle).toBe('Photosynthesis Basics');
});
test('trims whitespace and caps overlong courseTitle defensively', async () => {
const long = 'A '.repeat(80); // 160 chars
const result = await runWith({
languageDirective: 'Teach in English.',
courseTitle: ` ${long} `,
outlines: [],
});
expect(result.success).toBe(true);
expect(result.data?.courseTitle?.length).toBeLessThanOrEqual(120);
// trimmed
expect(result.data?.courseTitle?.startsWith(' ')).toBe(false);
});
test('returns undefined courseTitle when the field is missing (graceful fallback)', async () => {
const result = await runWith({
languageDirective: 'Teach in English.',
outlines: [],
});
expect(result.success).toBe(true);
expect(result.data?.courseTitle).toBeUndefined();
});
test('ignores a non-string / empty courseTitle', async () => {
const result = await runWith({
languageDirective: 'Teach in English.',
courseTitle: ' ',
outlines: [],
});
expect(result.success).toBe(true);
expect(result.data?.courseTitle).toBeUndefined();
});
});