Expand test coverage to match specs

This commit is contained in:
2026-02-05 18:57:25 +01:00
parent e11cb23313
commit 67a164e53b
14 changed files with 861 additions and 32 deletions

View File

@@ -1,13 +1,18 @@
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using GameList.Infrastructure;
using GameList.Endpoints;
using GameList.Tests.Support;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Testing;
using System.Text.Json;
using System.Net.Http.Json;
namespace GameList.Tests;
@@ -62,6 +67,74 @@ public class HelperTests
Assert.False(await EndpointHelpers.IsReachableImageAsync("http://127.0.0.1/img.png", new StubHttpClientFactory(new StubHttpMessageHandler())));
}
[Fact]
public async Task IsReachableImageAsync_handles_head_success_redirect_and_size_guard()
{
var handler = new StubHttpMessageHandler();
handler.SetResponder(req =>
{
if (req.Method == HttpMethod.Head)
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new ByteArrayContent(Array.Empty<byte>());
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
resp.Content.Headers.ContentLength = 100;
return resp;
}
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(Array.Empty<byte>())
{
Headers =
{
ContentType = new MediaTypeHeaderValue("image/png"),
ContentLength = 100
}
}
};
});
var ok = await EndpointHelpers.IsReachableImageAsync("http://example.com/img.png", new StubHttpClientFactory(handler), handler);
Assert.True(ok);
handler.SetResponder(_ =>
{
var resp = new HttpResponseMessage(HttpStatusCode.Redirect);
resp.Headers.Location = new Uri("http://example.com/other");
return resp;
});
var redirect = await EndpointHelpers.IsReachableImageAsync("http://example.com/img.png", new StubHttpClientFactory(handler), handler);
Assert.False(redirect);
handler.SetResponder(_ =>
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new ByteArrayContent(new byte[10]);
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
resp.Content.Headers.ContentLength = 6 * 1024 * 1024; // over 5 MB
return resp;
});
var tooLarge = await EndpointHelpers.IsReachableImageAsync("http://example.com/img.png", new StubHttpClientFactory(handler), handler);
Assert.False(tooLarge);
}
[Fact]
public async Task IsReachableImageAsync_rejects_non_image_content()
{
var handler = new StubHttpMessageHandler();
handler.SetResponder(_ =>
{
var resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes("not image"));
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
resp.Content.Headers.ContentLength = 9;
return resp;
});
var result = await EndpointHelpers.IsReachableImageAsync("http://example.com/img.png", new StubHttpClientFactory(handler), handler);
Assert.False(result);
}
[Fact]
public void Link_root_helpers_handle_groups()
{
@@ -98,6 +171,29 @@ public class HelperTests
Assert.Equal(3, root); // cycle breaks on revisit
}
[Fact]
public async Task Global_exception_handler_returns_json_error()
{
using var factory = new TestWebApplicationFactory().WithWebHostBuilder(builder =>
{
builder.Configure(app =>
{
app.UseGlobalExceptionLogging();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/boom", _ => throw new InvalidOperationException("boom"));
});
});
});
var client = factory.CreateClient();
var resp = await client.GetAsync("/boom");
Assert.Equal(HttpStatusCode.InternalServerError, resp.StatusCode);
var json = await resp.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal("Unexpected server error", json.GetProperty("error").GetString());
}
private class FakeEnv : IWebHostEnvironment
{
public string ApplicationName { get; set; } = "";