using StellaOps.Signals.Contracts; using Xunit; namespace StellaOps.Signals.Contracts.Tests; /// /// Tests for SignalEnvelope model. /// public sealed class SignalEnvelopeTests { [Fact] public void SignalEnvelope_RequiredProperties_MustBeSet() { var envelope = new SignalEnvelope { SignalKey = "pkg:npm/lodash@4.17.21:reachability", SignalType = SignalType.Reachability, Value = new { reachable = true, confidence = 0.95 }, ComputedAt = DateTimeOffset.UtcNow, SourceService = "reachability-analyzer" }; Assert.Equal("pkg:npm/lodash@4.17.21:reachability", envelope.SignalKey); Assert.Equal(SignalType.Reachability, envelope.SignalType); Assert.Equal("reachability-analyzer", envelope.SourceService); } [Theory] [InlineData(SignalType.Reachability)] [InlineData(SignalType.Entropy)] [InlineData(SignalType.Exploitability)] [InlineData(SignalType.Trust)] [InlineData(SignalType.UnknownSymbol)] [InlineData(SignalType.Custom)] public void SignalEnvelope_SignalType_AllValues_AreValid(SignalType type) { var envelope = new SignalEnvelope { SignalKey = $"test:{type.ToString().ToLowerInvariant()}", SignalType = type, Value = new { test = true }, ComputedAt = DateTimeOffset.UtcNow, SourceService = "test-service" }; Assert.Equal(type, envelope.SignalType); } [Fact] public void SignalEnvelope_DefaultSchemaVersion_IsOne() { var envelope = new SignalEnvelope { SignalKey = "test:schema", SignalType = SignalType.Custom, Value = new { }, ComputedAt = DateTimeOffset.UtcNow, SourceService = "test" }; Assert.Equal("1.0", envelope.SchemaVersion); } [Fact] public void SignalEnvelope_OptionalProperties_AreNullByDefault() { var envelope = new SignalEnvelope { SignalKey = "test:optional", SignalType = SignalType.Reachability, Value = new { }, ComputedAt = DateTimeOffset.UtcNow, SourceService = "test" }; Assert.Null(envelope.TenantId); Assert.Null(envelope.CorrelationId); Assert.Null(envelope.ProvenanceDigest); } [Fact] public void SignalEnvelope_WithAllOptionalProperties_ContainsValues() { var envelope = new SignalEnvelope { SignalKey = "pkg:pypi/django@4.2.0:trust", SignalType = SignalType.Trust, Value = new { score = 0.85 }, ComputedAt = DateTimeOffset.UtcNow, SourceService = "trust-engine", TenantId = "tenant-001", CorrelationId = "corr-abc123", ProvenanceDigest = "sha256:xyz789", SchemaVersion = "2.0" }; Assert.Equal("tenant-001", envelope.TenantId); Assert.Equal("corr-abc123", envelope.CorrelationId); Assert.Equal("sha256:xyz789", envelope.ProvenanceDigest); Assert.Equal("2.0", envelope.SchemaVersion); } [Fact] public void SignalEnvelope_Value_CanBeAnyObject() { var reachabilityValue = new { reachable = true, paths = new[] { "main->helper->vulnerable" }, confidence = 0.92 }; var envelope = new SignalEnvelope { SignalKey = "test:value", SignalType = SignalType.Reachability, Value = reachabilityValue, ComputedAt = DateTimeOffset.UtcNow, SourceService = "analyzer" }; Assert.NotNull(envelope.Value); } [Fact] public void SignalEnvelope_RecordEquality_WorksCorrectly() { var computedAt = DateTimeOffset.UtcNow; var value = new { test = 123 }; var envelope1 = new SignalEnvelope { SignalKey = "test:eq", SignalType = SignalType.Entropy, Value = value, ComputedAt = computedAt, SourceService = "test" }; var envelope2 = new SignalEnvelope { SignalKey = "test:eq", SignalType = SignalType.Entropy, Value = value, ComputedAt = computedAt, SourceService = "test" }; Assert.Equal(envelope1, envelope2); } } /// /// Tests for SignalType enum. /// public sealed class SignalTypeTests { [Fact] public void SignalType_AllDefinedValues_AreCounted() { var values = Enum.GetValues(); // Ensure we have expected signal types Assert.Equal(6, values.Length); } [Fact] public void SignalType_Reachability_HasValue() { Assert.Equal(0, (int)SignalType.Reachability); } [Fact] public void SignalType_Custom_IsLast() { var values = Enum.GetValues(); var last = values.Max(); Assert.Equal(SignalType.Custom, last); } }