Fix query and API bugs: 403 for non-owners, page bounds, lifecycle filters, cover fallback, race-safe inserts, async album delete
This commit is contained in:
+16
-2
@@ -53,7 +53,7 @@ public sealed class AddTrackToPlayListCommandHandlerTests : HandlerTestBase
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
public async Task Handle_NotOwner_ReturnsForbidden()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
@@ -62,7 +62,7 @@ public sealed class AddTrackToPlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToPlayListCommand(stranger.Id, playList.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.Equal(ErrorType.Forbidden, result.FirstError.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -89,4 +89,18 @@ public sealed class AddTrackToPlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
Assert.Equal(ErrorType.Conflict, result.FirstError.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TrySaveChangesAsync_DuplicatePlayListTrack_MapsTheUniqueViolationToTheGivenError()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var playList = TestEntities.PlayList(owner.Id);
|
||||
var track = TestEntities.Track(owner);
|
||||
await SeedAsync(owner, playList, track, new PlayListHasTrack { PlayListId = playList.Id, TrackId = track.Id, Position = 0 });
|
||||
Database.PlayListHasTracks.Add(new PlayListHasTrack { PlayListId = playList.Id, TrackId = track.Id, Position = 1 });
|
||||
|
||||
var result = await Database.TrySaveChangesAsync(Error.Conflict("Test.Duplicate", "duplicate"), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal("Test.Duplicate", result.FirstError.Code);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ public sealed class DeletePlayListCommandHandlerTests : HandlerTestBase
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
public async Task Handle_NotOwner_ReturnsForbidden()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
@@ -48,6 +48,6 @@ public sealed class DeletePlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
var result = await CreateHandler().Handle(new DeletePlayListCommand(stranger.Id, playList.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.Equal(ErrorType.Forbidden, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-2
@@ -33,7 +33,7 @@ public sealed class RemoveTrackFromPlayListCommandHandlerTests : HandlerTestBase
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
public async Task Handle_NotOwner_ReturnsForbidden()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
@@ -42,7 +42,7 @@ public sealed class RemoveTrackFromPlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromPlayListCommand(stranger.Id, playList.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.Equal(ErrorType.Forbidden, result.FirstError.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -56,4 +56,26 @@ public sealed class RemoveTrackFromPlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TrackInTheMiddle_RenumbersTheRemainingTracks()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var playList = TestEntities.PlayList(owner.Id);
|
||||
var first = TestEntities.Track(owner, "First");
|
||||
var second = TestEntities.Track(owner, "Second");
|
||||
var third = TestEntities.Track(owner, "Third");
|
||||
await SeedAsync(
|
||||
owner, playList, first, second, third,
|
||||
new PlayListHasTrack { PlayListId = playList.Id, TrackId = first.Id, Position = 0 },
|
||||
new PlayListHasTrack { PlayListId = playList.Id, TrackId = second.Id, Position = 1 },
|
||||
new PlayListHasTrack { PlayListId = playList.Id, TrackId = third.Id, Position = 2 });
|
||||
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromPlayListCommand(owner.Id, playList.Id, second.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var remaining = Database.PlayListHasTracks.OrderBy(link => link.Position).ToList();
|
||||
Assert.Equal([first.Id, third.Id], remaining.Select(link => link.TrackId));
|
||||
Assert.Equal([0, 1], remaining.Select(link => link.Position));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -48,7 +48,7 @@ public sealed class UpdatePlayListCommandHandlerTests : HandlerTestBase
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
public async Task Handle_NotOwner_ReturnsForbidden()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
@@ -59,7 +59,7 @@ public sealed class UpdatePlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.Equal(ErrorType.Forbidden, result.FirstError.Type);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -93,7 +93,7 @@ public sealed class UpdatePlayListCommandHandlerTests : HandlerTestBase
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_BlankNameAndDescription_LeavesThemUnchanged()
|
||||
public async Task Handle_BlankName_LeavesItUnchangedAndBlankDescriptionClearsIt()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var playList = TestEntities.PlayList(owner.Id, "Original Name", "Original description");
|
||||
@@ -105,7 +105,7 @@ public sealed class UpdatePlayListCommandHandlerTests : HandlerTestBase
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("Original Name", result.Value.Name);
|
||||
Assert.Equal("Original description", result.Value.Description);
|
||||
Assert.Null(result.Value.Description);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -126,7 +126,7 @@ public sealed class UpdatePlayListCommandHandlerTests : HandlerTestBase
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("new-cover.webp", result.Value.SmallImageKeyName);
|
||||
Assert.Null(result.Value.SmallImageKeyName);
|
||||
var stored = await Database.PlayLists.FindAsync([playList.Id], TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal("new-cover.webp", stored.Pictures?.OriginalName);
|
||||
|
||||
Reference in New Issue
Block a user