Files
openmaic/OpenMAIC/tests/app/api/learning-runtime-finalize.test.ts

71 lines
2.2 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { NextRequest } from 'next/server';
const mocks = vi.hoisted(() => ({
readJob: vi.fn(),
readClassroom: vi.fn(),
finalizeSingle: vi.fn(),
finalizeLarge: vi.fn(),
}));
vi.mock('@/lib/server/classroom-job-store', () => ({
isValidClassroomJobId: () => true,
readClassroomGenerationJob: mocks.readJob,
}));
vi.mock('@/lib/server/classroom-storage', () => ({
buildRequestOrigin: () => 'https://engine.example',
readClassroom: mocks.readClassroom,
}));
vi.mock('@/lib/course-framework/store', () => ({
readCourseRecordReconciled: vi.fn(),
}));
vi.mock('@/lib/makelore-course/finalize', () => ({
finalizeSingleLearningCourse: mocks.finalizeSingle,
finalizeLargeLearningCourse: mocks.finalizeLarge,
frozenLearningFinalizeResponse: vi.fn(),
}));
import { FrozenLearningCourseMutationError } from '@/lib/makelore-course/immutability';
import { POST } from '@/app/api/runtime/v1/courses/jobs/[jobId]/finalize/route';
describe('private Learning Engine finalize route', () => {
beforeEach(() => {
vi.clearAllMocks();
vi.stubEnv('LEARNING_ENGINE_TOKEN', 'engine-secret');
mocks.readJob.mockResolvedValue({
id: 'job-1',
ownerPrincipalId: 'owner-1',
status: 'succeeded',
result: { classroomId: 'course-1' },
input: { interactiveMode: true, enableTTS: true },
});
mocks.readClassroom.mockResolvedValue({ id: 'course-1', stage: {}, scenes: [] });
});
afterEach(() => {
vi.unstubAllEnvs();
});
it('returns a stable conflict when an immutable course source no longer matches', async () => {
mocks.finalizeSingle.mockRejectedValue(new FrozenLearningCourseMutationError('course-1'));
const request = new NextRequest(
'https://engine.example/api/runtime/v1/courses/jobs/job-1/finalize',
{
method: 'POST',
headers: {
Authorization: 'Bearer engine-secret',
'X-Owner-User-Id': 'owner-1',
},
},
);
const response = await POST(request, { params: Promise.resolve({ jobId: 'job-1' }) });
expect(response.status).toBe(409);
await expect(response.json()).resolves.toMatchObject({ error: 'course_frozen' });
});
});