using TeleWave.Application.Library.ListShows;
using TeleWave.Application.Tests.Support;
using TeleWave.Domain.Library;
using TeleWave.Domain.Media;
using Xunit;
namespace TeleWave.Application.Tests.Library;
///
/// Список библиотеки: он же считает сезоны (номера в модели не хранятся — только в именах файлов)
/// и подставляет названия жанров, поэтому проверяем именно сводку, а не факт выборки.
///
public class ListShowsTests
{
private sealed record Seeded(TestDb Db, Guid ActionGenreId, Guid DramaGenreId, Guid SeriesId);
private static async Task SeedAsync()
{
var fixture = new TestDb();
var action = Genre.Create("Боевик", "action");
var drama = Genre.Create("Драма", "drama");
var series = Show.Create("Сериал", ShowKind.Series);
series.SetGenres([action.Id, drama.Id], action.Id);
series.SetPosterImage(Guid.NewGuid());
var assets = new[]
{
MediaAsset.Register("Serial.S01E01.mkv", ".mkv", MediaSource.Upload),
MediaAsset.Register("Serial.S01E02.mkv", ".mkv", MediaSource.Upload),
MediaAsset.Register("Serial.S02E01.mkv", ".mkv", MediaSource.Upload),
// Имя без метки сезона: серия считается, сезон — нет.
MediaAsset.Register("Serial-bonus.mkv", ".mkv", MediaSource.Upload),
};
foreach (var asset in assets)
series.AddEpisode(asset.Id);
var film = Show.Create("Автофильм", ShowKind.Single);
var bumper = Show.Create("Ролик", ShowKind.Interstitial);
await using var seed = fixture.New();
seed.Genres.AddRange(action, drama);
seed.MediaAssets.AddRange(assets);
seed.Shows.AddRange(series, film, bumper);
await seed.SaveChangesAsync(CancellationToken.None);
return new Seeded(fixture, action.Id, drama.Id, series.Id);
}
[Fact]
public async Task List_ReturnsContentSortedByName_WithoutInterstitials()
{
var seeded = await SeedAsync();
await using var db = seeded.Db.New();
var shows = await new ListShowsQueryHandler(db).Handle(
new ListShowsQuery(),
CancellationToken.None
);
// Ролики-врезки живут на своей странице и в общей библиотеке только мешали бы.
Assert.Equal(new[] { "Автофильм", "Сериал" }, shows.Select(s => s.Name).ToArray());
}
[Fact]
public async Task List_CountsEpisodesAndDistinctSeasons()
{
var seeded = await SeedAsync();
await using var db = seeded.Db.New();
var shows = await new ListShowsQueryHandler(db).Handle(
new ListShowsQuery(),
CancellationToken.None
);
var series = shows.Single(s => s.Id == seeded.SeriesId);
Assert.Equal(4, series.EpisodeCount);
Assert.Equal(2, series.SeasonCount);
Assert.True(series.HasPoster);
Assert.Equal("Боевик", series.PrimaryGenre);
Assert.Equal(new[] { "Драма" }, series.OtherGenres.ToArray());
}
[Fact]
public async Task List_ByGenre_KeepsOnlyShowsWithIt()
{
var seeded = await SeedAsync();
await using var db = seeded.Db.New();
var byDrama = await new ListShowsQueryHandler(db).Handle(
new ListShowsQuery(seeded.DramaGenreId),
CancellationToken.None
);
var byUnknown = await new ListShowsQueryHandler(db).Handle(
new ListShowsQuery(Guid.NewGuid()),
CancellationToken.None
);
// Жанр ищется среди всех, а не только основного.
Assert.Equal(seeded.SeriesId, Assert.Single(byDrama).Id);
Assert.Empty(byUnknown);
}
[Fact]
public async Task List_Interstitials_ReturnsOnlyThem()
{
var seeded = await SeedAsync();
await using var db = seeded.Db.New();
var shows = await new ListShowsQueryHandler(db).Handle(
new ListShowsQuery(Interstitials: true),
CancellationToken.None
);
var only = Assert.Single(shows);
Assert.Equal("Ролик", only.Name);
Assert.Equal(ShowKind.Interstitial, only.Kind);
Assert.Equal(0, only.SeasonCount);
Assert.Null(only.PrimaryGenre);
Assert.False(only.HasPoster);
}
}