feat: productionize learning engine and classroom
This commit is contained in:
@@ -202,6 +202,31 @@ describe('packageCourseware (happy path)', () => {
|
||||
});
|
||||
|
||||
describe('packageCourseware (missing resources)', () => {
|
||||
test('allows intentional silent narration when TTS was disabled', async () => {
|
||||
const scenes = structuredClone(makeScenes());
|
||||
const speech = scenes[0].actions?.find((action) => action.type === 'speech');
|
||||
if (speech?.type === 'speech') speech.audioUrl = 'https://should-not-survive.example/audio.mp3';
|
||||
const result = await packageCourseware({
|
||||
coursewareId: 'cw-silent',
|
||||
version: 1,
|
||||
stage: makeStage(),
|
||||
scenes,
|
||||
requireNarrationAudio: false,
|
||||
requireComplete: true,
|
||||
publishedAt: '2026-08-15T00:00:00.000Z',
|
||||
});
|
||||
|
||||
expect(result.completeness.complete).toBe(true);
|
||||
expect(result.completeness.audioCount).toBe(0);
|
||||
expect(result.completeness.missing).not.toContainEqual(
|
||||
expect.objectContaining({ kind: 'audio' }),
|
||||
);
|
||||
expect(result.meta.runtimeCapabilities?.packaged.audio).toBe(false);
|
||||
expect(result.manifest.mediaIndex['audio/aud-1.mp3']).toBeUndefined();
|
||||
expect(result.manifest.scenes[0].actions?.[0]).not.toHaveProperty('audioRef');
|
||||
expect(result.manifest.scenes[0].actions?.[0]).not.toHaveProperty('audioUrl');
|
||||
});
|
||||
|
||||
test('reports missing audio and marks the media index entry', async () => {
|
||||
const result = await packageCourseware({
|
||||
coursewareId: 'cw-1',
|
||||
@@ -301,4 +326,30 @@ describe('packageCourseware (strict frozen publish contract)', () => {
|
||||
}),
|
||||
).rejects.toThrow(/incomplete.*interactive.*lab\.js/i);
|
||||
});
|
||||
|
||||
test('rejects an inlined Pyodide loader whose wasm and stdlib remain runtime downloads', async () => {
|
||||
const scenes = makeScenes().map((scene) =>
|
||||
scene.content.type === 'interactive'
|
||||
? ({
|
||||
...scene,
|
||||
content: {
|
||||
...scene.content,
|
||||
html: '<main>Python lab</main><script>const py = await loadPyodide();</script>',
|
||||
},
|
||||
} as Scene)
|
||||
: scene,
|
||||
);
|
||||
await expect(packageCourseware({
|
||||
coursewareId: 'cw-offline-python',
|
||||
version: 1,
|
||||
stage: makeStage(),
|
||||
scenes,
|
||||
resolveAudioBytes: async () => AUDIO_BYTES,
|
||||
publishedAt: '2026-08-16T00:00:00.000Z',
|
||||
requireAgentRoster: true,
|
||||
requireInteractiveHtml: true,
|
||||
strictInteractiveAssets: true,
|
||||
requireComplete: true,
|
||||
})).rejects.toThrow(/incomplete.*loadPyodide/i);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user