Files
ersatztv/ErsatzTV.Tests/Controllers/GraphicsElementControllerTests.cs
T
timothyandClaude Fable 5 6e2e0e1858 feat(api): optional refresh param on GET /api/graphics-elements
Review SHOULD-FIX (#145): the SPA graphics picker could go stale because
Blazor ran RefreshGraphicsElements (disk->DB sync) before listing, while the
API endpoint never refreshed — a newly added .yml would not appear. GET
/api/graphics-elements?refresh=true now sends RefreshGraphicsElements before
the list query; default false leaves existing callers untouched. The playback
troubleshooting screen passes refresh=true. Controller tests cover
refresh-iff-true ordering; regenerated OpenAPI v1.json (endpoint index and
generated TS schemas unchanged - query params are not part of either).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 07:52:14 +02:00

90 lines
2.9 KiB
C#

using System.Reflection;
using ErsatzTV.Application.Graphics;
using ErsatzTV.Controllers.Api;
using ErsatzTV.Core.Api.Graphics;
using MediatR;
using Microsoft.AspNetCore.Mvc.Routing;
using NSubstitute;
using NUnit.Framework;
using Shouldly;
namespace ErsatzTV.Tests.Controllers;
[TestFixture]
public class GraphicsElementControllerTests
{
private GraphicsElementController _controller = null!;
private IMediator _mediator = null!;
[SetUp]
public void SetUp()
{
_mediator = Substitute.For<IMediator>();
_controller = new GraphicsElementController(_mediator);
}
[Test]
public void Controller_Should_Expose_Idiomatic_Rest_Route()
{
MethodInfo action = typeof(GraphicsElementController).GetMethod(nameof(GraphicsElementController.GetAll))
?? throw new AssertionException("Missing action GetAll");
HttpMethodAttribute attribute = action.GetCustomAttributes<HttpMethodAttribute>(inherit: true).Single();
attribute.HttpMethods.ShouldContain("GET");
attribute.Template.ShouldBe("/api/graphics-elements");
}
[Test]
public async Task GetAll_Should_Return_GraphicsElements()
{
List<GraphicsElementResponseModel> models =
[
new GraphicsElementResponseModel(1, "Lower Third (lower-third.png)"),
new GraphicsElementResponseModel(2, "bug.png")
];
_mediator.Send(Arg.Any<GetAllGraphicsElementsForApi>(), Arg.Any<CancellationToken>())
.Returns(models);
List<GraphicsElementResponseModel> result = await _controller.GetAll(refresh: false, CancellationToken.None);
result.ShouldBe(models);
}
[Test]
public async Task GetAll_Should_Return_Empty_List_When_None_Exist()
{
_mediator.Send(Arg.Any<GetAllGraphicsElementsForApi>(), Arg.Any<CancellationToken>())
.Returns([]);
List<GraphicsElementResponseModel> result = await _controller.GetAll(refresh: false, CancellationToken.None);
result.ShouldBeEmpty();
}
[Test]
public async Task GetAll_Should_Not_Refresh_When_Refresh_Is_False()
{
_mediator.Send(Arg.Any<GetAllGraphicsElementsForApi>(), Arg.Any<CancellationToken>())
.Returns([]);
await _controller.GetAll(refresh: false, CancellationToken.None);
await _mediator.DidNotReceive().Send(Arg.Any<RefreshGraphicsElements>(), Arg.Any<CancellationToken>());
}
[Test]
public async Task GetAll_Should_Refresh_Before_Listing_When_Refresh_Is_True()
{
_mediator.Send(Arg.Any<GetAllGraphicsElementsForApi>(), Arg.Any<CancellationToken>())
.Returns([]);
await _controller.GetAll(refresh: true, CancellationToken.None);
Received.InOrder(() =>
{
_mediator.Send(Arg.Any<RefreshGraphicsElements>(), Arg.Any<CancellationToken>());
_mediator.Send(Arg.Any<GetAllGraphicsElementsForApi>(), Arg.Any<CancellationToken>());
});
}
}