79 lines
2.1 KiB
TypeScript
79 lines
2.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
validateCourseAgentAnchor,
|
|
validateCoursePackageDescriptor,
|
|
} from '../src/index.js';
|
|
|
|
const SHA = 'a'.repeat(64);
|
|
|
|
describe('course package descriptor', () => {
|
|
it('accepts immutable unique-course metadata without a product version', () => {
|
|
const descriptor = {
|
|
schemaVersion: 1,
|
|
kind: 'makelore-course-package',
|
|
courseId: 'course_python_basics',
|
|
contentHash: SHA,
|
|
archiveSha256: 'b'.repeat(64),
|
|
archiveBytes: 1024,
|
|
formatVersion: 1,
|
|
minPlayerVersion: '0.1.0',
|
|
title: 'Python 零基础入门',
|
|
sceneCount: 10,
|
|
capabilities: {
|
|
sceneKinds: ['slide', 'interactive', 'quiz'],
|
|
hasAudio: false,
|
|
hasWhiteboard: false,
|
|
hasAgent: true,
|
|
},
|
|
createdAt: '2026-08-16T00:00:00.000Z',
|
|
};
|
|
|
|
expect(validateCoursePackageDescriptor(descriptor)).toEqual({
|
|
ok: true,
|
|
value: descriptor,
|
|
errors: [],
|
|
});
|
|
expect(descriptor).not.toHaveProperty('version');
|
|
});
|
|
|
|
it('rejects malformed hashes and zero-byte archives', () => {
|
|
const result = validateCoursePackageDescriptor({
|
|
schemaVersion: 1,
|
|
kind: 'makelore-course-package',
|
|
courseId: 'course_1',
|
|
contentHash: 'bad',
|
|
archiveSha256: SHA,
|
|
archiveBytes: 0,
|
|
formatVersion: 1,
|
|
minPlayerVersion: '0.1.0',
|
|
title: 'Course',
|
|
sceneCount: 1,
|
|
capabilities: {
|
|
sceneKinds: ['slide'],
|
|
hasAudio: false,
|
|
hasWhiteboard: false,
|
|
hasAgent: false,
|
|
},
|
|
createdAt: '2026-08-16T00:00:00.000Z',
|
|
});
|
|
|
|
expect(result.ok).toBe(false);
|
|
expect(result.errors).toContain('contentHash must be a SHA-256 hex string');
|
|
expect(result.errors).toContain('archiveBytes must be a positive integer');
|
|
});
|
|
});
|
|
|
|
describe('agent anchor', () => {
|
|
it('binds an Agent request to an exact course and playback position', () => {
|
|
expect(
|
|
validateCourseAgentAnchor({
|
|
courseId: 'course_python_basics',
|
|
contentHash: SHA,
|
|
sceneOrder: 2,
|
|
actionIndex: 1,
|
|
positionMs: 3200,
|
|
}).ok,
|
|
).toBe(true);
|
|
});
|
|
});
|