namespace ZB.MOM.WW.Audit.Tests; public class TruncatingAuditRedactorTests { private static AuditEvent Evt(string? details, string? target = null) => new() { EventId = Guid.NewGuid(), OccurredAtUtc = DateTimeOffset.UtcNow, Actor = "a", Action = "x", Outcome = AuditOutcome.Success, DetailsJson = details, Target = target, }; [Fact] public void Short_values_pass_through_unchanged() { var r = new TruncatingAuditRedactor(new() { MaxDetailsJsonLength = 100 }); var evt = Evt("small"); Assert.Equal("small", r.Apply(evt).DetailsJson); } [Fact] public void Oversized_details_are_truncated_with_marker() { var opts = new TruncatingAuditRedactorOptions { MaxDetailsJsonLength = 10, TruncationMarker = "~" }; var r = new TruncatingAuditRedactor(opts); var result = r.Apply(Evt(new string('x', 50))); Assert.Equal(10, result.DetailsJson!.Length); Assert.EndsWith("~", result.DetailsJson); } [Fact] public void Oversized_target_is_truncated() { var r = new TruncatingAuditRedactor(new() { MaxTargetLength = 5, TruncationMarker = "" }); var result = r.Apply(Evt(null, target: "abcdefghij")); Assert.Equal(5, result.Target!.Length); } [Fact] public void Null_fields_are_left_null() { var r = new TruncatingAuditRedactor(); var result = r.Apply(Evt(null)); Assert.Null(result.DetailsJson); Assert.Null(result.Target); } [Fact] public void Marker_longer_than_max_clips_the_marker_itself() { // Misconfiguration: marker longer than the cap. Must not throw; clips to the first max chars. var opts = new TruncatingAuditRedactorOptions { MaxDetailsJsonLength = 3, TruncationMarker = "…[truncated]" }; var r = new TruncatingAuditRedactor(opts); var result = r.Apply(Evt(new string('x', 20))); Assert.Equal(3, result.DetailsJson!.Length); } }