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
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>
51 lines
2.3 KiB
C#
51 lines
2.3 KiB
C#
using ErsatzTV.Core.Api.Channels;
|
|
using ErsatzTV.Core.Domain;
|
|
using ErsatzTV.Infrastructure.Data;
|
|
using ErsatzTV.Infrastructure.Data.Repositories;
|
|
using ErsatzTV.Tests.Support;
|
|
using NUnit.Framework;
|
|
using Shouldly;
|
|
|
|
namespace ErsatzTV.Tests.Application.Channels;
|
|
|
|
[TestFixture]
|
|
public class ChannelRepositoryHealthTests
|
|
{
|
|
private static readonly DateTime Now = new(2026, 7, 23, 12, 0, 0, DateTimeKind.Utc);
|
|
private InMemoryTvContext _db = null!;
|
|
|
|
[SetUp]
|
|
public async Task SetUp() => _db = await InMemoryTvContext.CreateAsync();
|
|
|
|
[TearDown]
|
|
public async Task TearDown() => await _db.DisposeAsync();
|
|
|
|
[Test]
|
|
public async Task GetPlayoutUpcomingHealth_Counts_Upcoming_And_Broken()
|
|
{
|
|
await using (TvContext context = _db.CreateContext())
|
|
{
|
|
var normal = new Movie { Id = 1, State = MediaItemState.Normal };
|
|
var missing = new Movie { Id = 2, State = MediaItemState.FileNotFound };
|
|
var playout1 = new Playout { Id = 10, ChannelId = 1, Items = [] };
|
|
var playout2 = new Playout { Id = 11, ChannelId = 1, Items = [] };
|
|
context.Movies.AddRange(normal, missing);
|
|
context.Playouts.AddRange(playout1, playout2);
|
|
context.PlayoutItems.AddRange(
|
|
new PlayoutItem { Id = 100, PlayoutId = 10, MediaItemId = 1, Start = Now, Finish = Now.AddHours(1), ChapterTitle = "" },
|
|
new PlayoutItem { Id = 101, PlayoutId = 10, MediaItemId = 2, Start = Now.AddHours(1), Finish = Now.AddHours(2), ChapterTitle = "" },
|
|
new PlayoutItem { Id = 102, PlayoutId = 10, MediaItemId = 1, Start = Now.AddHours(-2), Finish = Now.AddHours(-1), ChapterTitle = "" }, // past — excluded
|
|
new PlayoutItem { Id = 103, PlayoutId = 11, MediaItemId = 1, Start = Now.AddHours(-3), Finish = Now.AddHours(-2), ChapterTitle = "" }); // playout2 all past
|
|
await context.SaveChangesAsync();
|
|
}
|
|
|
|
var repo = new ChannelRepository(_db.Factory);
|
|
Dictionary<int, PlayoutUpcoming> result =
|
|
await repo.GetPlayoutUpcomingHealth([10, 11], Now, CancellationToken.None);
|
|
|
|
result[10].TotalUpcoming.ShouldBe(2);
|
|
result[10].BrokenUpcoming.ShouldBe(1);
|
|
result.ContainsKey(11).ShouldBeFalse(); // no upcoming rows -> absent from dict
|
|
}
|
|
}
|