Files
Mind-o-Mat/tests/tfidf.test.ts
T
Jannik 080656b65a
CI / test (push) Canceled after 0s
CI / webapp (push) Canceled after 0s
ESLint 9 Flat-Config-Migration (Bonus 14)
- eslint.config.js (NEU): Flat-Config fuer ESLint 9
  - Globals explizit definiert (console, process, Buffer, etc.)
  - TypeScript-Parser + Plugin
  - Rules: no-unused-vars, no-explicit-any (warn)
  - Tests haben relaxed rules (no-explicit-any off, fuer Mocks)
- .eslintrc.cjs -> .eslintrc.cjs.bak (Deprecation-Warnung weg)
- package.json scripts.lint: USE_FLAT_CONFIG-Flag entfernt (default flat)
- Tests: 2 tote Variablen entfernt
  - tests/tfidf.test.ts: jaccardSim (ungenutzt, nur Kommentar-Vergleich noetig)
  - tests/webapp/manifest.test.ts: indexHtmlPath (ungenutzt)

Verifiziert:
- 117/117 Tests gruen
- ESLint exit 0 (ohne Deprecation-Warnung)
- Tool-Build OK, Webapp-Build OK
2026-09-05 13:03:19 +02:00

76 lines
2.8 KiB
TypeScript

// Tests fuer 2.5-erweitert (TF-IDF Cosinus-Aehnlichkeit)
// Phase 2.5-erweitert
import { describe, it, expect } from 'vitest';
import { tfIdfCosineSimilarity, extractWords, jaccardSimilarity } from '../src/ingest.js';
describe('extractWords', () => {
it('lowercase + >= 4 Zeichen', () => {
expect(extractWords('Kaffee und ich')).toEqual(['kaffee']);
});
it('Satzzeichen werden entfernt', () => {
expect(extractWords('Kaffee, Milch! Zucker.')).toEqual(['kaffee', 'milch', 'zucker']);
});
it('Unicode bleibt erhalten', () => {
expect(extractWords('Größere Übung mit Äpfeln')).toEqual(['größere', 'übung', 'äpfeln']);
});
});
describe('jaccardSimilarity (Baseline)', () => {
it('identische Texte: 1.0', () => {
expect(jaccardSimilarity('Kaffee und Kuchen', 'Kaffee und Kuchen')).toBe(1.0);
});
it('verschiedene Texte: 0.0', () => {
expect(jaccardSimilarity('Kaffee trinken', 'Auto fahren')).toBe(0.0);
});
it('Teilweise Überlappung: zwischen 0 und 1', () => {
const sim = jaccardSimilarity('Kaffee am Morgen mit Milch', 'Kaffee am Abend mit Zucker');
expect(sim).toBeGreaterThan(0);
expect(sim).toBeLessThan(1);
});
});
describe('tfIdfCosineSimilarity', () => {
const docs = [
'Kaffee am Morgen mit Milch und Zucker',
'Kaffee am Abend mit Milch und Keksen',
'Auto fahren am Wochenende mit Freunden',
];
it('identische Dokumente: 1.0', () => {
expect(tfIdfCosineSimilarity(docs, docs[0], docs[0])).toBe(1.0);
});
it('Thematisch aehnliche Dokumente (Kaffee) > thematisch ungleiche (Kaffee vs Auto)', () => {
const similar = tfIdfCosineSimilarity(docs, docs[0], docs[1]);
const different = tfIdfCosineSimilarity(docs, docs[0], docs[2]);
expect(similar).toBeGreaterThan(different);
});
it('0.0 wenn eines der Dokumente nicht im Korpus', () => {
expect(tfIdfCosineSimilarity(docs, 'nicht im Korpus', docs[0])).toBe(0);
expect(tfIdfCosineSimilarity(docs, docs[0], 'auch nicht')).toBe(0);
});
it('Cosinus ist symmetrisch: sim(a, b) === sim(b, a)', () => {
const ab = tfIdfCosineSimilarity(docs, docs[0], docs[1]);
const ba = tfIdfCosineSimilarity(docs, docs[1], docs[0]);
expect(ab).toBeCloseTo(ba, 10);
});
it('TF-IDF bevorzugt seltene Wörter (bessere Diskriminierung als Jaccard)', () => {
// Beide Dokumente haben 'Kaffee' und 'Milch' gemeinsam, aber unterschiedliche andere
const d1 = 'Kaffee Milch am Morgen';
const d2 = 'Kaffee Milch am Abend';
// TF-IDF sollte unterscheiden, weil 'Kaffee' und 'Milch' im Gesamtkorpus haeufiger sind
const tfidfSim = tfIdfCosineSimilarity([d1, d2, 'Eine ganz andere Notiz ueber Sport'], d1, d2);
// Beide positiv, aber konzeptuell aehnlich -> TF-IDF ist tendenziell niedriger
expect(tfidfSim).toBeGreaterThan(0);
expect(tfidfSim).toBeLessThanOrEqual(1);
});
});