test(api): pin mirror-offset guide behavior; clarify guide end-default wording (#102)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m1s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m57s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped

- Add GetChannelGuideDataHandlerTests coverage for the mirror-channel path:
  asserts programme Start/Stop shift by PlayoutOffset and that the source
  channel's seeded PlayoutItem entities are not mutated, pinning the
  WithPlayoutOffset copy fix.
- ChannelController.GetGuide Swagger description said end defaults to "now
  plus XmltvDaysToBuild"; it actually defaults to start plus that window
  (matters when start is supplied). Reworded and regenerated v1.json.
This commit is contained in:
2026-07-04 01:19:58 +02:00
parent ef024c0a05
commit 0585f4a7f8
3 changed files with 38 additions and 3 deletions
@@ -205,6 +205,41 @@ public class GetChannelGuideDataHandlerTests
(result.End - result.Start).ShouldBe(TimeSpan.FromDays(3)); (result.End - result.Start).ShouldBe(TimeSpan.FromDays(3));
} }
[Test]
public async Task Handle_Should_Shift_Mirror_Channel_Programmes_By_PlayoutOffset_Without_Mutating_Source_Items()
{
PlayoutItem sourceItem = MakeItem(BaseTime, BaseTime.AddHours(1), guideGroup: 1, movieTitle: "Live Show");
var playoutOffset = TimeSpan.FromHours(3);
await using (TvContext context = _db.CreateContext())
{
DomainChannel source = NewChannel("1", "Source", showInEpg: false);
source.Playouts = [MakePlayout(source, PlayoutScheduleKind.Classic, [sourceItem])];
DomainChannel mirror = NewChannel("2", "Mirror", showInEpg: true);
mirror.PlayoutSource = ChannelPlayoutSource.Mirror;
mirror.MirrorSourceChannel = source;
mirror.PlayoutOffset = playoutOffset;
context.Channels.AddRange(source, mirror);
await context.SaveChangesAsync();
}
ChannelGuideResponseModel result = await MakeHandler().Handle(
new GetChannelGuideData(BaseTime, BaseTime.AddDays(1)),
CancellationToken.None);
ChannelGuideProgrammeResponseModel programme = result.Channels.Single(c => c.Number == "2").Programmes.Single();
programme.Title.ShouldBe("Live Show");
programme.Start.ShouldBe(new DateTimeOffset(BaseTime.Add(playoutOffset), TimeSpan.Zero));
programme.Stop.ShouldBe(new DateTimeOffset(BaseTime.AddHours(1).Add(playoutOffset), TimeSpan.Zero));
// the WithPlayoutOffset copy fix: applying the mirror offset must not mutate the source playout's
// own (shared, AsNoTracking) PlayoutItem entities in place.
sourceItem.Start.ShouldBe(BaseTime);
sourceItem.Finish.ShouldBe(BaseTime.AddHours(1));
}
[Test] [Test]
public async Task Handle_Should_Return_Empty_Programmes_For_Channel_Without_Playout() public async Task Handle_Should_Return_Empty_Programmes_For_Channel_Without_Playout()
{ {
@@ -26,8 +26,8 @@ public class ChannelController(ChannelWriter<IBackgroundServiceRequest> workerCh
[Tags("Channels")] [Tags("Channels")]
[EndpointSummary("Get the JSON channel guide (EPG)")] [EndpointSummary("Get the JSON channel guide (EPG)")]
[EndpointDescription( [EndpointDescription(
"Returns per-channel programme arrays for the EPG grid. When omitted, start defaults to now " + "Returns per-channel programme arrays for the EPG grid. When omitted, start defaults to now, " +
"and end defaults to now plus the configured XmltvDaysToBuild window.")] "and end defaults to start plus the configured XmltvDaysToBuild window.")]
[EndpointGroupName("general")] [EndpointGroupName("general")]
[ProducesResponseType(typeof(ChannelGuideResponseModel), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ChannelGuideResponseModel), StatusCodes.Status200OK)]
public async Task<ChannelGuideResponseModel> GetGuide( public async Task<ChannelGuideResponseModel> GetGuide(
+1 -1
View File
@@ -221,7 +221,7 @@
"Channels" "Channels"
], ],
"summary": "Get the JSON channel guide (EPG)", "summary": "Get the JSON channel guide (EPG)",
"description": "Returns per-channel programme arrays for the EPG grid. When omitted, start defaults to now and end defaults to now plus the configured XmltvDaysToBuild window.", "description": "Returns per-channel programme arrays for the EPG grid. When omitted, start defaults to now, and end defaults to start plus the configured XmltvDaysToBuild window.",
"parameters": [ "parameters": [
{ {
"name": "start", "name": "start",