Updated the Channel and related DTOs to incorporate an optional IconImageId property, allowing for the specification of a channel icon for external IPTV players. Modified the UpdateChannelSettings command and its handler to accommodate this new property. Adjusted frontend components to manage the icon image, including selection and display functionality. Updated localization files to support new UI elements related to the IPTV icon. This enhancement improves the user experience by providing a visual representation of channels in IPTV applications.
126 lines
4.8 KiB
C#
126 lines
4.8 KiB
C#
using TeleWave.Application.Streaming.ListPublicChannels;
|
|
using TeleWave.Application.Tests.Support;
|
|
using TeleWave.Domain.Broadcast;
|
|
using TeleWave.Domain.Library;
|
|
using TeleWave.Domain.Media;
|
|
using Xunit;
|
|
|
|
namespace TeleWave.Application.Tests.Streaming;
|
|
|
|
/// <summary>
|
|
/// Витрина зрителя: только включённые каналы, порядок по номеру и обложка того, что идёт прямо
|
|
/// сейчас. Выключенный канал не должен просачиваться в публичную выдачу.
|
|
/// </summary>
|
|
public class ListPublicChannelsTests
|
|
{
|
|
private static readonly DateTimeOffset T0 = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
|
|
|
[Fact]
|
|
public async Task List_ReturnsEnabledChannelsOrderedByNumber()
|
|
{
|
|
var fixture = new TestDb();
|
|
var numbered = Channel.Create("Второй", "two", T0);
|
|
numbered.UpdateTimeSettings(
|
|
2,
|
|
Channel.DefaultUtcOffsetMinutes,
|
|
Channel.DefaultDayStartTime
|
|
);
|
|
var first = Channel.Create("Первый", "one", T0);
|
|
first.UpdateTimeSettings(1, Channel.DefaultUtcOffsetMinutes, Channel.DefaultDayStartTime);
|
|
var unnumbered = Channel.Create("Аврора", "aurora", T0);
|
|
var disabled = Channel.Create("Выключенный", "off", T0);
|
|
|
|
foreach (var channel in new[] { numbered, first, unnumbered })
|
|
channel.UpdateSettings(channel.Name, isEnabled: true, null, null);
|
|
disabled.UpdateSettings("Выключенный", isEnabled: false, null, null);
|
|
|
|
await using (var seed = fixture.New())
|
|
{
|
|
seed.Channels.AddRange(numbered, first, unnumbered, disabled);
|
|
await seed.SaveChangesAsync(CancellationToken.None);
|
|
}
|
|
|
|
await using var db = fixture.New();
|
|
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
|
|
new ListPublicChannelsQuery(),
|
|
CancellationToken.None
|
|
);
|
|
|
|
// Ненумерованный уходит в конец: на телевизоре порядок задаёт номер.
|
|
Assert.Equal(["Первый", "Второй", "Аврора"], channels.Select(c => c.Name).ToArray());
|
|
Assert.Null(channels[^1].Number);
|
|
Assert.All(channels, c => Assert.Null(c.CurrentShowId));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_AddsCurrentProgramCover()
|
|
{
|
|
var fixture = new TestDb();
|
|
var channel = Channel.Create("Первый", "one", T0);
|
|
channel.UpdateSettings("Первый", isEnabled: true, null, null);
|
|
var logoId = Guid.NewGuid();
|
|
channel.UpdateViewerSettings(logoId, LogoCorner.TopRight, 0.5, showClock: true, 0.3);
|
|
|
|
var show = Show.Create("Сейчас в эфире", ShowKind.Series);
|
|
show.SetPosterImage(Guid.NewGuid());
|
|
var asset = MediaAsset.Register("now.mkv", ".mkv", MediaSource.Upload);
|
|
var now = DateTimeOffset.UtcNow;
|
|
var current = ScheduleEntry.Program(
|
|
channel.Id,
|
|
asset.Id,
|
|
now.AddMinutes(-5),
|
|
now.AddMinutes(25),
|
|
show.Id,
|
|
0
|
|
);
|
|
// Прошедшая запись того же канала не должна перебить текущую.
|
|
var past = ScheduleEntry.Program(
|
|
channel.Id,
|
|
asset.Id,
|
|
now.AddHours(-2),
|
|
now.AddHours(-1),
|
|
Guid.NewGuid(),
|
|
0
|
|
);
|
|
|
|
await using (var seed = fixture.New())
|
|
{
|
|
seed.Channels.Add(channel);
|
|
seed.Shows.Add(show);
|
|
seed.MediaAssets.Add(asset);
|
|
seed.ScheduleEntries.AddRange(current, past);
|
|
await seed.SaveChangesAsync(CancellationToken.None);
|
|
}
|
|
|
|
await using var db = fixture.New();
|
|
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
|
|
new ListPublicChannelsQuery(),
|
|
CancellationToken.None
|
|
);
|
|
|
|
var dto = Assert.Single(channels);
|
|
Assert.Equal(show.Id, dto.CurrentShowId);
|
|
Assert.Equal("Сейчас в эфире", dto.CurrentShowName);
|
|
Assert.Equal(show.PosterImageId, dto.CurrentShowPosterImageId);
|
|
Assert.Equal(logoId, dto.LogoImageId);
|
|
Assert.Equal(LogoCorner.TopRight, dto.LogoCorner);
|
|
Assert.Equal(0.5, dto.LogoOpacity);
|
|
Assert.True(dto.ShowClock);
|
|
Assert.Equal(0.3, dto.AnalogFilterStrength);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_WithoutEnabledChannels_ReturnsEmpty()
|
|
{
|
|
var fixture = new TestDb();
|
|
await using var db = fixture.New();
|
|
|
|
var channels = await new ListPublicChannelsQueryHandler(db).Handle(
|
|
new ListPublicChannelsQuery(),
|
|
CancellationToken.None
|
|
);
|
|
|
|
Assert.Empty(channels);
|
|
}
|
|
}
|