using System.Net; using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using StellaOps.Policy; using StellaOps.Scanner.WebService.Contracts; namespace StellaOps.Scanner.WebService.Tests; public sealed class PolicyEndpointsTests { private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web); [Fact] public async Task PolicySchemaReturnsEmbeddedSchema() { using var factory = new ScannerApplicationFactory(); using var client = factory.CreateClient(); var response = await client.GetAsync("/api/v1/policy/schema"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("application/schema+json", response.Content.Headers.ContentType?.MediaType); var payload = await response.Content.ReadAsStringAsync(); Assert.Contains("\"$schema\"", payload); Assert.Contains("\"properties\"", payload); } [Fact] public async Task PolicyDiagnosticsReturnsRecommendations() { using var factory = new ScannerApplicationFactory(); using var client = factory.CreateClient(); var request = new PolicyDiagnosticsRequestDto { Policy = new PolicyPreviewPolicyDto { Content = "version: \"1.0\"\nrules: []\n", Format = "yaml", Actor = "tester", Description = "empty ruleset" } }; var response = await client.PostAsJsonAsync("/api/v1/policy/diagnostics", request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var diagnostics = await response.Content.ReadFromJsonAsync(SerializerOptions); Assert.NotNull(diagnostics); Assert.False(diagnostics!.Success); Assert.True(diagnostics.ErrorCount >= 0); Assert.NotEmpty(diagnostics.Recommendations); } [Fact] public async Task PolicyPreviewUsesProposedPolicy() { using var factory = new ScannerApplicationFactory(); using var client = factory.CreateClient(); const string policyYaml = """ version: "1.0" rules: - name: Block Critical severity: [Critical] action: block """; var request = new PolicyPreviewRequestDto { ImageDigest = "sha256:abc123", Findings = new[] { new PolicyPreviewFindingDto { Id = "finding-1", Severity = "Critical", Source = "NVD", Tags = new[] { "reachability:runtime" } } }, Policy = new PolicyPreviewPolicyDto { Content = policyYaml, Format = "yaml", Actor = "preview", Description = "test policy" } }; var response = await client.PostAsJsonAsync("/api/v1/policy/preview", request); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var preview = await response.Content.ReadFromJsonAsync(SerializerOptions); Assert.NotNull(preview); Assert.True(preview!.Success); Assert.Equal(1, preview.Changed); var diff = Assert.Single(preview.Diffs); Assert.Equal("finding-1", diff.Projected?.FindingId); Assert.Equal("Blocked", diff.Projected?.Status); Assert.Equal(PolicyScoringConfig.Default.Version, diff.Projected?.ConfigVersion); Assert.NotNull(diff.Projected?.Inputs); Assert.True(diff.Projected!.Inputs!.ContainsKey("severityWeight")); Assert.Equal("NVD", diff.Projected.SourceTrust); Assert.Equal("runtime", diff.Projected.Reachability); } }