import { describe, expect, it } from 'vitest';
import {
courseMaterialFingerprint,
dedupeCourseMaterialFiles,
} from '@/lib/document/course-materials';
import type { SelectedCourseMaterial } from '@/lib/types/generation';
function fileOf(name: string, content: string, lastModified: number): File {
return new File([content], name, { type: 'text/plain', lastModified });
}
function material(file: File, id: string): SelectedCourseMaterial {
return {
id,
file,
name: file.name,
size: file.size,
lastModified: file.lastModified,
type: file.type,
order: 1,
};
}
describe('courseMaterialFingerprint', () => {
it('is stable for the same name, size, and lastModified', () => {
const a = fileOf('lesson.pdf', 'same bytes', 1_700_000_000_000);
const b = fileOf('lesson.pdf', 'same bytes', 1_700_000_000_000);
expect(courseMaterialFingerprint(a)).toBe(courseMaterialFingerprint(b));
});
it('changes when the name changes', () => {
expect(courseMaterialFingerprint(fileOf('a.pdf', 'x', 1000))).not.toBe(
courseMaterialFingerprint(fileOf('b.pdf', 'x', 1000)),
);
});
it('changes when the size changes', () => {
expect(courseMaterialFingerprint(fileOf('a.pdf', 'x', 1000))).not.toBe(
courseMaterialFingerprint(fileOf('a.pdf', 'xy', 1000)),
);
});
it('changes when lastModified changes', () => {
expect(courseMaterialFingerprint(fileOf('a.pdf', 'x', 1000))).not.toBe(
courseMaterialFingerprint(fileOf('a.pdf', 'x', 1001)),
);
});
it('also fingerprints an existing SelectedCourseMaterial by the same fields', () => {
const file = fileOf('a.pdf', 'x', 1000);
expect(courseMaterialFingerprint(material(file, 'm1'))).toBe(courseMaterialFingerprint(file));
});
});
describe('dedupeCourseMaterialFiles', () => {
it('drops incoming files already present in the existing list', () => {
const existing = fileOf('a.pdf', 'x', 1000);
const incoming = fileOf('a.pdf', 'x', 1000);
expect(dedupeCourseMaterialFiles([material(existing, 'm1')], [incoming])).toEqual([]);
});
it('drops duplicates within a single incoming batch', () => {
const one = fileOf('a.pdf', 'x', 1000);
const two = fileOf('a.pdf', 'x', 1000);
const other = fileOf('b.pdf', 'y', 2000);
expect(dedupeCourseMaterialFiles([], [one, two, other])).toEqual([one, other]);
});
it('keeps distinct files even when only one field differs', () => {
const one = fileOf('a.pdf', 'x', 1000);
const two = fileOf('a.pdf', 'x', 1001);
expect(dedupeCourseMaterialFiles([], [one, two])).toEqual([one, two]);
});
});