fix(#193): review follow-ups — drop Playlist option, non-tracking existence check
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 7m43s
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 9m52s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped

Adversarial review follow-ups on the #193 rerun selection validation:
- RerunCollectionEditor.razor: remove the CollectionType.Playlist
  dropdown option — RerunCollection has no PlaylistId column, so the
  option previously persisted a broken row and now fails validation.
- RerunCollectionSelectionValidation: replace FindAsync with a
  non-tracking AnyAsync(EF.Property<int>("Id") == id) existence check
  so nothing is materialized/tracked into the save-path context.
- Tests: pin the deliberate 422-not-404 choice
  (ShouldNotBeOfType<NotFoundError>) and cover the unsupported-type
  default arm (Playlist -> "Unsupported collection type"), which was
  reachable via the Blazor editor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 19:53:29 +02:00
co-authored by Claude Fable 5
parent ad7e151565
commit 6dac2d724c
3 changed files with 20 additions and 2 deletions
@@ -100,7 +100,9 @@ internal static class RerunCollectionSelectionValidation
CancellationToken cancellationToken)
where T : class
{
if (id is null || await set.FindAsync([id.Value], cancellationToken) is null)
// pure existence check — no tracking, nothing materialized into the save-path context
if (id is null ||
!await set.AnyAsync(e => EF.Property<int>(e, "Id") == id.Value, cancellationToken))
{
return Fail<BaseError, Unit>(errorMessage);
}
@@ -3,6 +3,7 @@ using ErsatzTV.Application.MediaCollections;
using ErsatzTV.Application.MediaItems;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Errors;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Tests.Support;
@@ -32,9 +33,25 @@ public class RerunCollectionHandlerTests : MediaCollectionHandlerTestBase
CancellationToken.None);
BaseError error = LeftOf(result);
// deliberate 422-not-404: the missing entity is a request-body FK, not the route resource
error.ShouldNotBeOfType<NotFoundError>();
error.Value.ShouldContain("Collection does not exist");
}
[Test]
public async Task Create_Should_Return_Error_When_CollectionType_Unsupported()
{
var handler = new CreateRerunCollectionHandler(Db.Factory);
// reachable via the legacy Blazor editor (no IsSupportedSelectionType pre-check)
Either<BaseError, RerunCollectionViewModel> result = await handler.Handle(
MakeCreate(CollectionType.Playlist),
CancellationToken.None);
BaseError error = LeftOf(result);
error.Value.ShouldContain("Unsupported collection type");
}
[Test]
public async Task Create_Should_Return_Error_When_MediaItem_Missing()
{
@@ -36,7 +36,6 @@
<MudSelectItem Value="CollectionType.Artist">Artist</MudSelectItem>
<MudSelectItem Value="CollectionType.MultiCollection">Multi Collection</MudSelectItem>
<MudSelectItem Value="CollectionType.SmartCollection">Smart Collection</MudSelectItem>
<MudSelectItem Value="CollectionType.Playlist">Playlist</MudSelectItem>
</MudSelect>
</MudStack>
@if (_model.CollectionType == CollectionType.Collection)