Files
audita/internal/framework/validators/protected_terms_test.go
Eric Rakestraw 2d41748006
Some checks failed
ci/woodpecker/tag/release Pipeline failed
Use the Go v3 module path for Audita
2026-10-11 01:40:38 +00:00

116 lines
4.5 KiB
Go

package validators
import (
"reflect"
"testing"
"gitea.maximumdirect.net/eric/audita/v3/internal/core/schema"
"gitea.maximumdirect.net/eric/audita/v3/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},
},
{
CorrectionProposal: proposals.CorrectionProposal{TargetSegmentID: 1, OriginalText: "Jesters", CorrectedText: "", Confidence: 0.9},
ProposalMetadata: proposals.ProposalMetadata{ProposalIndex: 1},
},
},
}
res, err := ValidateProtectedTerms(req, false)
if err != nil {
t.Fatalf("validator error: %v", err)
}
if len(res.Decisions) != 2 || res.Decisions[0].Approved || res.Decisions[1].Approved || res.Decisions[1].ReasonCode != ReasonProtectedGlossaryTerm {
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)
}
}
func TestProtectedNameRepetitionRequiresSurvivingIdentityAndSpokenWordScope(t *testing.T) {
for _, tc := range []struct {
name, module, before, original, replacement string
allowed bool
}{
{"whole repetition", "spoken_word", "Jesters Jesters arrived", "Jesters Jesters", "Jesters", true},
{"span deletion", "spoken_word", "Jesters, Jesters arrived", "Jesters, ", "", true},
{"last reference", "spoken_word", "Jesters arrived", "Jesters ", "", false},
{"different identity", "spoken_word", "Jesters Jesters arrived", "Jesters Jesters", "Lyra", false},
{"spelling degraded", "spoken_word", "Jesters Jesters arrived", "Jesters Jesters", "jestERS", false},
{"grammar unchanged", "grammar", "Jesters Jesters arrived", "Jesters Jesters", "Jesters", false},
} {
t.Run(tc.name, func(t *testing.T) {
req := Request{ModuleKey: tc.module, ReplacementPolicy: proposals.ReplacementPolicyRequireUnique,
WorkingTranscript: &schema.Transcript{Segments: []schema.Segment{{ID: 1, Text: tc.before}}},
Glossary: &schema.Glossary{Entries: []schema.GlossaryEntry{{Name: "Jesters"}, {Name: "Lyra"}}},
CandidateProposal: []proposals.EnrichedCorrectionProposal{{CorrectionProposal: proposals.CorrectionProposal{TargetSegmentID: 1, OriginalText: tc.original, CorrectedText: tc.replacement, Confidence: 1}}},
}
result, err := ValidateProtectedTerms(req, false)
if err != nil || len(result.Decisions) != 1 || result.Decisions[0].Approved != tc.allowed {
t.Fatalf("result=%+v err=%v", result, err)
}
})
}
}