feat(api): #288 wrap raw VMs, nullable-honest DTOs, search pageNum

24 #nullable enable flips across ErsatzTV.Core/Api; Collection/Schedule/
SmartCollection/Resolution VMs wrapped in ResponseModels (Version now
header-only, SPA-verified); pageNum threaded into GET /api/search.

Refs #288 #197

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 02:08:12 +02:00
co-authored by Claude Opus 4.8
parent 9e2d160884
commit fecf16d3d2
38 changed files with 189 additions and 45 deletions
@@ -47,6 +47,31 @@ public class ResolutionControllerTests
]);
}
[Test]
public async Task GetResolutionByName_Should_Return_ResponseModel_Not_ViewModel()
{
_mediator.Send(Arg.Any<GetResolutionByName>(), Arg.Any<CancellationToken>())
.Returns(Option<ResolutionViewModel>.Some(new ResolutionViewModel(1, "1920x1080", 1920, 1080, false)));
ActionResult<ResolutionResponseModel> result =
await _controller.GetResolutionByName("1920x1080", CancellationToken.None);
var ok = result.Result.ShouldBeOfType<OkObjectResult>();
ok.Value.ShouldBe(new ResolutionResponseModel(1, "1920x1080", 1920, 1080, false));
}
[Test]
public async Task GetResolutionByName_Should_Return_404_For_None()
{
_mediator.Send(Arg.Any<GetResolutionByName>(), Arg.Any<CancellationToken>())
.Returns(Option<ResolutionViewModel>.None);
ActionResult<ResolutionResponseModel> result =
await _controller.GetResolutionByName("nope", CancellationToken.None);
result.Result.ShouldBeOfType<NotFoundResult>();
}
[Test]
public async Task Create_Should_Return_201_With_Location_And_Body()
{