Files
TeleWave/backend/tests/TeleWave.Application.Tests/Programming/GetGroupTests.cs
T
Leonid Pershin 375e0a810b
ci / build-backend (push) Successful in 1m36s
ci / build-frontend (push) Successful in 52s
ci / tests (push) Successful in 2m3s
ci / sonar (push) Successful in 6m21s
Refactor group mode switching logic to ensure proper list management
Updated the Group and UpdateGroupCommandHandler classes to clarify the behavior of group mode switching. The transition to dynamic mode now clears the existing item list to prevent old items from interfering with the new rule-based composition. Enhanced documentation and comments to explain the implications of mode changes. Updated tests to reflect the new behavior, ensuring that the group correctly handles item lists during mode transitions. Localization strings were also updated to inform users about the changes in item management during mode switching.
2026-07-31 04:22:36 +03:00

168 lines
6.2 KiB
C#

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.SetMode(GroupMode.Dynamic);
// Закрепляют уже в динамическом режиме: там список — это поправки к правилу.
group.AddElement(GroupElementKind.Show, pinned.Id);
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;
}
}