feat(auditlog): IAuditPayloadFilter contract (#23 M5)

This commit is contained in:
Joseph Doherty
2026-05-20 16:59:10 -04:00
parent e7b40c1c50
commit 25cdf857c9
2 changed files with 89 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
using System.Linq;
using System.Reflection;
using ScadaLink.AuditLog.Payload;
using ScadaLink.Commons.Entities.Audit;
namespace ScadaLink.AuditLog.Tests.Payload;
/// <summary>
/// Bundle A (M5-T1) contract test for <see cref="IAuditPayloadFilter"/>. The
/// interface is the seam between event construction and writer persistence;
/// later bundles register the production implementation as a singleton and
/// invoke it from the site/central writer paths. We pin the surface area here
/// via reflection so accidental signature drift breaks the build before the
/// downstream wiring goes red.
/// </summary>
public class PayloadFilterContractTests
{
[Fact]
public void Interface_Exists_InPayloadNamespace()
{
var type = typeof(IAuditPayloadFilter);
Assert.True(type.IsInterface, "IAuditPayloadFilter must be an interface");
Assert.Equal("ScadaLink.AuditLog.Payload", type.Namespace);
}
[Fact]
public void Apply_Method_HasDocumentedSignature()
{
var type = typeof(IAuditPayloadFilter);
var method = type.GetMethod(
"Apply",
BindingFlags.Instance | BindingFlags.Public,
binder: null,
types: new[] { typeof(AuditEvent) },
modifiers: null);
Assert.NotNull(method);
Assert.Equal(typeof(AuditEvent), method!.ReturnType);
var parameters = method.GetParameters();
Assert.Single(parameters);
Assert.Equal("rawEvent", parameters[0].Name);
Assert.Equal(typeof(AuditEvent), parameters[0].ParameterType);
}
[Fact]
public void Interface_DeclaresExactlyOneMethod()
{
var type = typeof(IAuditPayloadFilter);
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.Where(m => !m.IsSpecialName)
.ToArray();
Assert.Single(methods);
Assert.Equal("Apply", methods[0].Name);
}
}