package validators import ( "reflect" "testing" "gitea.maximumdirect.net/eric/audita/internal/core/schema" "gitea.maximumdirect.net/eric/audita/internal/framework/proposals" ) func TestExtractProtectedTermsStableDeduplicatedWithPlurals(t *testing.T) { glossary := &schema.Glossary{ Entries: []schema.GlossaryEntry{ {Name: "Jesters", Aliases: []string{"Jester", " "}, Plural: "Jesters", Category: "faction", Summary: "Faction"}, {Name: "Hrank", Aliases: []string{"hrank", "Hrank"}, Plural: "Hranks", Category: "pc", Summary: "Character"}, {Name: "Lyra", Aliases: []string{}, Plural: "", Category: "npc", Summary: "NPC"}, }, } got := ExtractProtectedTerms(glossary) want := []string{"Hrank", "Hranks", "Jester", "Jesters", "Jesterss", "Lyra", "Lyras"} if !reflect.DeepEqual(got, want) { t.Fatalf("unexpected protected terms\n got: %v\nwant: %v", got, want) } } func TestExtractProtectedTermsEmptyGlossary(t *testing.T) { if terms := ExtractProtectedTerms(&schema.Glossary{}); len(terms) != 0 { t.Fatalf("expected no terms, got %v", terms) } } func TestValidateProtectedTermsAppliesToNonGlossaryModule(t *testing.T) { req := Request{ ModuleKey: "grammar", Glossary: &schema.Glossary{ Entries: []schema.GlossaryEntry{{Name: "Jesters", Category: "faction", Summary: "Faction"}}, }, CandidateProposal: []proposals.EnrichedCorrectionProposal{ { CorrectionProposal: proposals.CorrectionProposal{ TargetSegmentID: 1, OriginalText: "Jesters", CorrectedText: "Gestures", Confidence: 0.9, }, ProposalMetadata: proposals.ProposalMetadata{ProposalIndex: 0}, }, }, } res, err := ValidateProtectedTerms(req, false) if err != nil { t.Fatalf("validator error: %v", err) } if len(res.Decisions) != 1 || res.Decisions[0].Approved { t.Fatalf("expected protected-term rejection, got %+v", res.Decisions) } } func TestValidateProtectedTermsGlossaryStageAllowsProtectedTermSwap(t *testing.T) { req := Request{ ModuleKey: "glossary", Glossary: &schema.Glossary{ Entries: []schema.GlossaryEntry{{Name: "Jesters", Category: "faction", Summary: "Faction"}}, }, CandidateProposal: []proposals.EnrichedCorrectionProposal{ { CorrectionProposal: proposals.CorrectionProposal{ TargetSegmentID: 1, OriginalText: "gestures", CorrectedText: "Jesters", Confidence: 0.9, }, ProposalMetadata: proposals.ProposalMetadata{ProposalIndex: 0}, }, }, } res, err := ValidateProtectedTerms(req, true) if err != nil { t.Fatalf("validator error: %v", err) } if len(res.Decisions) != 1 || !res.Decisions[0].Approved { t.Fatalf("expected approval for glossary-stage protected term correction, got %+v", res.Decisions) } }