mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
7.2 KiB
203 lines
7.2 KiB
using Destructurama; |
|
using ErsatzTV.Core.Domain; |
|
using ErsatzTV.Core.Domain.Filler; |
|
using ErsatzTV.Core.Domain.Scheduling; |
|
using ErsatzTV.Core.Interfaces.Metadata; |
|
using ErsatzTV.Core.Interfaces.Repositories; |
|
using ErsatzTV.Core.Interfaces.Scheduling; |
|
using ErsatzTV.Core.Scheduling; |
|
using ErsatzTV.Core.Tests.Fakes; |
|
using Microsoft.Extensions.Logging; |
|
using NSubstitute; |
|
using NUnit.Framework; |
|
using Serilog; |
|
|
|
namespace ErsatzTV.Core.Tests.Scheduling.ClassicScheduling; |
|
|
|
public abstract class PlayoutBuilderTestBase |
|
{ |
|
[SetUp] |
|
public void SetUp() => CancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token; |
|
|
|
protected readonly ILogger<PlayoutBuilder> Logger; |
|
protected CancellationToken CancellationToken; |
|
|
|
protected PlayoutBuilderTestBase() |
|
{ |
|
Log.Logger = new LoggerConfiguration() |
|
.MinimumLevel.Debug() |
|
.WriteTo.Console() |
|
.Destructure.UsingAttributes() |
|
.CreateLogger(); |
|
|
|
ILoggerFactory loggerFactory = new LoggerFactory().AddSerilog(Log.Logger); |
|
|
|
Logger = loggerFactory.CreateLogger<PlayoutBuilder>(); |
|
} |
|
|
|
protected static DateTimeOffset HoursAfterMidnight(int hours) |
|
{ |
|
DateTimeOffset now = DateTimeOffset.Now; |
|
return now - now.TimeOfDay + TimeSpan.FromHours(hours); |
|
|
|
// // pick a timezone that has DST and a known offset on a specific date |
|
// TimeZoneInfo eastern = TimeZoneInfo.FindSystemTimeZoneById("America/New_York"); |
|
// DateTime date = new DateTime(2025, 11, 2, 0, 0, 0, DateTimeKind.Unspecified); |
|
// DateTimeOffset now = new DateTimeOffset(date, eastern.GetUtcOffset(date)); |
|
// return now.Date + TimeSpan.FromHours(hours); |
|
} |
|
|
|
protected TestData TestDataFloodForItems( |
|
List<MediaItem> mediaItems, |
|
PlaybackOrder playbackOrder, |
|
IConfigElementRepository configMock = null) |
|
{ |
|
var mediaCollection = new Collection |
|
{ |
|
Id = 1, |
|
MediaItems = mediaItems |
|
}; |
|
|
|
IConfigElementRepository configRepo = configMock ?? Substitute.For<IConfigElementRepository>(); |
|
|
|
var collectionRepo = new FakeMediaCollectionRepository(Map((mediaCollection.Id, mediaItems))); |
|
var televisionRepo = new FakeTelevisionRepository(); |
|
IArtistRepository artistRepo = Substitute.For<IArtistRepository>(); |
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory = |
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(); |
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>(); |
|
var builder = new PlayoutBuilder( |
|
configRepo, |
|
collectionRepo, |
|
televisionRepo, |
|
artistRepo, |
|
factory, |
|
localFileSystem, |
|
Logger); |
|
|
|
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, playbackOrder) }; |
|
|
|
var playout = new Playout |
|
{ |
|
Id = 1, |
|
ProgramSchedule = new ProgramSchedule { Items = items }, |
|
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" }, |
|
Items = [], |
|
ProgramScheduleAnchors = [], |
|
ProgramScheduleAlternates = [], |
|
FillGroupIndices = [] |
|
}; |
|
|
|
var referenceData = new PlayoutReferenceData(playout.Channel, Option<Deco>.None, [], [], playout.ProgramSchedule, [], []); |
|
|
|
return new TestData(builder, playout, referenceData); |
|
} |
|
|
|
protected static Movie TestMovie(int id, TimeSpan duration, DateTime aired) => |
|
new() |
|
{ |
|
Id = id, |
|
MovieMetadata = [new MovieMetadata { ReleaseDate = aired }], |
|
MediaVersions = |
|
[ |
|
new MediaVersion |
|
{ |
|
Duration = duration, MediaFiles = [new MediaFile { Path = $"/fake/path/{id}" }] |
|
} |
|
] |
|
}; |
|
|
|
private static ProgramScheduleItem Flood(Collection mediaCollection, PlaybackOrder playbackOrder) => |
|
new ProgramScheduleItemFlood |
|
{ |
|
Id = 1, |
|
Index = 1, |
|
CollectionType = ProgramScheduleItemCollectionType.Collection, |
|
Collection = mediaCollection, |
|
CollectionId = mediaCollection.Id, |
|
StartTime = null, |
|
PlaybackOrder = playbackOrder |
|
}; |
|
|
|
private static ProgramScheduleItem Flood( |
|
SmartCollection smartCollection, |
|
SmartCollection fillerCollection, |
|
PlaybackOrder playbackOrder) => |
|
new ProgramScheduleItemFlood |
|
{ |
|
Id = 1, |
|
Index = 1, |
|
CollectionType = ProgramScheduleItemCollectionType.SmartCollection, |
|
SmartCollection = smartCollection, |
|
SmartCollectionId = smartCollection.Id, |
|
StartTime = null, |
|
PlaybackOrder = playbackOrder, |
|
FallbackFiller = new FillerPreset |
|
{ |
|
Id = 1, |
|
CollectionType = ProgramScheduleItemCollectionType.SmartCollection, |
|
SmartCollection = fillerCollection, |
|
SmartCollectionId = fillerCollection.Id, |
|
FillerKind = FillerKind.Fallback |
|
} |
|
}; |
|
|
|
protected TestData TestDataFloodForSmartCollectionItems( |
|
List<MediaItem> mediaItems, |
|
PlaybackOrder playbackOrder, |
|
IConfigElementRepository configMock = null) |
|
{ |
|
var mediaCollection = new SmartCollection |
|
{ |
|
Id = 1, |
|
Query = "asdf" |
|
}; |
|
|
|
var fillerCollection = new SmartCollection |
|
{ |
|
Id = 2, |
|
Query = "qwerty" |
|
}; |
|
|
|
IConfigElementRepository configRepo = configMock ?? Substitute.For<IConfigElementRepository>(); |
|
|
|
var collectionRepo = new FakeMediaCollectionRepository( |
|
Map( |
|
(mediaCollection.Id, mediaItems), |
|
(fillerCollection.Id, mediaItems.Take(1).ToList()) |
|
) |
|
); |
|
var televisionRepo = new FakeTelevisionRepository(); |
|
IArtistRepository artistRepo = Substitute.For<IArtistRepository>(); |
|
IMultiEpisodeShuffleCollectionEnumeratorFactory factory = |
|
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>(); |
|
ILocalFileSystem localFileSystem = Substitute.For<ILocalFileSystem>(); |
|
var builder = new PlayoutBuilder( |
|
configRepo, |
|
collectionRepo, |
|
televisionRepo, |
|
artistRepo, |
|
factory, |
|
localFileSystem, |
|
Logger); |
|
|
|
var items = new List<ProgramScheduleItem> { Flood(mediaCollection, fillerCollection, playbackOrder) }; |
|
|
|
var playout = new Playout |
|
{ |
|
Id = 1, |
|
ProgramSchedule = new ProgramSchedule { Items = items }, |
|
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" }, |
|
Items = [], |
|
ProgramScheduleAnchors = [], |
|
ProgramScheduleAlternates = [], |
|
FillGroupIndices = [] |
|
}; |
|
|
|
var referenceData = new PlayoutReferenceData(playout.Channel, Option<Deco>.None, [], [], playout.ProgramSchedule, [], []); |
|
|
|
return new TestData(builder, playout, referenceData); |
|
} |
|
|
|
protected record TestData(PlayoutBuilder Builder, Playout Playout, PlayoutReferenceData ReferenceData); |
|
} |