using System.Text.Json; using Xunit; namespace StellaOps.Notifier.Tests; public sealed class AttestationTemplateCoverageTests { private static readonly string RepoRoot = LocateRepoRoot(); [Fact] public void Attestation_templates_cover_required_channels() { var directory = Path.Combine(RepoRoot, "offline", "notifier", "templates", "attestation"); Assert.True(Directory.Exists(directory), $"Expected template directory at {directory}"); var templates = Directory .GetFiles(directory, "*.template.json") .Select(path => new { Path = path, Document = JsonDocument.Parse(File.ReadAllText(path)).RootElement }) .ToList(); var required = new Dictionary { ["tmpl-attest-verify-fail"] = new[] { "slack", "email", "webhook" }, ["tmpl-attest-expiry-warning"] = new[] { "email", "slack" }, ["tmpl-attest-key-rotation"] = new[] { "email", "webhook" }, ["tmpl-attest-transparency-anomaly"] = new[] { "slack", "webhook" } }; foreach (var pair in required) { var matches = templates.Where(t => t.Document.GetProperty("key").GetString() == pair.Key); var channels = matches .Select(t => t.Document.GetProperty("channelType").GetString() ?? string.Empty) .ToHashSet(StringComparer.OrdinalIgnoreCase); var missing = pair.Value.Where(requiredChannel => !channels.Contains(requiredChannel)).ToArray(); Assert.True(missing.Length == 0, $"{pair.Key} missing channels: {string.Join(", ", missing)}"); } } [Fact] public void Attestation_templates_include_schema_and_locale_metadata() { var directory = Path.Combine(RepoRoot, "offline", "notifier", "templates", "attestation"); Assert.True(Directory.Exists(directory), $"Expected template directory at {directory}"); foreach (var path in Directory.GetFiles(directory, "*.template.json")) { var document = JsonDocument.Parse(File.ReadAllText(path)).RootElement; Assert.True(document.TryGetProperty("schemaVersion", out var schemaVersion) && !string.IsNullOrWhiteSpace(schemaVersion.GetString()), $"schemaVersion missing for {Path.GetFileName(path)}"); Assert.True(document.TryGetProperty("locale", out var locale) && !string.IsNullOrWhiteSpace(locale.GetString()), $"locale missing for {Path.GetFileName(path)}"); Assert.True(document.TryGetProperty("key", out var key) && !string.IsNullOrWhiteSpace(key.GetString()), $"key missing for {Path.GetFileName(path)}"); } } private static string LocateRepoRoot() { var directory = AppContext.BaseDirectory; while (directory != null) { var candidate = Path.Combine(directory, "offline", "notifier", "templates", "attestation"); if (Directory.Exists(candidate)) { return directory; } directory = Directory.GetParent(directory)?.FullName; } throw new InvalidOperationException("Unable to locate repository root containing offline/notifier/templates/attestation."); } }