using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Configuration;
using RackPeek.Domain.Api;
using RackPeek.Domain.Discovery;
using RackPeek.Web;
namespace Tests.Discovery;
///
/// A real RackPeek server backed by a temporary config file, driven through the
/// same the CLI uses. These are the end-to-end
/// tests: discovery YAML goes over HTTP into the inventory API and the assertions
/// are made against what actually lands on disk.
///
public sealed class DiscoveryApiFixture : IDisposable {
private const string _apiKey = "discovery-test-key";
private readonly WebApplicationFactory _factory;
private readonly string _tempDir;
///
/// Contents to seed config.yaml with before the server first reads it — the way
/// to test how the server behaves against a file it did not write itself.
///
public DiscoveryApiFixture(string? initialConfig = null) {
_tempDir = Path.Combine(Path.GetTempPath(), "rackpeek-discovery-tests", Guid.NewGuid().ToString());
Directory.CreateDirectory(_tempDir);
if (initialConfig != null)
File.WriteAllText(Path.Combine(_tempDir, "config.yaml"), initialConfig);
_factory = new WebApplicationFactory()
.WithWebHostBuilder(builder => {
builder.UseSetting("RPK_YAML_DIR", _tempDir);
builder.ConfigureAppConfiguration((_, config) =>
config.AddInMemoryCollection(new Dictionary {
["RPK_YAML_DIR"] = _tempDir,
["RPK_API_KEY"] = _apiKey
}));
});
}
public string StoredYaml => File.ReadAllText(Path.Combine(_tempDir, "config.yaml"));
public void Dispose() {
try {
_factory.Dispose();
if (Directory.Exists(_tempDir))
Directory.Delete(_tempDir, true);
}
catch {
// Cleanup only; a leftover temp directory must never fail a test run.
}
}
public async Task PublishAsync(string yaml, bool dryRun = false) {
HttpClient client = _factory.CreateClient();
using var publisher = new DiscoveryPublisher(
client.BaseAddress!.ToString(),
_apiKey,
client);
return await publisher.PublishAsync(yaml, dryRun);
}
}