Files
Musify/backend/Tests/Musify.Infrastructure.Tests/MassTransit/DeleteRoutingSlipBuilderTests.cs
T
Admin 28a7c4a98c Enable more analyzers, drop log-and-rethrow in file activities and apply dotnet format
Use invariant culture when formatting ids, put cancellation tokens last in endpoint handlers, remove the
CS8618 pragmas and keep only the analyzer overrides that still apply.
2026-09-24 12:57:53 +02:00

206 lines
8.1 KiB
C#

using Musify.Application.Configuration;
using Musify.Domain.Entities;
using Musify.Domain.ValueObjects;
using Musify.Infrastructure.MassTransit.RoutingSlip;
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
using Musify.Infrastructure.Tests.TestSupport;
using Xunit;
namespace Musify.Infrastructure.Tests.MassTransit;
[Collection(InfrastructureCollection.Name)]
public sealed class DeleteRoutingSlipBuilderTests(InfrastructureTestFixture fixture)
{
private static CancellationToken Ct => TestContext.Current.CancellationToken;
[Fact]
public async Task BuildAlbum_WithProcessedPictures_RemovesEveryPictureBeforeDeletingTheRow()
{
var album = await SeedAlbumAsync(new EntityPictures
{
OriginalName = "original.webp",
SmallName = "small.webp",
MediumName = "medium.webp",
LargeName = "large.webp"
});
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildAlbumAsync(album.Id, album.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[
ActivityNames.MarkAlbumAsRemoving,
ActivityNames.RemoveAlbumOriginalPicture,
ActivityNames.RemoveAlbumSmallPicture,
ActivityNames.RemoveAlbumMediumPicture,
ActivityNames.RemoveAlbumLargePicture,
ActivityNames.DeleteAlbumFromDb,
],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildAlbum_WithPendingPicture_OnlyRemovesTheOriginal()
{
var album = await SeedAlbumAsync(EntityPictures.Pending("original.webp"));
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildAlbumAsync(album.Id, album.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[ActivityNames.MarkAlbumAsRemoving, ActivityNames.RemoveAlbumOriginalPicture, ActivityNames.DeleteAlbumFromDb],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildAlbum_MissingAlbum_OnlyMarksAndDeletes()
{
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildAlbumAsync(Guid.NewGuid(), 1, null, Ct)).Build();
Assert.Equal(
[ActivityNames.MarkAlbumAsRemoving, ActivityNames.DeleteAlbumFromDb],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildPlayList_WithoutPictures_OnlyMarksAndDeletes()
{
var playList = await SeedPlayListAsync(pictures: null);
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildPlayListAsync(playList.Id, playList.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[ActivityNames.MarkPlayListAsRemoving, ActivityNames.DeletePlayListFromDb],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildPlayList_WithPictures_RemovesThemBetweenMarkAndDelete()
{
var playList = await SeedPlayListAsync(new EntityPictures { OriginalName = "original.webp", SmallName = "small.webp" });
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildPlayListAsync(playList.Id, playList.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[
ActivityNames.MarkPlayListAsRemoving,
ActivityNames.RemovePlayListOriginalPicture,
ActivityNames.RemovePlayListSmallPicture,
ActivityNames.DeletePlayListFromDb,
],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildTrack_Unprocessed_NeverRemovesTheSharedPresetPictures()
{
var track = await SeedTrackAsync(new TrackPictures { OriginalName = "original.webp", SmallName = "preset.webp" }, new TrackAudio { OriginalName = "audio.mp3" });
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildTrackAsync(track.Id, track.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[
ActivityNames.MarkTrackAsRemoving,
ActivityNames.RemoveTrackOriginalPicture,
ActivityNames.RemoveTrackOriginalAudio,
ActivityNames.DeleteTrackFromDb,
],
slip.Itinerary.Select(activity => activity.Name));
}
[Fact]
public async Task BuildTrack_Processed_RemovesResizedPicturesAndProcessedAudio()
{
var track = await SeedTrackAsync(
new TrackPictures
{
OriginalName = "original.webp",
SmallName = "s.webp",
MediumName = "m.webp",
LargeName = "l.webp",
ProcessingStatus = ProcessingStatus.Completed
},
new TrackAudio { OriginalName = "audio.mp3", FolderName = "folder", TranscodeStatus = ProcessingStatus.Completed });
await using var database = fixture.CreateDatabase();
var slip = (await CreateBuilder(database).BuildTrackAsync(track.Id, track.OwnerUserId, null, Ct)).Build();
Assert.Equal(
[
ActivityNames.MarkTrackAsRemoving,
ActivityNames.RemoveTrackOriginalPicture,
ActivityNames.RemoveTrackSmallPicture,
ActivityNames.RemoveTrackMediumPicture,
ActivityNames.RemoveTrackLargePicture,
ActivityNames.RemoveTrackOriginalAudio,
ActivityNames.RemoveTrackProcessedAudio,
ActivityNames.DeleteTrackFromDb,
],
slip.Itinerary.Select(activity => activity.Name));
}
private static DeleteRoutingSlipBuilder CreateBuilder(Musify.Application.Contracts.IDatabase database) =>
new(
database,
new TrackConfiguration(),
new AlbumConfiguration(),
new PlayListConfiguration(),
new ApplicationStorageConfiguration { Bucket = "bucket" });
private async Task<User> SeedUserAsync()
{
await using var database = fixture.CreateDatabase();
var name = $"delete-{Guid.NewGuid():N}"[..30];
var user = new User { Id = Random.Shared.NextInt64(1, long.MaxValue), Name = name, NormalizedName = name.ToUpperInvariant() };
await database.Users.AddAsync(user, Ct);
await database.SaveChangesAsync(Ct);
return user;
}
private async Task<Album> SeedAlbumAsync(EntityPictures? pictures)
{
var user = await SeedUserAsync();
await using var database = fixture.CreateDatabase();
var title = $"album-{Guid.NewGuid():N}";
var album = new Album { Title = title, NormalizedTitle = title.ToUpperInvariant(), OwnerUserId = user.Id, Pictures = pictures };
await database.Albums.AddAsync(album, Ct);
await database.SaveChangesAsync(Ct);
return album;
}
private async Task<PlayList> SeedPlayListAsync(EntityPictures? pictures)
{
var user = await SeedUserAsync();
await using var database = fixture.CreateDatabase();
var name = $"pl-{Guid.NewGuid():N}"[..30];
var playList = new PlayList { Name = name, NormalizedName = name.ToUpperInvariant(), OwnerUserId = user.Id, Pictures = pictures };
await database.PlayLists.AddAsync(playList, Ct);
await database.SaveChangesAsync(Ct);
return playList;
}
private async Task<Track> SeedTrackAsync(TrackPictures pictures, TrackAudio audio)
{
var user = await SeedUserAsync();
await using var database = fixture.CreateDatabase();
var title = $"track-{Guid.NewGuid():N}";
var track = new Track
{
Title = title,
NormalizedTitle = title.ToUpperInvariant(),
DurationSeconds = 10,
OwnerUserId = user.Id,
Pictures = pictures,
Audio = audio
};
await database.Tracks.AddAsync(track, Ct);
await database.SaveChangesAsync(Ct);
return track;
}
}