Files
wisp/src/lib/learn/glossary.test.ts
T
NilsBriggen 40858e0025
CI / test (push) Successful in 16s
CI / build-apk (push) Has been skipped
CI / deploy-web (push) Successful in 30s
feat(phase3): learning helpers — summary, glossary, flashcards (SM-2), quizzes
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>
2026-06-14 15:37:42 +02:00

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);
});
});