import { IntentClassifier } from '../intent-classifier' describe('IntentClassifier', () => { const classifier = new IntentClassifier() describe('classify - Draft mode', () => { it.each([ ['Erstelle ein VVT fuer unseren Hauptprozess', 'draft'], ['Generiere eine TOM-Dokumentation', 'draft'], ['Schreibe eine Datenschutzerklaerung', 'draft'], ['Verfasse einen Entwurf fuer das Loeschkonzept', 'draft'], ['Create a DSFA document', 'draft'], ['Draft a privacy policy for us', 'draft'], ['Neues VVT anlegen', 'draft'], ])('"%s" should classify as %s', (input, expectedMode) => { const result = classifier.classify(input) expect(result.mode).toBe(expectedMode) expect(result.confidence).toBeGreaterThan(0.7) }) }) describe('classify - Validate mode', () => { it.each([ ['Pruefe die Konsistenz meiner Dokumente', 'validate'], ['Ist mein VVT korrekt?', 'validate'], ['Validiere die TOM gegen das VVT', 'validate'], ['Check die Vollstaendigkeit', 'validate'], ['Stimmt das mit der DSFA ueberein?', 'validate'], ['Cross-Check VVT und TOM', 'validate'], ])('"%s" should classify as %s', (input, expectedMode) => { const result = classifier.classify(input) expect(result.mode).toBe(expectedMode) expect(result.confidence).toBeGreaterThan(0.7) }) }) describe('classify - Ask mode', () => { it.each([ ['Was fehlt noch in meinem Profil?', 'ask'], ['Zeige mir die Luecken', 'ask'], ['Welche Dokumente fehlen noch?', 'ask'], ['Was ist der naechste Schritt?', 'ask'], ['Welche Informationen brauche ich noch?', 'ask'], ])('"%s" should classify as %s', (input, expectedMode) => { const result = classifier.classify(input) expect(result.mode).toBe(expectedMode) expect(result.confidence).toBeGreaterThan(0.6) }) }) describe('classify - Explain mode (fallback)', () => { it.each([ ['Was ist DSGVO?', 'explain'], ['Erklaere mir Art. 30', 'explain'], ['Hallo', 'explain'], ['Danke fuer die Hilfe', 'explain'], ])('"%s" should classify as %s (fallback)', (input, expectedMode) => { const result = classifier.classify(input) expect(result.mode).toBe(expectedMode) }) }) describe('classify - confidence thresholds', () => { it('should have high confidence for clear draft intents', () => { const result = classifier.classify('Erstelle ein neues VVT') expect(result.confidence).toBeGreaterThanOrEqual(0.85) }) it('should have lower confidence for ambiguous inputs', () => { const result = classifier.classify('Hallo') expect(result.confidence).toBeLessThan(0.6) }) it('should boost confidence with document type detection', () => { const withDoc = classifier.classify('Erstelle VVT') const withoutDoc = classifier.classify('Erstelle etwas') expect(withDoc.confidence).toBeGreaterThanOrEqual(withoutDoc.confidence) }) it('should boost confidence with multiple pattern matches', () => { const single = classifier.classify('Erstelle Dokument') const multi = classifier.classify('Erstelle und generiere ein neues Dokument') expect(multi.confidence).toBeGreaterThanOrEqual(single.confidence) }) }) describe('detectDocumentType', () => { it.each([ ['VVT erstellen', 'vvt'], ['Verarbeitungsverzeichnis', 'vvt'], ['Art. 30 Dokumentation', 'vvt'], ['TOM definieren', 'tom'], ['technisch organisatorische Massnahmen', 'tom'], ['Art. 32 Massnahmen', 'tom'], ['DSFA durchfuehren', 'dsfa'], ['Datenschutz-Folgenabschaetzung', 'dsfa'], ['Art. 35 Pruefung', 'dsfa'], ['DPIA erstellen', 'dsfa'], ['Datenschutzerklaerung', 'dsi'], ['Privacy Policy', 'dsi'], ['Art. 13 Information', 'dsi'], ['Loeschfristen definieren', 'lf'], ['Loeschkonzept erstellen', 'lf'], ['Retention Policy', 'lf'], ['Auftragsverarbeitung', 'av_vertrag'], ['AVV erstellen', 'av_vertrag'], ['Art. 28 Vertrag', 'av_vertrag'], ['Einwilligung einholen', 'einwilligung'], ['Consent Management', 'einwilligung'], ['Cookie Banner', 'einwilligung'], ])('"%s" should detect document type %s', (input, expectedType) => { const result = classifier.detectDocumentType(input) expect(result).toBe(expectedType) }) it('should return undefined for unrecognized types', () => { expect(classifier.detectDocumentType('Hallo Welt')).toBeUndefined() expect(classifier.detectDocumentType('Was kostet das?')).toBeUndefined() }) }) describe('classify - Umlaut handling', () => { it('should handle German umlauts correctly', () => { // With actual umlauts (ä, ö, ü) const result1 = classifier.classify('Prüfe die Vollständigkeit') expect(result1.mode).toBe('validate') // With ae/oe/ue substitution const result2 = classifier.classify('Pruefe die Vollstaendigkeit') expect(result2.mode).toBe('validate') }) it('should handle ß correctly', () => { const result = classifier.classify('Schließe Lücken') // Should still detect via normalized patterns expect(result).toBeDefined() }) }) describe('classify - combined mode + document type', () => { it('should detect both mode and document type', () => { const result = classifier.classify('Erstelle ein VVT fuer unsere Firma') expect(result.mode).toBe('draft') expect(result.detectedDocumentType).toBe('vvt') }) it('should detect validate + document type', () => { const result = classifier.classify('Pruefe mein TOM auf Konsistenz') expect(result.mode).toBe('validate') expect(result.detectedDocumentType).toBe('tom') }) }) })