using System.Text.Json; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging.Abstractions; using Tiku.Api.Middleware; using Tiku.Api.Modules.Platform.Errors; using Tiku.Application.Backoffice; namespace Tiku.IntegrationTests.Api; public sealed class ExceptionHandlingMiddlewareTests { [Theory] [InlineData("platform_access_denied", StatusCodes.Status403Forbidden)] [InlineData("role_not_found", StatusCodes.Status404NotFound)] [InlineData("permission_not_found", StatusCodes.Status404NotFound)] [InlineData("system_role_locked", StatusCodes.Status400BadRequest)] [InlineData("tenant_required", StatusCodes.Status400BadRequest)] public async Task Backoffice_exception_is_returned_as_problem_details(string code, int expectedStatus) { var context = new DefaultHttpContext(); context.Request.Path = "/api/backoffice/test"; context.Response.Body = new MemoryStream(); context.TraceIdentifier = "backoffice-test-trace"; var middleware = new ExceptionHandlingMiddleware( _ => throw new BackofficeException("Backoffice request failed.", code), NullLogger.Instance, new TestHostEnvironment(), [new PlatformExceptionProblemDetailsMapper()]); await middleware.InvokeAsync(context); Assert.Equal(expectedStatus, context.Response.StatusCode); context.Response.Body.Position = 0; using var document = await JsonDocument.ParseAsync(context.Response.Body); var root = document.RootElement; Assert.Equal("Backoffice request failed.", root.GetProperty("title").GetString()); Assert.Equal(expectedStatus, root.GetProperty("status").GetInt32()); Assert.Equal("/api/backoffice/test", root.GetProperty("instance").GetString()); Assert.Equal(code, root.GetProperty("code").GetString()); Assert.Equal("backoffice-test-trace", root.GetProperty("traceId").GetString()); } [Fact] public async Task Registered_exception_types_have_exactly_one_owner() { await using var factory = new ApiTestFactory(); var ownership = factory.Services.GetServices() .SelectMany(mapper => mapper.HandledExceptionTypes.Select(type => new { type, mapper })) .GroupBy(item => item.type) .Where(group => group.Count() != 1) .Select(group => group.Key.FullName) .ToArray(); Assert.Empty(ownership); } private sealed class TestHostEnvironment : IHostEnvironment { public string EnvironmentName { get; set; } = Environments.Production; public string ApplicationName { get; set; } = "Tiku.IntegrationTests"; public string ContentRootPath { get; set; } = AppContext.BaseDirectory; public IFileProvider ContentRootFileProvider { get; set; } = new NullFileProvider(); } }