Use block-scoped namespaces in the test suite
Converts all 73 test source files from file-scoped (namespace X;) to
block-scoped (namespace X { ... }) declarations, re-indenting their
contents accordingly. Matches the existing convention already used in
several production files (e.g. Musify.Infrastructure.Configuration,
Musify.Application.Contracts).
Mechanical change only, done with a script, verified with a full
rebuild (0 warnings, 0 errors) and test run (257/257 passing).
This commit is contained in:
+81
-80
@@ -5,107 +5,108 @@ using Musify.Application.Tests.TestSupport;
|
||||
using Musify.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class AddTrackToAlbumCommandHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private AddTrackToAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<AddTrackToAlbumCommandHandler>());
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_FirstTrack_AddsItAtNumberOne()
|
||||
public sealed class AddTrackToAlbumCommandHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, album, track);
|
||||
private AddTrackToAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<AddTrackToAlbumCommandHandler>());
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_FirstTrack_AddsItAtNumberOne()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, album, track);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var link = Assert.Single(await Database.AlbumHasTracks.ToListAsync(TestContext.Current.CancellationToken));
|
||||
Assert.Equal(1, link.TrackNumber);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, track);
|
||||
Assert.False(result.IsError);
|
||||
var link = Assert.Single(await Database.AlbumHasTracks.ToListAsync(TestContext.Current.CancellationToken));
|
||||
Assert.Equal(1, link.TrackNumber);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, Guid.NewGuid(), track.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, track);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, Guid.NewGuid(), track.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, stranger, album, track);
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(stranger.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, stranger, album, track);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(stranger.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TrackMissing_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_TrackMissing_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TrackOwnedByAnotherUser_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var otherOwner = TestEntities.User(2, "other");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var foreignTrack = TestEntities.LocalTrack(otherOwner);
|
||||
await SeedAsync(owner, otherOwner, album, foreignTrack);
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, foreignTrack.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_TrackOwnedByAnotherUser_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var otherOwner = TestEntities.User(2, "other");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var foreignTrack = TestEntities.LocalTrack(otherOwner);
|
||||
await SeedAsync(owner, otherOwner, album, foreignTrack);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, foreignTrack.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlreadyInAlbum_ReturnsConflict()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
var link = new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 };
|
||||
await SeedAsync(owner, album, track, link);
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_AlreadyInAlbum_ReturnsConflict()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
var link = new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 };
|
||||
await SeedAsync(owner, album, track, link);
|
||||
|
||||
Assert.Equal(ErrorType.Conflict, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, track.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumAlreadyHasTracks_AppendsAtNextNumber()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var firstTrack = TestEntities.LocalTrack(owner, "First");
|
||||
var secondTrack = TestEntities.LocalTrack(owner, "Second");
|
||||
var existingLink = new AlbumHasTrack { AlbumId = album.Id, TrackId = firstTrack.Id, TrackNumber = 3 };
|
||||
await SeedAsync(owner, album, firstTrack, secondTrack, existingLink);
|
||||
Assert.Equal(ErrorType.Conflict, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, secondTrack.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumAlreadyHasTracks_AppendsAtNextNumber()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var firstTrack = TestEntities.LocalTrack(owner, "First");
|
||||
var secondTrack = TestEntities.LocalTrack(owner, "Second");
|
||||
var existingLink = new AlbumHasTrack { AlbumId = album.Id, TrackId = firstTrack.Id, TrackNumber = 3 };
|
||||
await SeedAsync(owner, album, firstTrack, secondTrack, existingLink);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var newLink = await Database.AlbumHasTracks.SingleAsync(l => l.TrackId == secondTrack.Id, TestContext.Current.CancellationToken);
|
||||
Assert.Equal(4, newLink.TrackNumber);
|
||||
var result = await CreateHandler().Handle(new AddTrackToAlbumCommand(owner.Id, album.Id, secondTrack.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var newLink = await Database.AlbumHasTracks.SingleAsync(l => l.TrackId == secondTrack.Id, TestContext.Current.CancellationToken);
|
||||
Assert.Equal(4, newLink.TrackNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,41 +3,42 @@ using Musify.Application.Albums;
|
||||
using Musify.Application.Tests.TestSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class CreateAlbumCommandHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private CreateAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<CreateAlbumCommandHandler>());
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_UserExists_CreatesAlbumAndReturnsIt()
|
||||
public sealed class CreateAlbumCommandHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner);
|
||||
private CreateAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<CreateAlbumCommandHandler>());
|
||||
|
||||
var command = new CreateAlbumCommand(owner.Id, " My Album ", "A description", 2024);
|
||||
[Fact]
|
||||
public async Task Handle_UserExists_CreatesAlbumAndReturnsIt()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner);
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
var command = new CreateAlbumCommand(owner.Id, " My Album ", "A description", 2024);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("My Album", result.Value.Title);
|
||||
Assert.Equal("A description", result.Value.Description);
|
||||
Assert.Equal(2024, result.Value.ReleaseYear);
|
||||
Assert.Equal(owner.Id, result.Value.OwnerUserId);
|
||||
Assert.Equal(0, result.Value.TrackCount);
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
var stored = await Database.UserAlbums.FindAsync([result.Value.Id], TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal("MY ALBUM", stored.NormalizedTitle);
|
||||
}
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("My Album", result.Value.Title);
|
||||
Assert.Equal("A description", result.Value.Description);
|
||||
Assert.Equal(2024, result.Value.ReleaseYear);
|
||||
Assert.Equal(owner.Id, result.Value.OwnerUserId);
|
||||
Assert.Equal(0, result.Value.TrackCount);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_UserDoesNotExist_ReturnsNotFound()
|
||||
{
|
||||
var command = new CreateAlbumCommand(UserId: 404, "Orphan Album", Description: null, ReleaseYear: null);
|
||||
var stored = await Database.UserAlbums.FindAsync([result.Value.Id], TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal("MY ALBUM", stored.NormalizedTitle);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_UserDoesNotExist_ReturnsNotFound()
|
||||
{
|
||||
var command = new CreateAlbumCommand(UserId: 404, "Orphan Album", Description: null, ReleaseYear: null);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,44 +3,45 @@ using Musify.Application.Albums;
|
||||
using Musify.Application.Tests.TestSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class DeleteAlbumCommandHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private DeleteAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<DeleteAlbumCommandHandler>());
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_Owner_RemovesAlbum()
|
||||
public sealed class DeleteAlbumCommandHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
private DeleteAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<DeleteAlbumCommandHandler>());
|
||||
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(owner.Id, album.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_Owner_RemovesAlbum()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Null(await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken));
|
||||
}
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(owner.Id, album.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(1, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
Assert.False(result.IsError);
|
||||
Assert.Null(await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken));
|
||||
}
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(1, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorizedAndKeepsAlbum()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(stranger.Id, album.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorizedAndKeepsAlbum()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.NotNull(await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken));
|
||||
var result = await CreateHandler().Handle(new DeleteAlbumCommand(stranger.Id, album.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
Assert.NotNull(await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,33 +4,34 @@ using Musify.Application.Tests.TestSupport;
|
||||
using Musify.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class GetAlbumByIdQueryHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private GetAlbumByIdQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ExistingAlbum_ReturnsItWithTrackCountAndCovers()
|
||||
public sealed class GetAlbumByIdQueryHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, album, track, new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 });
|
||||
private GetAlbumByIdQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumByIdQuery(album.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_ExistingAlbum_ReturnsItWithTrackCountAndCovers()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var track = TestEntities.LocalTrack(owner);
|
||||
await SeedAsync(owner, album, track, new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 });
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(album.Id, result.Value.Id);
|
||||
Assert.Equal(1, result.Value.TrackCount);
|
||||
Assert.Equal([track.Id], result.Value.CoverTrackIds);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetAlbumByIdQuery(album.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumByIdQuery(Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(album.Id, result.Value.Id);
|
||||
Assert.Equal(1, result.Value.TrackCount);
|
||||
Assert.Equal([track.Id], result.Value.CoverTrackIds);
|
||||
}
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumByIdQuery(Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,35 +4,36 @@ using Musify.Application.Tests.TestSupport;
|
||||
using Musify.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class GetAlbumTracksQueryHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private GetAlbumTracksQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumWithTracks_ReturnsThemOrderedByTrackNumber()
|
||||
public sealed class GetAlbumTracksQueryHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var second = TestEntities.LocalTrack(owner, "Second");
|
||||
var first = TestEntities.LocalTrack(owner, "First");
|
||||
await SeedAsync(
|
||||
owner, album, second, first,
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = second.Id, TrackNumber = 2 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = first.Id, TrackNumber = 1 });
|
||||
private GetAlbumTracksQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumTracksQuery(album.Id, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumWithTracks_ReturnsThemOrderedByTrackNumber()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var second = TestEntities.LocalTrack(owner, "Second");
|
||||
var first = TestEntities.LocalTrack(owner, "First");
|
||||
await SeedAsync(
|
||||
owner, album, second, first,
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = second.Id, TrackNumber = 2 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = first.Id, TrackNumber = 1 });
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(["First", "Second"], result.Value.Items.Select(track => track.Title));
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetAlbumTracksQuery(album.Id, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumTracksQuery(Guid.NewGuid(), PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(["First", "Second"], result.Value.Items.Select(track => track.Title));
|
||||
}
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumTracksQuery(Guid.NewGuid(), PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-20
@@ -3,31 +3,32 @@ using Musify.Application.Albums;
|
||||
using Musify.Application.Tests.TestSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class GetAlbumsByUserIdQueryHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private GetAlbumsByUserIdQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_UserWithAlbums_ReturnsOnlyTheirAlbums()
|
||||
public sealed class GetAlbumsByUserIdQueryHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var other = TestEntities.User(2, "other");
|
||||
await SeedAsync(owner, other, TestEntities.UserAlbum(owner.Id, "Mine"), TestEntities.UserAlbum(other.Id, "Theirs"));
|
||||
private GetAlbumsByUserIdQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumsByUserIdQuery(owner.Id, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_UserWithAlbums_ReturnsOnlyTheirAlbums()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var other = TestEntities.User(2, "other");
|
||||
await SeedAsync(owner, other, TestEntities.UserAlbum(owner.Id, "Mine"), TestEntities.UserAlbum(other.Id, "Theirs"));
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var album = Assert.Single(result.Value.Items);
|
||||
Assert.Equal("Mine", album.Title);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetAlbumsByUserIdQuery(owner.Id, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_UserMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumsByUserIdQuery(404, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
Assert.False(result.IsError);
|
||||
var album = Assert.Single(result.Value.Items);
|
||||
Assert.Equal("Mine", album.Title);
|
||||
}
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
[Fact]
|
||||
public async Task Handle_UserMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new GetAlbumsByUserIdQuery(404, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,47 +2,48 @@ using Musify.Application.Albums;
|
||||
using Musify.Application.Tests.TestSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class GetAlbumsQueryHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private GetAlbumsQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NoTitleFilter_ReturnsAllAlbumsPaged()
|
||||
public sealed class GetAlbumsQueryHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "Alpha"), TestEntities.UserAlbum(owner.Id, "Beta"));
|
||||
private GetAlbumsQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: null, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_NoTitleFilter_ReturnsAllAlbumsPaged()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "Alpha"), TestEntities.UserAlbum(owner.Id, "Beta"));
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.TotalItemCount);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: null, PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TitleFilter_ReturnsOnlyMatchingAlbums()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "Rock Classics"), TestEntities.UserAlbum(owner.Id, "Jazz Favorites"));
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.TotalItemCount);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: "rock", PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_TitleFilter_ReturnsOnlyMatchingAlbums()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "Rock Classics"), TestEntities.UserAlbum(owner.Id, "Jazz Favorites"));
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var album = Assert.Single(result.Value.Items);
|
||||
Assert.Equal("Rock Classics", album.Title);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: "rock", PageNumber: 1, PageSize: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_PageSizeSmallerThanTotal_ReportsHasNextPage()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "One"), TestEntities.UserAlbum(owner.Id, "Two"), TestEntities.UserAlbum(owner.Id, "Three"));
|
||||
Assert.False(result.IsError);
|
||||
var album = Assert.Single(result.Value.Items);
|
||||
Assert.Equal("Rock Classics", album.Title);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: null, PageNumber: 1, PageSize: 2), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_PageSizeSmallerThanTotal_ReportsHasNextPage()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner, TestEntities.UserAlbum(owner.Id, "One"), TestEntities.UserAlbum(owner.Id, "Two"), TestEntities.UserAlbum(owner.Id, "Three"));
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.Items.Count);
|
||||
Assert.True(result.Value.HasNextPage);
|
||||
var result = await CreateHandler().Handle(new GetAlbumsQuery(Title: null, PageNumber: 1, PageSize: 2), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.Items.Count);
|
||||
Assert.True(result.Value.HasNextPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-43
@@ -3,58 +3,59 @@ using Musify.Application.Tests.TestSupport;
|
||||
using Musify.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class GetRecentlyListenedAlbumsQueryHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private GetRecentlyListenedAlbumsQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ListenedTracks_ReturnsTheirAlbumsMostRecentFirst()
|
||||
public sealed class GetRecentlyListenedAlbumsQueryHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var olderAlbum = TestEntities.UserAlbum(owner.Id, "Older");
|
||||
var newerAlbum = TestEntities.UserAlbum(owner.Id, "Newer");
|
||||
var olderTrack = TestEntities.LocalTrack(owner, "In older album");
|
||||
var newerTrack = TestEntities.LocalTrack(owner, "In newer album");
|
||||
await SeedAsync(
|
||||
owner, olderAlbum, newerAlbum, olderTrack, newerTrack,
|
||||
new AlbumHasTrack { AlbumId = olderAlbum.Id, TrackId = olderTrack.Id, TrackNumber = 1 },
|
||||
new AlbumHasTrack { AlbumId = newerAlbum.Id, TrackId = newerTrack.Id, TrackNumber = 1 },
|
||||
TestEntities.ListeningHistory(owner.Id, olderTrack.Id, DateTime.UtcNow.AddDays(-2)),
|
||||
TestEntities.ListeningHistory(owner.Id, newerTrack.Id, DateTime.UtcNow.AddDays(-1)));
|
||||
private GetRecentlyListenedAlbumsQueryHandler CreateHandler() => new(Database);
|
||||
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_ListenedTracks_ReturnsTheirAlbumsMostRecentFirst()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var olderAlbum = TestEntities.UserAlbum(owner.Id, "Older");
|
||||
var newerAlbum = TestEntities.UserAlbum(owner.Id, "Newer");
|
||||
var olderTrack = TestEntities.LocalTrack(owner, "In older album");
|
||||
var newerTrack = TestEntities.LocalTrack(owner, "In newer album");
|
||||
await SeedAsync(
|
||||
owner, olderAlbum, newerAlbum, olderTrack, newerTrack,
|
||||
new AlbumHasTrack { AlbumId = olderAlbum.Id, TrackId = olderTrack.Id, TrackNumber = 1 },
|
||||
new AlbumHasTrack { AlbumId = newerAlbum.Id, TrackId = newerTrack.Id, TrackNumber = 1 },
|
||||
TestEntities.ListeningHistory(owner.Id, olderTrack.Id, DateTime.UtcNow.AddDays(-2)),
|
||||
TestEntities.ListeningHistory(owner.Id, newerTrack.Id, DateTime.UtcNow.AddDays(-1)));
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(["Newer", "Older"], result.Value.Select(album => album.Title));
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NoListeningHistory_ReturnsEmptyList()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner);
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(["Newer", "Older"], result.Value.Select(album => album.Title));
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 10), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_NoListeningHistory_ReturnsEmptyList()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
await SeedAsync(owner);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Empty(result.Value);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 10), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_LimitLowerThanCandidates_ReturnsOnlyThatManyAlbums()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var albums = Enumerable.Range(1, 3).Select(i => TestEntities.UserAlbum(owner.Id, $"Album {i}")).ToList();
|
||||
var tracks = albums.Select((_, i) => TestEntities.LocalTrack(owner, $"Track {i}")).ToList();
|
||||
var links = albums.Zip(tracks, (album, track) => new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 }).ToList();
|
||||
var histories = tracks.Select((track, i) => TestEntities.ListeningHistory(owner.Id, track.Id, DateTime.UtcNow.AddMinutes(-i))).ToList();
|
||||
await SeedAsync([owner, .. albums, .. tracks, .. links, .. histories]);
|
||||
Assert.False(result.IsError);
|
||||
Assert.Empty(result.Value);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 2), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_LimitLowerThanCandidates_ReturnsOnlyThatManyAlbums()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var albums = Enumerable.Range(1, 3).Select(i => TestEntities.UserAlbum(owner.Id, $"Album {i}")).ToList();
|
||||
var tracks = albums.Select((_, i) => TestEntities.LocalTrack(owner, $"Track {i}")).ToList();
|
||||
var links = albums.Zip(tracks, (album, track) => new AlbumHasTrack { AlbumId = album.Id, TrackId = track.Id, TrackNumber = 1 }).ToList();
|
||||
var histories = tracks.Select((track, i) => TestEntities.ListeningHistory(owner.Id, track.Id, DateTime.UtcNow.AddMinutes(-i))).ToList();
|
||||
await SeedAsync([owner, .. albums, .. tracks, .. links, .. histories]);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.Count);
|
||||
var result = await CreateHandler().Handle(new GetRecentlyListenedAlbumsQuery(owner.Id, Limit: 2), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal(2, result.Value.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+52
-51
@@ -5,68 +5,69 @@ using Musify.Application.Tests.TestSupport;
|
||||
using Musify.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class RemoveTrackFromAlbumCommandHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private RemoveTrackFromAlbumCommandHandler CreateHandler() =>
|
||||
new(Database, NoOpLogger<RemoveTrackFromAlbumCommandHandler>());
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TrackInAlbum_RemovesItAndRenumbersTheRest()
|
||||
public sealed class RemoveTrackFromAlbumCommandHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var first = TestEntities.LocalTrack(owner, "First");
|
||||
var second = TestEntities.LocalTrack(owner, "Second");
|
||||
var third = TestEntities.LocalTrack(owner, "Third");
|
||||
await SeedAsync(
|
||||
owner, album, first, second, third,
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = first.Id, TrackNumber = 1 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = second.Id, TrackNumber = 2 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = third.Id, TrackNumber = 3 });
|
||||
private RemoveTrackFromAlbumCommandHandler CreateHandler() =>
|
||||
new(Database, NoOpLogger<RemoveTrackFromAlbumCommandHandler>());
|
||||
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(owner.Id, album.Id, second.Id), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_TrackInAlbum_RemovesItAndRenumbersTheRest()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
var first = TestEntities.LocalTrack(owner, "First");
|
||||
var second = TestEntities.LocalTrack(owner, "Second");
|
||||
var third = TestEntities.LocalTrack(owner, "Third");
|
||||
await SeedAsync(
|
||||
owner, album, first, second, third,
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = first.Id, TrackNumber = 1 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = second.Id, TrackNumber = 2 },
|
||||
new AlbumHasTrack { AlbumId = album.Id, TrackId = third.Id, TrackNumber = 3 });
|
||||
|
||||
Assert.False(result.IsError);
|
||||
var remaining = await Database.AlbumHasTracks
|
||||
.Where(link => link.AlbumId == album.Id)
|
||||
.OrderBy(link => link.TrackNumber)
|
||||
.ToListAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Equal([first.Id, third.Id], remaining.Select(link => link.TrackId));
|
||||
Assert.Equal([1, 2], remaining.Select(link => link.TrackNumber));
|
||||
}
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(owner.Id, album.Id, second.Id), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(1, Guid.NewGuid(), Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
Assert.False(result.IsError);
|
||||
var remaining = await Database.AlbumHasTracks
|
||||
.Where(link => link.AlbumId == album.Id)
|
||||
.OrderBy(link => link.TrackNumber)
|
||||
.ToListAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Equal([first.Id, third.Id], remaining.Select(link => link.TrackId));
|
||||
Assert.Equal([1, 2], remaining.Select(link => link.TrackNumber));
|
||||
}
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(1, Guid.NewGuid(), Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(stranger.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(stranger.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_TrackNotInAlbum_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(owner.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_TrackNotInAlbum_ReturnsNotFound()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, album);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
var result = await CreateHandler().Handle(new RemoveTrackFromAlbumCommand(owner.Id, album.Id, Guid.NewGuid()), TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,55 +3,56 @@ using Musify.Application.Albums;
|
||||
using Musify.Application.Tests.TestSupport;
|
||||
using Xunit;
|
||||
|
||||
namespace Musify.Application.Tests.Albums;
|
||||
|
||||
public sealed class UpdateAlbumCommandHandlerTests : HandlerTestBase
|
||||
namespace Musify.Application.Tests.Albums
|
||||
{
|
||||
private UpdateAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<UpdateAlbumCommandHandler>());
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_Owner_UpdatesTitleDescriptionAndReleaseYear()
|
||||
public sealed class UpdateAlbumCommandHandlerTests : HandlerTestBase
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id, title: "Old Title", description: "Old", releaseYear: 2020);
|
||||
await SeedAsync(owner, album);
|
||||
private UpdateAlbumCommandHandler CreateHandler() => new(Database, NoOpLogger<UpdateAlbumCommandHandler>());
|
||||
|
||||
var command = new UpdateAlbumCommand(owner.Id, album.Id, " New Title ", "New description", 2025);
|
||||
[Fact]
|
||||
public async Task Handle_Owner_UpdatesTitleDescriptionAndReleaseYear()
|
||||
{
|
||||
var owner = TestEntities.User();
|
||||
var album = TestEntities.UserAlbum(owner.Id, title: "Old Title", description: "Old", releaseYear: 2020);
|
||||
await SeedAsync(owner, album);
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
var command = new UpdateAlbumCommand(owner.Id, album.Id, " New Title ", "New description", 2025);
|
||||
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("New Title", result.Value.Title);
|
||||
Assert.Equal("New description", result.Value.Description);
|
||||
Assert.Equal(2025, result.Value.ReleaseYear);
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
var stored = await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal("NEW TITLE", stored.NormalizedTitle);
|
||||
}
|
||||
Assert.False(result.IsError);
|
||||
Assert.Equal("New Title", result.Value.Title);
|
||||
Assert.Equal("New description", result.Value.Description);
|
||||
Assert.Equal(2025, result.Value.ReleaseYear);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var command = new UpdateAlbumCommand(1, Guid.NewGuid(), "Title", null, null);
|
||||
var stored = await Database.UserAlbums.FindAsync([album.Id], TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal("NEW TITLE", stored.NormalizedTitle);
|
||||
}
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
[Fact]
|
||||
public async Task Handle_AlbumMissing_ReturnsNotFound()
|
||||
{
|
||||
var command = new UpdateAlbumCommand(1, Guid.NewGuid(), "Title", null, null);
|
||||
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
Assert.Equal(ErrorType.NotFound, result.FirstError.Type);
|
||||
}
|
||||
|
||||
var command = new UpdateAlbumCommand(stranger.Id, album.Id, "Hijacked", null, null);
|
||||
[Fact]
|
||||
public async Task Handle_NotOwner_ReturnsUnauthorized()
|
||||
{
|
||||
var owner = TestEntities.User(1, "owner");
|
||||
var stranger = TestEntities.User(2, "stranger");
|
||||
var album = TestEntities.UserAlbum(owner.Id);
|
||||
await SeedAsync(owner, stranger, album);
|
||||
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
var command = new UpdateAlbumCommand(stranger.Id, album.Id, "Hijacked", null, null);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
var result = await CreateHandler().Handle(command, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(ErrorType.Unauthorized, result.FirstError.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user