using System.Text.Json.Nodes; using StellaOps.Notifier.Worker.Processing; using StellaOps.Notify.Models; using Xunit; namespace StellaOps.Notifier.Tests; public sealed class RuleEvaluatorTests { [Fact] public void Evaluate_MatchingPolicyViolation_ReturnsActions() { var rule = NotifyRule.Create( ruleId: "rule-critical", tenantId: "tenant-a", name: "Critical policy violation", match: NotifyRuleMatch.Create( eventKinds: new[] { "policy.violation" }, labels: new[] { "kev" }, minSeverity: "high", verdicts: new[] { "fail" }), actions: new[] { NotifyRuleAction.Create( actionId: "act-slack", channel: "chn-slack", throttle: TimeSpan.FromMinutes(10)) }); var payload = new JsonObject { ["verdict"] = "fail", ["severity"] = "critical", ["labels"] = new JsonArray("kev", "policy") }; var notifyEvent = NotifyEvent.Create( eventId: Guid.NewGuid(), kind: "policy.violation", tenant: "tenant-a", ts: DateTimeOffset.UtcNow, payload: payload, scope: NotifyEventScope.Create(repo: "registry.local/api", digest: "sha256:123"), actor: "policy-engine", version: "1", attributes: new[] { new KeyValuePair("severity", "critical"), new KeyValuePair("verdict", "fail"), new KeyValuePair("kev", "true") }); var evaluator = new DefaultNotifyRuleEvaluator(); var outcome = evaluator.Evaluate(rule, notifyEvent); Assert.True(outcome.IsMatch); Assert.Single(outcome.Actions); Assert.Equal("act-slack", outcome.Actions[0].ActionId); } }