105 lines
3.8 KiB
C#
105 lines
3.8 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Reflection;
|
|
using FluentAssertions;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using StellaOps.SbomService.Repositories;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.SbomService.Tests;
|
|
|
|
public class ProjectionEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
|
{
|
|
private readonly WebApplicationFactory<Program> _factory;
|
|
|
|
public ProjectionEndpointTests(WebApplicationFactory<Program> factory)
|
|
{
|
|
var contentRoot = ResolveContentRoot();
|
|
_factory = factory.WithWebHostBuilder(builder =>
|
|
{
|
|
var fixturePath = GetProjectionFixturePath();
|
|
if (!File.Exists(fixturePath))
|
|
{
|
|
throw new InvalidOperationException($"Projection fixture missing at {fixturePath}");
|
|
}
|
|
|
|
builder.ConfigureAppConfiguration((_, config) =>
|
|
{
|
|
config.AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["SbomService:ProjectionsPath"] = fixturePath
|
|
});
|
|
});
|
|
|
|
builder.ConfigureServices(services =>
|
|
{
|
|
// Avoid MongoDB dependency in tests; use seeded in-memory repo.
|
|
services.RemoveAll<IComponentLookupRepository>();
|
|
services.AddSingleton<IComponentLookupRepository, InMemoryComponentLookupRepository>();
|
|
});
|
|
|
|
builder.UseSetting(WebHostDefaults.ContentRootKey, contentRoot);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Projection_requires_tenant()
|
|
{
|
|
var client = _factory.CreateClient();
|
|
|
|
var response = await client.GetAsync("/sboms/snap-001/projection");
|
|
|
|
if (response.StatusCode != HttpStatusCode.BadRequest)
|
|
{
|
|
var body = await response.Content.ReadAsStringAsync();
|
|
throw new Xunit.Sdk.XunitException($"Expected 400 but got {(int)response.StatusCode}: {response.StatusCode}. Body: {body}");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Projection_returns_payload_and_hash()
|
|
{
|
|
var client = _factory.CreateClient();
|
|
|
|
var response = await client.GetAsync("/sboms/snap-001/projection?tenant=tenant-a");
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
var json = await response.Content.ReadFromJsonAsync<ProjectionResponse>();
|
|
json.Should().NotBeNull();
|
|
json!.snapshotId.Should().Be("snap-001");
|
|
json.tenantId.Should().Be("tenant-a");
|
|
json.hash.Should().NotBeNullOrEmpty();
|
|
json.projection.GetProperty("purl").GetString().Should().Be("pkg:npm/lodash@4.17.21");
|
|
}
|
|
|
|
private sealed record ProjectionResponse(string snapshotId, string tenantId, string schemaVersion, string hash, System.Text.Json.JsonElement projection);
|
|
|
|
private static string GetProjectionFixturePath()
|
|
{
|
|
// Resolve docs/modules/sbomservice/fixtures/lnm-v1/projections.json relative to test bin directory.
|
|
var baseDir = ResolveContentRoot();
|
|
return Path.Combine(baseDir, "docs", "modules", "sbomservice", "fixtures", "lnm-v1", "projections.json");
|
|
}
|
|
|
|
private static string ResolveContentRoot()
|
|
{
|
|
// Walk up from bin folder to repo root (containing docs/).
|
|
var dir = AppContext.BaseDirectory;
|
|
for (var i = 0; i < 6; i++)
|
|
{
|
|
var candidate = Path.GetFullPath(Path.Combine(dir, ".."));
|
|
if (Directory.Exists(Path.Combine(candidate, "docs")) &&
|
|
Directory.Exists(Path.Combine(candidate, "src")))
|
|
{
|
|
return candidate;
|
|
}
|
|
dir = candidate;
|
|
}
|
|
return AppContext.BaseDirectory;
|
|
}
|
|
}
|