package proposals import ( "reflect" "testing" "gitea.maximumdirect.net/eric/audita/internal/core/schema" ) func TestPreviewProposalForSegmentRequireUniqueSuccess(t *testing.T) { segment := &schema.Segment{ID: 7, Text: "The gestures are odd."} proposal := CorrectionProposal{ TargetSegmentID: 7, OriginalText: "gestures", CorrectedText: "Jesters", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if !result.Applicable { t.Fatalf("expected applicable preview, got skip reason %q", result.SkipReason) } if result.CorrectedSegmentText != "The Jesters are odd." { t.Fatalf("unexpected corrected text: %q", result.CorrectedSegmentText) } if result.ReplacementCount != 1 { t.Fatalf("expected 1 replacement, got %d", result.ReplacementCount) } } func TestPreviewProposalForSegmentRequireUniqueMissingOriginalText(t *testing.T) { segment := &schema.Segment{ID: 7, Text: "The jesters are odd."} proposal := CorrectionProposal{ TargetSegmentID: 7, OriginalText: "gestures", CorrectedText: "Jesters", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if result.Applicable { t.Fatal("expected non-applicable preview") } if result.SkipReason != SkipReasonMissingOriginalText { t.Fatalf("expected skip reason %q, got %q", SkipReasonMissingOriginalText, result.SkipReason) } } func TestPreviewProposalForSegmentRequireUniqueAmbiguousOriginalText(t *testing.T) { segment := &schema.Segment{ID: 7, Text: "rank and rank"} proposal := CorrectionProposal{ TargetSegmentID: 7, OriginalText: "rank", CorrectedText: "Hrank", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if result.Applicable { t.Fatal("expected non-applicable preview") } if result.SkipReason != SkipReasonAmbiguousOriginal { t.Fatalf("expected skip reason %q, got %q", SkipReasonAmbiguousOriginal, result.SkipReason) } } func TestPreviewProposalForSegmentReplaceAllSuccessMultipleOccurrences(t *testing.T) { segment := &schema.Segment{ID: 8, Text: "uh uh uh"} proposal := CorrectionProposal{ TargetSegmentID: 8, OriginalText: "uh", CorrectedText: "um", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyReplaceAll) if !result.Applicable { t.Fatalf("expected applicable preview, got skip reason %q", result.SkipReason) } if result.CorrectedSegmentText != "um um um" { t.Fatalf("unexpected corrected text: %q", result.CorrectedSegmentText) } if result.ReplacementCount != 3 { t.Fatalf("expected 3 replacements, got %d", result.ReplacementCount) } } func TestPreviewProposalForSegmentReplaceAllMissingOriginalText(t *testing.T) { segment := &schema.Segment{ID: 8, Text: "um um um"} proposal := CorrectionProposal{ TargetSegmentID: 8, OriginalText: "uh", CorrectedText: "um", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyReplaceAll) if result.Applicable { t.Fatal("expected non-applicable preview") } if result.SkipReason != SkipReasonMissingOriginalText { t.Fatalf("expected skip reason %q, got %q", SkipReasonMissingOriginalText, result.SkipReason) } } func TestPreviewProposalForSegmentNoEffectReplacement(t *testing.T) { segment := &schema.Segment{ID: 8, Text: "hello there"} proposal := CorrectionProposal{ TargetSegmentID: 8, OriginalText: "hello", CorrectedText: "hello", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if result.Applicable { t.Fatal("expected non-applicable preview") } if result.SkipReason != SkipReasonNoEffect { t.Fatalf("expected skip reason %q, got %q", SkipReasonNoEffect, result.SkipReason) } } func TestPreviewProposalForSegmentAllowsEmptyCorrectedTextWhenSegmentRemainsNonEmpty(t *testing.T) { segment := &schema.Segment{ID: 8, Text: "uh hello"} proposal := CorrectionProposal{ TargetSegmentID: 8, OriginalText: "uh ", CorrectedText: "", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if !result.Applicable { t.Fatalf("expected applicable preview, got skip reason %q", result.SkipReason) } if result.CorrectedSegmentText != "hello" { t.Fatalf("unexpected corrected text: %q", result.CorrectedSegmentText) } } func TestPreviewProposalForSegmentRejectsEmptyResultingSegment(t *testing.T) { segment := &schema.Segment{ID: 8, Text: "uh"} proposal := CorrectionProposal{ TargetSegmentID: 8, OriginalText: "uh", CorrectedText: "", Confidence: 0.9, } result := PreviewProposalForSegment(segment, proposal, ReplacementPolicyRequireUnique) if result.Applicable { t.Fatal("expected non-applicable preview") } if result.SkipReason != SkipReasonEmptyResultingText { t.Fatalf("expected skip reason %q, got %q", SkipReasonEmptyResultingText, result.SkipReason) } } func TestPreviewProposalForSegmentPreservesInputSegment(t *testing.T) { segment := &schema.Segment{ID: 9, Speaker: "A", Start: 1.0, End: 2.0, Text: "rank rank"} original := *segment proposal := CorrectionProposal{ TargetSegmentID: 9, OriginalText: "rank", CorrectedText: "Hrank", Confidence: 0.9, } _ = PreviewProposalForSegment(segment, proposal, ReplacementPolicyReplaceAll) if !reflect.DeepEqual(*segment, original) { t.Fatalf("segment mutated: before=%+v after=%+v", original, *segment) } } func TestPreviewProposalForSegmentLiteralMatchingCaseSensitiveAndPunctuation(t *testing.T) { segment := &schema.Segment{ID: 10, Text: "Hello, world."} punctuationProposal := CorrectionProposal{ TargetSegmentID: 10, OriginalText: "world.", CorrectedText: "earth.", Confidence: 0.9, } punctuationResult := PreviewProposalForSegment(segment, punctuationProposal, ReplacementPolicyRequireUnique) if !punctuationResult.Applicable { t.Fatalf("expected punctuation proposal applicable, got skip reason %q", punctuationResult.SkipReason) } if punctuationResult.CorrectedSegmentText != "Hello, earth." { t.Fatalf("unexpected corrected text: %q", punctuationResult.CorrectedSegmentText) } caseMismatchProposal := CorrectionProposal{ TargetSegmentID: 10, OriginalText: "hello", CorrectedText: "Hi", Confidence: 0.9, } caseMismatchResult := PreviewProposalForSegment(segment, caseMismatchProposal, ReplacementPolicyRequireUnique) if caseMismatchResult.Applicable { t.Fatal("expected case-mismatch proposal to be non-applicable") } if caseMismatchResult.SkipReason != SkipReasonMissingOriginalText { t.Fatalf("expected skip reason %q, got %q", SkipReasonMissingOriginalText, caseMismatchResult.SkipReason) } }