Files
ersatztv/ErsatzTV.Tests/Application/Channels/GetAllChannelsForApiHandlerHealthTests.cs
T
timothyandtimothy 65c0e09179
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (push) Has been skipped
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (push) Has been skipped
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 15m30s
Build ErsatzTV Image / Functional E2E (curl contracts) (push) Successful in 15m48s
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 7m32s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
feat(415): per-channel fault detection — server-derived health object + Problems filter (#581)
Closes #415. Server-derived health object on the channel list + detail DTOs (built-timeline detection, kind-agnostic across all 5 PlayoutScheduleKind; assessable gate keyed to the owning channel's mode), single "Problems" SPA filter with per-fault badges. Supersedes #72's api.channel-health-signal decision.

Co-authored-by: Timothy <timothy.look@gmail.com>
Co-committed-by: Timothy <timothy.look@gmail.com>
2026-07-23 20:45:19 +00:00

52 lines
1.9 KiB
C#

using ErsatzTV.Application.Channels;
using ErsatzTV.Core.Api.Channels;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using NSubstitute;
using NUnit.Framework;
using Shouldly;
namespace ErsatzTV.Tests.Application.Channels;
[TestFixture]
public class GetAllChannelsForApiHandlerHealthTests
{
[Test]
public async Task Populates_Health_From_Aggregate()
{
var channel = new Channel(Guid.NewGuid())
{
Id = 1, Number = "1", Name = "News", Group = "ETV", IsEnabled = true,
StreamingMode = StreamingMode.HttpLiveStreamingDirect,
PlayoutSource = ChannelPlayoutSource.Generated,
PlayoutMode = ChannelPlayoutMode.Continuous,
Artwork = [],
FFmpegProfile = new FFmpegProfile { Name = "P" },
Playouts =
[
new Playout
{
Id = 10,
BuildStatus = new PlayoutBuildStatus
{
PlayoutId = 10, Success = true,
LastBuild = new DateTimeOffset(2026, 7, 23, 0, 0, 0, TimeSpan.Zero)
}
}
]
};
var repo = Substitute.For<IChannelRepository>();
repo.GetAll(Arg.Any<CancellationToken>()).Returns([channel]);
repo.GetPlayoutUpcomingHealth(Arg.Any<IReadOnlyCollection<int>>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>())
.Returns(new Dictionary<int, PlayoutUpcoming> { [10] = new(6, 2) });
var handler = new GetAllChannelsForApiHandler(repo);
List<ChannelResponseModel> result = await handler.Handle(new GetAllChannelsForApi(), CancellationToken.None);
result[0].Health.Status.ShouldBe(ChannelHealthStatus.Problems);
result[0].Health.Faults.ShouldContain(ChannelFault.BrokenSource);
result[0].Health.BrokenSourceItemCount.ShouldBe(2);
}
}