All checks were successful
release-tag / release-image (push) Successful in 2m22s
82 lines
3.6 KiB
Go
82 lines
3.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/local/glpi-neural-brain/internal/config"
|
|
"github.com/local/glpi-neural-brain/internal/model"
|
|
)
|
|
|
|
func TestArticleContentToDraftFormatsConceptWithoutInventedSteps(t *testing.T) {
|
|
content := model.KnowledgeArticleContent{
|
|
Title: "Btrfs-Snapshots und ZFS-History in einer Timeline einordnen",
|
|
ProblemDescription: "Bei der forensischen Timeline-Analyse müssen Dateisystemartefakte mit unterschiedlicher Semantik korrekt eingeordnet werden.",
|
|
Scope: "Gilt für die vergleichende Analyse von Btrfs- und ZFS-Artefakten.",
|
|
KeyPoints: []string{
|
|
"Ein Snapshot beschreibt einen referenzierten Dateisystemzustand und nicht automatisch eine vollständige Ereignishistorie.",
|
|
"Zeitstempel müssen mit Artefakttyp, Erzeugungsmechanismus und Datenquelle dokumentiert werden.",
|
|
},
|
|
DecisionCriteria: []string{
|
|
"Für eine Ereignistimeline sind nur Zeitangaben geeignet, deren Herkunft und Semantik nachvollziehbar sind.",
|
|
"Snapshot-Zeitpunkte dürfen nicht ohne zusätzliche Belege als Zeitpunkt jeder enthaltenen Dateiänderung interpretiert werden.",
|
|
},
|
|
}
|
|
|
|
draft := articleContentToDraft(content, []string{"S1", "S2"}, "concept")
|
|
if strings.TrimSpace(draft.Answer) == "" {
|
|
t.Fatal("concept article must have a useful answer without artificial solution steps")
|
|
}
|
|
if !strings.Contains(draft.Answer, "## Kernaussagen") || !strings.Contains(draft.Answer, "## Einordnung und Abgrenzung") {
|
|
t.Fatalf("concept sections missing: %s", draft.Answer)
|
|
}
|
|
if strings.Contains(draft.Answer, "1. ") {
|
|
t.Fatalf("concept article contains invented numbered steps: %s", draft.Answer)
|
|
}
|
|
}
|
|
|
|
func TestArticleContentToDraftKeepsOperationalStepsNumbered(t *testing.T) {
|
|
content := model.KnowledgeArticleContent{
|
|
Title: "Audit Logging prüfen",
|
|
ProblemDescription: "Audit-Ereignisse fehlen in der zentralen Protokollierung.",
|
|
SolutionSteps: []string{
|
|
"Aktivieren Sie die zentrale Audit-Protokollierung.",
|
|
"Erzeugen Sie ein dokumentiertes Testereignis.",
|
|
},
|
|
}
|
|
|
|
draft := articleContentToDraft(content, []string{"S1"}, "troubleshooting")
|
|
if !strings.Contains(draft.Answer, "1. Aktivieren") || !strings.Contains(draft.Answer, "2. Erzeugen") {
|
|
t.Fatalf("operational steps were not numbered: %s", draft.Answer)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeArticleContentCleansConceptFields(t *testing.T) {
|
|
content := normalizeArticleContent(model.KnowledgeArticleContent{
|
|
KeyPoints: []string{" 1. Erster Punkt ", "Erster Punkt"},
|
|
DecisionCriteria: []string{" - Kriterium A ", ""},
|
|
})
|
|
if len(content.KeyPoints) != 1 || content.KeyPoints[0] != "Erster Punkt" {
|
|
t.Fatalf("unexpected key points: %#v", content.KeyPoints)
|
|
}
|
|
if len(content.DecisionCriteria) != 1 || content.DecisionCriteria[0] != "Kriterium A" {
|
|
t.Fatalf("unexpected decision criteria: %#v", content.DecisionCriteria)
|
|
}
|
|
}
|
|
|
|
func TestArticleQualityContextCarriesArticleType(t *testing.T) {
|
|
e := &Engine{}
|
|
contextValue := e.articleQualityContext(model.KnowledgeArticleDraft{Title: "Vergleich", Text: "Beschreibung", Answer: "Kernaussagen"}, "concept", nil, nil)
|
|
if !strings.Contains(contextValue, "ARTIKELTYP: concept") {
|
|
t.Fatalf("article type missing from quality context: %s", contextValue)
|
|
}
|
|
}
|
|
|
|
func TestArticleDraftContextCarriesArticleType(t *testing.T) {
|
|
e := &Engine{Cfg: config.Config{MaxContextChars: 4000}}
|
|
contextValue := e.articleDraftContext(nil, model.ArticlePlanDecision{ArticleType: "decision_guide", Action: "create"}, model.KnowledgeBrief{}, nil)
|
|
if !strings.Contains(contextValue, "ARTIKELTYP: decision_guide") {
|
|
t.Fatalf("article type missing from draft context: %s", contextValue)
|
|
}
|
|
}
|