40858e0025
Deterministic, on-device, no model: - src/lib/learn pure modules (tokenize, summary [TextRank-ish], glossary [definition-pattern + frequency], flashcards [cloze/Q-A], srs [SM-2], quiz [MCQ with distractors]) — 37 unit tests. - Flashcard persistence: Dexie v4 + native v4 `flashcards` table; create/list/ listDue/updateSrs/delete/counts; cascades (transcript delete, course->Unsorted). - UI: transcript "Study aids" (generate summary+glossary, click-to-seek; create flashcards), Study screen (SM-2 review + Anki CSV export), per-lecture Quiz, library Study link with due-count badge. 215 tests green, 0 tsc errors, web export builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { glossary } from './glossary';
|
|
import type { Segment } from '../types';
|
|
|
|
const seg = (start: number, text: string, id?: string): Segment => ({
|
|
id,
|
|
start,
|
|
end: start + 1,
|
|
text,
|
|
});
|
|
|
|
describe('glossary', () => {
|
|
it('returns [] for no segments', () => {
|
|
expect(glossary([])).toEqual([]);
|
|
});
|
|
|
|
it('captures an "X is Y" definition pattern', () => {
|
|
const segs = [
|
|
seg(3, 'Backpropagation is an algorithm for training neural networks.', 's1'),
|
|
];
|
|
const out = glossary(segs);
|
|
const entry = out.find((e) => e.term.toLowerCase() === 'backpropagation');
|
|
expect(entry).toBeDefined();
|
|
expect(entry!.definition).toBe(
|
|
'Backpropagation is an algorithm for training neural networks.',
|
|
);
|
|
expect(entry!.start).toBe(3);
|
|
expect(entry!.segmentId).toBe('s1');
|
|
});
|
|
|
|
it('recognizes means / refers to / is defined as', () => {
|
|
const segs = [
|
|
seg(0, 'Entropy means the amount of disorder in a system.'),
|
|
seg(1, 'A token refers to a unit of text.'),
|
|
seg(2, 'Latency is defined as the delay before a transfer begins.'),
|
|
];
|
|
const terms = glossary(segs).map((e) => e.term.toLowerCase());
|
|
expect(terms).toContain('entropy');
|
|
expect(terms).toContain('a token');
|
|
expect(terms).toContain('latency');
|
|
});
|
|
|
|
it('dedupes by lowercased term, preferring the explicit definition', () => {
|
|
const segs = [
|
|
seg(0, 'Recursion is fun. Recursion appears again here as Recursion.'),
|
|
seg(1, 'Recursion is when a function calls itself.', 'def'),
|
|
];
|
|
const out = glossary(segs);
|
|
const recursion = out.filter((e) => e.term.toLowerCase() === 'recursion');
|
|
expect(recursion.length).toBe(1);
|
|
expect(recursion[0]!.definition).toBe(
|
|
'Recursion is when a function calls itself.',
|
|
);
|
|
});
|
|
|
|
it('respects the max cap', () => {
|
|
const segs = [
|
|
seg(0, 'Apple is a fruit.'),
|
|
seg(1, 'Banana is a fruit.'),
|
|
seg(2, 'Cherry is a fruit.'),
|
|
];
|
|
expect(glossary(segs, { max: 2 }).length).toBeLessThanOrEqual(2);
|
|
});
|
|
});
|