Add unit tests for dynamic group mode handling and exclusions
Implemented several unit tests to validate the behavior of dynamic group modes, including the preservation of pinned items when switching to dynamic mode, the dropping of exclusions when reverting to static mode, and the default pinning of new elements in dynamic groups. Additional tests ensure that exclusions are correctly applied and removed, and that static groups refuse exclusions. These tests enhance the coverage and reliability of the group management functionality.
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
using TeleWave.Application.Programming.Groups;
|
||||
using TeleWave.Application.Programming.Groups.GetGroup;
|
||||
using TeleWave.Application.Tests.Support;
|
||||
using TeleWave.Domain.Library;
|
||||
using TeleWave.Domain.Media;
|
||||
using TeleWave.Domain.Programming;
|
||||
using Xunit;
|
||||
|
||||
namespace TeleWave.Application.Tests.Programming;
|
||||
|
||||
/// <summary>
|
||||
/// Карточка группы. Главное свойство — показанное совпадает с тем, что уйдёт в эфир: состав
|
||||
/// считается на месте, а не читается из кэша статистики.
|
||||
/// </summary>
|
||||
public class GetGroupTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task StaticGroup_ReturnsItemsWithIdsAndStats()
|
||||
{
|
||||
var fixture = new TestDb();
|
||||
var asset = ReadyAsset(TimeSpan.FromMinutes(30));
|
||||
var show = Show.Create("Шоу", ShowKind.Series);
|
||||
show.AddEpisode(asset.Id);
|
||||
|
||||
var group = Group.Create("Статическая");
|
||||
group.AddElement(GroupElementKind.Show, show.Id);
|
||||
|
||||
await SeedAsync(fixture, group, [show], [asset]);
|
||||
|
||||
var dto = await GetAsync(fixture, group.Id);
|
||||
|
||||
var item = Assert.Single(dto.Items);
|
||||
// У позиции статической группы есть своя строка — её можно двигать и взвешивать.
|
||||
Assert.NotNull(item.Id);
|
||||
Assert.False(item.Pinned);
|
||||
Assert.Equal("Шоу", item.ElementName);
|
||||
Assert.Equal(1, dto.UnitCount);
|
||||
Assert.Equal(TimeSpan.FromMinutes(30).TotalSeconds, dto.TotalDurationSeconds);
|
||||
Assert.Empty(dto.Excluded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DynamicGroup_ShowsRuleMatchesWithoutItemId()
|
||||
{
|
||||
var fixture = new TestDb();
|
||||
var genre = Genre.Create("Мультфильм", "animation");
|
||||
var byRule = Show.Create("По правилу", ShowKind.Series);
|
||||
byRule.SetGenres([genre.Id]);
|
||||
var pinned = Show.Create("Закреплённое", ShowKind.Single);
|
||||
|
||||
var group = Group.Create("Динамическая");
|
||||
group.SetFilter(new GroupFilter(GenreIds: [genre.Id]).ToJson());
|
||||
group.AddElement(GroupElementKind.Show, pinned.Id);
|
||||
group.SetMode(GroupMode.Dynamic);
|
||||
|
||||
await using (var seed = fixture.New())
|
||||
{
|
||||
seed.Genres.Add(genre);
|
||||
seed.Shows.AddRange(byRule, pinned);
|
||||
seed.Groups.Add(group);
|
||||
await seed.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
var dto = await GetAsync(fixture, group.Id);
|
||||
|
||||
Assert.Equal(GroupMode.Dynamic, dto.Mode);
|
||||
var first = dto.Items[0];
|
||||
Assert.True(first.Pinned);
|
||||
Assert.NotNull(first.Id);
|
||||
|
||||
var second = dto.Items[1];
|
||||
Assert.False(second.Pinned);
|
||||
// Найденному правилом строки в таблице не отвечает — значит, ни веса, ни порядка.
|
||||
Assert.Null(second.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DynamicGroup_ListsExclusionsSeparately()
|
||||
{
|
||||
// Иначе непонятно, почему шоу нет в составе, хотя правило его находит.
|
||||
var fixture = new TestDb();
|
||||
var genre = Genre.Create("Мультфильм", "animation");
|
||||
var dropped = Show.Create("Исключённое", ShowKind.Series);
|
||||
dropped.SetGenres([genre.Id]);
|
||||
|
||||
var group = Group.Create("Динамическая");
|
||||
group.SetFilter(new GroupFilter(GenreIds: [genre.Id]).ToJson());
|
||||
group.SetMode(GroupMode.Dynamic);
|
||||
group.Exclude(GroupElementKind.Show, dropped.Id);
|
||||
|
||||
await using (var seed = fixture.New())
|
||||
{
|
||||
seed.Genres.Add(genre);
|
||||
seed.Shows.Add(dropped);
|
||||
seed.Groups.Add(group);
|
||||
await seed.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
var dto = await GetAsync(fixture, group.Id);
|
||||
|
||||
Assert.Empty(dto.Items);
|
||||
var excluded = Assert.Single(dto.Excluded);
|
||||
Assert.Equal("Исключённое", excluded.ElementName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MissingElement_ShowsDashInsteadOfFailing()
|
||||
{
|
||||
// Элемент мог исчезнуть из библиотеки между чисткой и чтением — экран группы падать не должен.
|
||||
var fixture = new TestDb();
|
||||
var group = Group.Create("Со следом");
|
||||
group.AddElement(GroupElementKind.Show, Guid.NewGuid());
|
||||
await SeedAsync(fixture, group, [], []);
|
||||
|
||||
var dto = await GetAsync(fixture, group.Id);
|
||||
|
||||
Assert.Equal("—", Assert.Single(dto.Items).ElementName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UnknownGroup_ReturnsNotFound()
|
||||
{
|
||||
var fixture = new TestDb();
|
||||
await using var db = fixture.New();
|
||||
|
||||
var result = await Handler(db)
|
||||
.Handle(new GetGroupQuery(Guid.NewGuid()), CancellationToken.None);
|
||||
|
||||
Assert.False(result.IsSuccess);
|
||||
}
|
||||
|
||||
private static MediaAsset ReadyAsset(TimeSpan duration)
|
||||
{
|
||||
var asset = MediaAsset.Register($"{Guid.NewGuid():N}.mkv", ".mkv", MediaSource.Upload);
|
||||
asset.MarkProcessing();
|
||||
asset.MarkReady(
|
||||
new MediaReadyInfo(duration, 2, 900, 1920, 1080, "h264", "aac", "assets/x")
|
||||
);
|
||||
return asset;
|
||||
}
|
||||
|
||||
private static async Task SeedAsync(
|
||||
TestDb fixture,
|
||||
Group group,
|
||||
Show[] shows,
|
||||
MediaAsset[] assets
|
||||
)
|
||||
{
|
||||
await using var seed = fixture.New();
|
||||
seed.MediaAssets.AddRange(assets);
|
||||
seed.Shows.AddRange(shows);
|
||||
seed.Groups.Add(group);
|
||||
await seed.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
private static GetGroupQueryHandler Handler(Infrastructure.Persistence.AppDbContext db) =>
|
||||
new(db, new GroupElementResolver(db), GroupServices.Dynamic(db));
|
||||
|
||||
private static async Task<GroupDto> GetAsync(TestDb fixture, Guid groupId)
|
||||
{
|
||||
await using var db = fixture.New();
|
||||
var result = await Handler(db).Handle(new GetGroupQuery(groupId), CancellationToken.None);
|
||||
Assert.True(result.IsSuccess);
|
||||
return result.Value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user