using ErsatzTV;
using ErsatzTV.Controllers.Api;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi;
using NSubstitute;
using NUnit.Framework;
namespace ErsatzTV.Tests.Support;
///
/// Builds the "v1" OpenAPI document in-process from the real
/// registrations, so contract tests validate the document the running app would actually serve —
/// including every registered document/operation/schema transformer — rather than a stale committed
/// wwwroot/openapi/v1.json that is regenerated out-of-band. Mirrors the DI-only bootstrap that
/// ApiControllerSecurityTests uses to inspect MvcOptions.
///
public static class GeneratedOpenApiDocument
{
public static async Task BuildV1Async()
{
var settings = new Dictionary
{
["provider"] = "sqlite",
["ConnectionStrings:Data"] = "Data Source=:memory:"
};
IConfiguration configuration = new ConfigurationBuilder().AddInMemoryCollection(settings).Build();
var environment = Substitute.For();
environment.ApplicationName.Returns("ErsatzTV");
environment.EnvironmentName.Returns("Development");
environment.ContentRootPath.Returns(TestContext.CurrentContext.TestDirectory);
environment.WebRootPath.Returns(TestContext.CurrentContext.TestDirectory);
environment.ContentRootFileProvider.Returns(new NullFileProvider());
environment.WebRootFileProvider.Returns(new NullFileProvider());
var services = new ServiceCollection();
// The host normally provides these; supply them so the OpenAPI document service and the
// API-key provider (an operation-transformer dependency) can be constructed.
services.AddSingleton(configuration);
services.AddLogging();
services.AddSingleton(environment);
services.AddSingleton(environment);
new Startup(configuration, environment).ConfigureServices(services);
// In the running app ErsatzTV is the entry assembly and its controllers are discovered
// automatically; under the test runner it is not, so register it as an application part.
ApplicationPartManager? partManager = services
.FirstOrDefault(d => d.ServiceType == typeof(ApplicationPartManager))?.ImplementationInstance
as ApplicationPartManager;
if (partManager is not null &&
!partManager.ApplicationParts.OfType()
.Any(p => p.Assembly == typeof(CollectionController).Assembly))
{
partManager.ApplicationParts.Add(new AssemblyPart(typeof(CollectionController).Assembly));
}
await using ServiceProvider provider = services.BuildServiceProvider();
IOpenApiDocumentProvider documentProvider = provider.GetRequiredKeyedService("v1");
return await documentProvider.GetOpenApiDocumentAsync();
}
}