From aeda5050d30fd02f602ed035127bac56a66655c0 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:26:49 -0500 Subject: [PATCH] nvidia decoder fixes (#2041) * replace FluentAssertions with Shouldly * fix song transcoding tests * only specify hwaccel when hardware decode is required * update changelog --- CHANGELOG.md | 1 + .../Domain/PlayoutItemTests.cs | 6 +- .../Emby/EmbyPathReplacementServiceTests.cs | 22 +- .../ErsatzTV.Core.Tests.csproj | 2 +- .../FFmpegPlaybackSettingsCalculatorTests.cs | 134 +-- .../FFmpeg/FFmpegStreamSelectorTests.cs | 14 +- .../FFmpeg/HlsPlaylistFilterTests.cs | 38 +- .../FFmpeg/WatermarkCalculatorTests.cs | 4 +- .../Iptv/ChannelIdentifierTests.cs | 6 +- .../JellyfinPathReplacementServiceTests.cs | 24 +- .../Jellyfin/JellyfinUrlTests.cs | 14 +- .../Metadata/FallbackMetadataProviderTests.cs | 22 +- .../Plex/PlexPathReplacementServiceTests.cs | 20 +- .../BlockPlayoutChangeDetectionTests.cs | 8 +- .../BlockScheduling/EffectiveBlockTests.cs | 18 +- .../Scheduling/ChronologicalContentTests.cs | 18 +- .../Scheduling/CustomOrderContentTests.cs | 14 +- .../MultiPartEpisodeGrouperTests.cs | 32 +- .../Scheduling/PlaylistEnumeratorTests.cs | 6 +- .../Scheduling/PlayoutBuilderTests.cs | 1004 ++++++++--------- .../PlayoutModeSchedulerBaseTests.cs | 66 +- .../PlayoutModeSchedulerDurationTests.cs | 686 +++++------ .../PlayoutModeSchedulerFloodTests.cs | 910 +++++++-------- .../PlayoutModeSchedulerMultipleTests.cs | 504 ++++----- .../PlayoutModeSchedulerOneTests.cs | 464 ++++---- .../PlayoutTemplateSelectorTests.cs | 38 +- .../Scheduling/RandomizedContentTests.cs | 16 +- .../Scheduling/SeasonEpisodeContentTests.cs | 18 +- .../Scheduling/ShuffledContentTests.cs | 26 +- .../Vaapi/VaapiCapabilityParserTests.cs | 12 +- .../ErsatzTV.FFmpeg.Tests.csproj | 2 +- .../Filter/WatermarkOpacityFilterTests.cs | 6 +- .../PipelineBuilderBaseTests.cs | 42 +- .../Pipeline/NvidiaPipelineBuilder.cs | 15 +- .../Caching/CachingSearchRepositoryTests.cs | 6 +- .../ErsatzTV.Infrastructure.Tests.csproj | 2 +- .../Metadata/LocalStatisticsProviderTests.cs | 4 +- .../Search/SearchQueryParserTests.cs | 4 +- .../Core/FFmpeg/TranscodingTests.cs | 72 +- .../Metadata/LocalSubtitlesProviderTests.cs | 34 +- .../Core/Metadata/MovieFolderScannerTests.cs | 28 +- .../Core/Metadata/Nfo/ArtistNfoReaderTests.cs | 38 +- .../Metadata/Nfo/EpisodeNfoReaderTests.cs | 128 +-- .../Core/Metadata/Nfo/MovieNfoReaderTests.cs | 50 +- .../Metadata/Nfo/MusicVideoNfoReaderTests.cs | 44 +- .../Metadata/Nfo/OtherVideoNfoReaderTests.cs | 50 +- .../Core/Metadata/Nfo/ShowNfoReaderTests.cs | 42 +- .../ErsatzTV.Scanner.Tests.csproj | 8 +- .../Resources/song_album_cover_512.png | Bin 0 -> 171151 bytes 49 files changed, 2365 insertions(+), 2357 deletions(-) create mode 100644 ErsatzTV.Scanner.Tests/Resources/song_album_cover_512.png diff --git a/CHANGELOG.md b/CHANGELOG.md index c41c0847..880e0dc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Use cache busting to avoid UI errors after upgrading the MudBlazor library - Fix multi-variant playlist to report more accurate `BANDWIDTH` value based on ffmpeg profile - Fix detecting NVIDIA capabilities on Blackwell GPUs +- Fix decoder selection in NVIDIA pipeline ## [25.1.0] - 2025-01-10 ### Added diff --git a/ErsatzTV.Core.Tests/Domain/PlayoutItemTests.cs b/ErsatzTV.Core.Tests/Domain/PlayoutItemTests.cs index 1d728957..61b56df1 100644 --- a/ErsatzTV.Core.Tests/Domain/PlayoutItemTests.cs +++ b/ErsatzTV.Core.Tests/Domain/PlayoutItemTests.cs @@ -1,5 +1,5 @@ using ErsatzTV.Core.Domain; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Domain; @@ -18,7 +18,7 @@ public class PlayoutItemTests string actual = item.GetDisplayDuration(); - actual.Should().Be("3:05:04"); + actual.ShouldBe("3:05:04"); } [Test] @@ -32,6 +32,6 @@ public class PlayoutItemTests string actual = item.GetDisplayDuration(); - actual.Should().Be("27:05:04"); + actual.ShouldBe("27:05:04"); } } diff --git a/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs index 81e4bde8..89a0e4fc 100644 --- a/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Emby/EmbyPathReplacementServiceTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Emby; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.FFmpeg.Runtime; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -42,7 +42,7 @@ public class EmbyPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -74,7 +74,7 @@ public class EmbyPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -98,7 +98,7 @@ public class EmbyPathReplacementServiceTests @"\\192.168.1.100\Something\Some Shared Folder", @"C:\mnt\something else\Some Shared Folder"); - result.Should().Be(@"C:\mnt\something else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\mnt\something else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -130,7 +130,7 @@ public class EmbyPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -162,7 +162,7 @@ public class EmbyPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -194,7 +194,7 @@ public class EmbyPathReplacementServiceTests 0, @"\\SERVERNAME\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -226,7 +226,7 @@ public class EmbyPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -258,7 +258,7 @@ public class EmbyPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -290,7 +290,7 @@ public class EmbyPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -322,6 +322,6 @@ public class EmbyPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/Some Movie/Some Movie.mkv"); } } diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj index 7a67ce2e..b714f940 100644 --- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj +++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj @@ -9,7 +9,6 @@ - @@ -27,6 +26,7 @@ + diff --git a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs index 97413780..4de5a53f 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs @@ -1,7 +1,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.FFmpeg; @@ -32,7 +32,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.FormatFlags.Should().NotContain("+genpts"); + actual.FormatFlags.ShouldNotContain("+genpts"); } [Test] @@ -57,7 +57,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ThreadCount.Should().Be(7); + actual.ThreadCount.ShouldBe(7); } [Test] @@ -78,7 +78,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ThreadCount.Should().Be(7); + actual.ThreadCount.ShouldBe(7); } [Test] @@ -100,8 +100,8 @@ public class FFmpegPlaybackSettingsCalculatorTests None); string[] expected = { "+genpts", "+discardcorrupt", "+igndts" }; - actual.FormatFlags.Count.Should().Be(expected.Length); - actual.FormatFlags.Should().Contain(expected); + actual.FormatFlags.Count.ShouldBe(expected.Length); + expected.ShouldBeSubsetOf(actual.FormatFlags); } [Test] @@ -123,8 +123,8 @@ public class FFmpegPlaybackSettingsCalculatorTests None); string[] expected = { "+genpts", "+discardcorrupt", "+igndts" }; - actual.FormatFlags.Count.Should().Be(expected.Length); - actual.FormatFlags.Should().Contain(expected); + actual.FormatFlags.Count.ShouldBe(expected.Length); + expected.ShouldBeSubsetOf(actual.FormatFlags); } [Test] @@ -145,7 +145,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.RealtimeOutput.Should().BeTrue(); + actual.RealtimeOutput.ShouldBeTrue(); } [Test] @@ -166,7 +166,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.RealtimeOutput.Should().BeTrue(); + actual.RealtimeOutput.ShouldBeTrue(); } [Test] @@ -189,8 +189,8 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.StreamSeek.IsSome.Should().BeTrue(); - actual.StreamSeek.IfNone(TimeSpan.Zero).Should().Be(TimeSpan.FromMinutes(5)); + actual.StreamSeek.IsSome.ShouldBeTrue(); + actual.StreamSeek.IfNone(TimeSpan.Zero).ShouldBe(TimeSpan.FromMinutes(5)); } [Test] @@ -213,8 +213,8 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.StreamSeek.IsSome.Should().BeTrue(); - actual.StreamSeek.IfNone(TimeSpan.Zero).Should().Be(TimeSpan.FromMinutes(5)); + actual.StreamSeek.IsSome.ShouldBeTrue(); + actual.StreamSeek.IfNone(TimeSpan.Zero).ShouldBe(TimeSpan.FromMinutes(5)); } [Test] @@ -241,7 +241,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); + actual.ScaledSize.IsNone.ShouldBeTrue(); } [Test] @@ -268,7 +268,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); + actual.ScaledSize.IsNone.ShouldBeTrue(); } [Test] @@ -295,8 +295,8 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); } [Test] @@ -323,8 +323,8 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeTrue(); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeTrue(); } [Test] @@ -351,9 +351,9 @@ public class FFmpegPlaybackSettingsCalculatorTests None); IDisplaySize scaledSize = actual.ScaledSize.IfNone(new MediaVersion { Width = 0, Height = 0 }); - scaledSize.Width.Should().Be(1280); - scaledSize.Height.Should().Be(554); - actual.PadToDesiredResolution.Should().BeTrue(); + scaledSize.Width.ShouldBe(1280); + scaledSize.Height.ShouldBe(554); + actual.PadToDesiredResolution.ShouldBeTrue(); } [Test] @@ -381,9 +381,9 @@ public class FFmpegPlaybackSettingsCalculatorTests None); IDisplaySize scaledSize = actual.ScaledSize.IfNone(new MediaVersion { Width = 0, Height = 0 }); - scaledSize.Width.Should().Be(1280); - scaledSize.Height.Should().Be(976); - actual.PadToDesiredResolution.Should().BeFalse(); + scaledSize.Width.ShouldBe(1280); + scaledSize.Height.ShouldBe(976); + actual.PadToDesiredResolution.ShouldBeFalse(); } [Test] @@ -411,9 +411,9 @@ public class FFmpegPlaybackSettingsCalculatorTests None); IDisplaySize scaledSize = actual.ScaledSize.IfNone(new MediaVersion { Width = 0, Height = 0 }); - scaledSize.Width.Should().Be(1694); - scaledSize.Height.Should().Be(720); - actual.PadToDesiredResolution.Should().BeFalse(); + scaledSize.Width.ShouldBe(1694); + scaledSize.Height.ShouldBe(720); + actual.PadToDesiredResolution.ShouldBeFalse(); } [Test] @@ -440,8 +440,8 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); } @@ -470,9 +470,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeTrue(); - actual.VideoFormat.Should().Be(FFmpegProfileVideoFormat.H264); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeTrue(); + actual.VideoFormat.ShouldBe(FFmpegProfileVideoFormat.H264); } [Test] @@ -502,9 +502,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); - actual.VideoFormat.Should().Be(FFmpegProfileVideoFormat.H264); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); + actual.VideoFormat.ShouldBe(FFmpegProfileVideoFormat.H264); } [Test] @@ -533,9 +533,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); - actual.VideoFormat.Should().Be(FFmpegProfileVideoFormat.Copy); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); + actual.VideoFormat.ShouldBe(FFmpegProfileVideoFormat.Copy); } [Test] @@ -564,9 +564,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); - actual.VideoFormat.Should().Be(FFmpegProfileVideoFormat.H264); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); + actual.VideoFormat.ShouldBe(FFmpegProfileVideoFormat.H264); } [Test] @@ -594,9 +594,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeTrue(); - actual.VideoBitrate.IfNone(0).Should().Be(2525); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeTrue(); + actual.VideoBitrate.IfNone(0).ShouldBe(2525); } [Test] @@ -625,9 +625,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); - actual.VideoBitrate.IfNone(0).Should().Be(2525); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); + actual.VideoBitrate.IfNone(0).ShouldBe(2525); } [Test] @@ -655,9 +655,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeTrue(); - actual.VideoBufferSize.IfNone(0).Should().Be(2525); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeTrue(); + actual.VideoBufferSize.IfNone(0).ShouldBe(2525); } [Test] @@ -686,9 +686,9 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.ScaledSize.IsNone.Should().BeTrue(); - actual.PadToDesiredResolution.Should().BeFalse(); - actual.VideoBufferSize.IfNone(0).Should().Be(2525); + actual.ScaledSize.IsNone.ShouldBeTrue(); + actual.PadToDesiredResolution.ShouldBeFalse(); + actual.VideoBufferSize.IfNone(0).ShouldBe(2525); } [Test] @@ -712,7 +712,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioFormat.Should().Be(FFmpegProfileAudioFormat.Aac); + actual.AudioFormat.ShouldBe(FFmpegProfileAudioFormat.Aac); } [Test] @@ -736,7 +736,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioFormat.Should().Be(FFmpegProfileAudioFormat.Aac); + actual.AudioFormat.ShouldBe(FFmpegProfileAudioFormat.Aac); } [Test] @@ -760,7 +760,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioFormat.Should().Be(FFmpegProfileAudioFormat.Copy); + actual.AudioFormat.ShouldBe(FFmpegProfileAudioFormat.Copy); } [Test] @@ -785,7 +785,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioBitrate.IfNone(0).Should().Be(2424); + actual.AudioBitrate.IfNone(0).ShouldBe(2424); } [Test] @@ -810,7 +810,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioBufferSize.IfNone(0).Should().Be(2424); + actual.AudioBufferSize.IfNone(0).ShouldBe(2424); } [Test] @@ -835,7 +835,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioChannels.IfNone(0).Should().Be(6); + actual.AudioChannels.IfNone(0).ShouldBe(6); } [Test] @@ -860,7 +860,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioSampleRate.IfNone(0).Should().Be(48); + actual.AudioSampleRate.IfNone(0).ShouldBe(48); } [Test] @@ -884,7 +884,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioChannels.IfNone(0).Should().Be(6); + actual.AudioChannels.IfNone(0).ShouldBe(6); } [Test] @@ -908,7 +908,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioSampleRate.IfNone(0).Should().Be(48); + actual.AudioSampleRate.IfNone(0).ShouldBe(48); } [Test] @@ -938,7 +938,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.AudioDuration.IfNone(TimeSpan.MinValue).Should().Be(TimeSpan.FromMinutes(2)); + actual.AudioDuration.IfNone(TimeSpan.MinValue).ShouldBe(TimeSpan.FromMinutes(2)); } [Test] @@ -962,7 +962,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.NormalizeLoudnessMode.Should().Be(NormalizeLoudnessMode.LoudNorm); + actual.NormalizeLoudnessMode.ShouldBe(NormalizeLoudnessMode.LoudNorm); } } @@ -988,7 +988,7 @@ public class FFmpegPlaybackSettingsCalculatorTests false, None); - actual.HardwareAcceleration.Should().Be(HardwareAccelerationKind.Qsv); + actual.HardwareAcceleration.ShouldBe(HardwareAccelerationKind.Qsv); } } diff --git a/ErsatzTV.Core.Tests/FFmpeg/FFmpegStreamSelectorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/FFmpegStreamSelectorTests.cs index bbd3095c..94247074 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/FFmpegStreamSelectorTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/FFmpegStreamSelectorTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Infrastructure.Scripting; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -64,10 +64,10 @@ public class FFmpegStreamSelectorTests Substitute.For>()); Option selectedStream = await selector.SelectAudioStream(audioVersion, StreamingMode.TransportStream, channel, "jpn", "Whatever"); - selectedStream.IsSome.Should().BeTrue(); + selectedStream.IsSome.ShouldBeTrue(); foreach (MediaStream stream in selectedStream) { - stream.Language.Should().Be("ja"); + stream.Language.ShouldBe("ja"); } } @@ -119,10 +119,10 @@ public class FFmpegStreamSelectorTests Substitute.For>()); Option selectedStream = await selector.SelectAudioStream(audioVersion, StreamingMode.TransportStream, channel, null, channel.PreferredAudioTitle); - selectedStream.IsSome.Should().BeTrue(); + selectedStream.IsSome.ShouldBeTrue(); foreach (MediaStream stream in selectedStream) { - stream.Language.Should().Be("ja"); + stream.Language.ShouldBe("ja"); } } @@ -166,10 +166,10 @@ public class FFmpegStreamSelectorTests channel, "heb", ChannelSubtitleMode.Any); - selectedStream.IsSome.Should().BeTrue(); + selectedStream.IsSome.ShouldBeTrue(); foreach (Subtitle stream in selectedStream) { - stream.Language.Should().Be("he"); + stream.Language.ShouldBe("he"); } } } diff --git a/ErsatzTV.Core.Tests/FFmpeg/HlsPlaylistFilterTests.cs b/ErsatzTV.Core.Tests/FFmpeg/HlsPlaylistFilterTests.cs index 0a2f816f..7be63fe4 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/HlsPlaylistFilterTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/HlsPlaylistFilterTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.FFmpeg; using ErsatzTV.Core.Interfaces.FFmpeg; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -42,9 +42,9 @@ live001139.ts").Split(Environment.NewLine); TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(-30), input); - result.PlaylistStart.Should().Be(start); - result.Sequence.Should().Be(1137); - result.Playlist.Should().Be( + result.PlaylistStart.ShouldBe(start); + result.Sequence.ShouldBe(1137); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 @@ -87,9 +87,9 @@ live001139.ts").Split(Environment.NewLine); TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(-30), input, 2); - result.PlaylistStart.Should().Be(start); - result.Sequence.Should().Be(1137); - result.Playlist.Should().Be( + result.PlaylistStart.ShouldBe(start); + result.Sequence.ShouldBe(1137); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 @@ -134,9 +134,9 @@ live001139.ts").Split(Environment.NewLine); int.MaxValue, true); - result.PlaylistStart.Should().Be(start); - result.Sequence.Should().Be(1137); - result.Playlist.Should().Be( + result.PlaylistStart.ShouldBe(start); + result.Sequence.ShouldBe(1137); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 @@ -180,9 +180,9 @@ live001139.ts").Split(Environment.NewLine); TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(6), input, 1); - result.PlaylistStart.Should().Be(start.AddSeconds(8)); - result.Sequence.Should().Be(1139); - result.Playlist.Should().Be( + result.PlaylistStart.ShouldBe(start.AddSeconds(8)); + result.Sequence.ShouldBe(1139); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 @@ -220,9 +220,9 @@ live001139.ts").Split(Environment.NewLine); TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(6), input); - result.PlaylistStart.Should().Be(start); - result.Sequence.Should().Be(1137); - result.Playlist.Should().Be( + result.PlaylistStart.ShouldBe(start); + result.Sequence.ShouldBe(1137); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 @@ -508,9 +508,9 @@ live000082.ts").Split(Environment.NewLine); TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(220), input); - // result.PlaylistStart.Should().Be(start); - result.Sequence.Should().Be(56); - result.Playlist.Should().Be( + // result.PlaylistStart.ShouldBe(start); + result.Sequence.ShouldBe(56); + result.Playlist.ShouldBe( NormalizeLineEndings( @"#EXTM3U #EXT-X-VERSION:6 diff --git a/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs index 5190324e..ed967a79 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs @@ -1,5 +1,5 @@ using ErsatzTV.Core.FFmpeg; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.FFmpeg; @@ -18,6 +18,6 @@ public class WatermarkCalculatorTests 15, 10); - actual.Should().HaveCount(0); + actual.Count.ShouldBe(0); } } diff --git a/ErsatzTV.Core.Tests/Iptv/ChannelIdentifierTests.cs b/ErsatzTV.Core.Tests/Iptv/ChannelIdentifierTests.cs index 1829eca2..8d28f23c 100644 --- a/ErsatzTV.Core.Tests/Iptv/ChannelIdentifierTests.cs +++ b/ErsatzTV.Core.Tests/Iptv/ChannelIdentifierTests.cs @@ -1,5 +1,5 @@ using ErsatzTV.Core.Iptv; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Iptv; @@ -16,7 +16,7 @@ public class ChannelIdentifierTests public void TestLegacy(string channelNumber, string expected) { string actual = ChannelIdentifier.LegacyFromNumber(channelNumber); - actual.Should().Be(expected); + actual.ShouldBe(expected); } [TestCase("1.23", "C1.23.150.ersatztv.org")] @@ -28,6 +28,6 @@ public class ChannelIdentifierTests public void TestNew(string channelNumber, string expected) { string actual = ChannelIdentifier.FromNumber(channelNumber); - actual.Should().Be(expected); + actual.ShouldBe(expected); } } diff --git a/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs index 6aaf9b75..29e32d9e 100644 --- a/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Jellyfin/JellyfinPathReplacementServiceTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Jellyfin; using ErsatzTV.FFmpeg.Runtime; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -42,7 +42,7 @@ public class JellyfinPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -74,7 +74,7 @@ public class JellyfinPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -98,7 +98,7 @@ public class JellyfinPathReplacementServiceTests @"\\192.168.1.100\Something\Some Shared Folder", @"C:\mnt\something else\Some Shared Folder"); - result.Should().Be(@"C:\mnt\something else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\mnt\something else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -130,7 +130,7 @@ public class JellyfinPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -162,7 +162,7 @@ public class JellyfinPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -194,7 +194,7 @@ public class JellyfinPathReplacementServiceTests 0, @"\\SERVERNAME\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -226,7 +226,7 @@ public class JellyfinPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -258,7 +258,7 @@ public class JellyfinPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -290,7 +290,7 @@ public class JellyfinPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -322,7 +322,7 @@ public class JellyfinPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -354,6 +354,6 @@ public class JellyfinPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/Some Movie/Some Movie.mkv"); } } diff --git a/ErsatzTV.Core.Tests/Jellyfin/JellyfinUrlTests.cs b/ErsatzTV.Core.Tests/Jellyfin/JellyfinUrlTests.cs index ca6173f9..31a0f9d0 100644 --- a/ErsatzTV.Core.Tests/Jellyfin/JellyfinUrlTests.cs +++ b/ErsatzTV.Core.Tests/Jellyfin/JellyfinUrlTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Jellyfin; -using FluentAssertions; +using Shouldly; using Flurl; using NUnit.Framework; @@ -23,7 +23,7 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server/Items/2/Images/3?tag=4"); } [Test] @@ -41,7 +41,7 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server/Items/2/Images/3?tag=4"); } [Test] @@ -59,7 +59,7 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server:1000/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server:1000/Items/2/Images/3?tag=4"); } [Test] @@ -77,7 +77,7 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server:1000/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server:1000/Items/2/Images/3?tag=4"); } [Test] @@ -95,7 +95,7 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server/jellyfin/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server/jellyfin/Items/2/Images/3?tag=4"); } [Test] @@ -113,6 +113,6 @@ public class JellyfinUrlTests Url url = JellyfinUrl.ForArtwork(Some(mediaSource), artwork); - url.ToString().Should().Be("https://some.jellyfin.server/jellyfin/Items/2/Images/3?tag=4"); + url.ToString().ShouldBe("https://some.jellyfin.server/jellyfin/Items/2/Images/3?tag=4"); } } diff --git a/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs b/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs index 447515b9..0f2353f1 100644 --- a/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs +++ b/ErsatzTV.Core.Tests/Metadata/FallbackMetadataProviderTests.cs @@ -1,7 +1,7 @@ using Bugsnag; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Metadata; -using FluentAssertions; +using Shouldly; using NSubstitute; using NUnit.Framework; @@ -65,10 +65,10 @@ public class FallbackMetadataProviderTests } }); - metadata.Count.Should().Be(1); + metadata.Count.ShouldBe(1); // TODO: how can we test season number? do we need to? - // metadata.Season.Should().Be(season); - metadata.Head().EpisodeNumber.Should().Be(episode); + // metadata.Season.ShouldBe(season); + metadata.Head().EpisodeNumber.ShouldBe(episode); } [TestCase("Awesome Show - S01_BLAH.mkv", 0)] @@ -91,8 +91,8 @@ public class FallbackMetadataProviderTests } }); - metadata.Count.Should().Be(1); - metadata.Head().EpisodeNumber.Should().Be(episode); + metadata.Count.ShouldBe(1); + metadata.Head().EpisodeNumber.ShouldBe(episode); } [Test] @@ -122,8 +122,8 @@ public class FallbackMetadataProviderTests } }); - metadata.Count.Should().Be(2); - metadata.Map(m => m.EpisodeNumber).Should().BeEquivalentTo(new[] { episode1, episode2 }); + metadata.Count.ShouldBe(2); + metadata.Map(m => m.EpisodeNumber).ShouldBe([episode1, episode2]); } [Test] @@ -147,8 +147,8 @@ public class FallbackMetadataProviderTests } }); - metadata.Should().NotBeNull(); - metadata.Title.Should().Be(expectedTitle); + metadata.ShouldNotBeNull(); + metadata.Title.ShouldBe(expectedTitle); } [Test] @@ -172,6 +172,6 @@ public class FallbackMetadataProviderTests public void GetSeasonNumberForFolder_ShouldHandleVariousFormats(string folder, int? season) { Option actual = _fallbackMetadataProvider.GetSeasonNumberForFolder(folder); - actual.Should>().Be(Optional(season)); + actual.ShouldBe(Optional(season)); } } diff --git a/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs b/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs index 015ca1ac..b8ef15ad 100644 --- a/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs +++ b/ErsatzTV.Core.Tests/Plex/PlexPathReplacementServiceTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Plex; using ErsatzTV.FFmpeg.Runtime; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -42,7 +42,7 @@ public class PlexPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -74,7 +74,7 @@ public class PlexPathReplacementServiceTests 0, @"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -106,7 +106,7 @@ public class PlexPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -138,7 +138,7 @@ public class PlexPathReplacementServiceTests 0, @"\\192.168.1.100\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -170,7 +170,7 @@ public class PlexPathReplacementServiceTests 0, @"\\SERVERNAME\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -202,7 +202,7 @@ public class PlexPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); + result.ShouldBe(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); } [Test] @@ -234,7 +234,7 @@ public class PlexPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -266,7 +266,7 @@ public class PlexPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); } [Test] @@ -298,6 +298,6 @@ public class PlexPathReplacementServiceTests 0, @"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); - result.Should().Be(@"/Some Movie/Some Movie.mkv"); + result.ShouldBe(@"/Some Movie/Some Movie.mkv"); } } diff --git a/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs b/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs index a9db5c47..bca4f07f 100644 --- a/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/BlockPlayoutChangeDetectionTests.cs @@ -2,7 +2,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Core.Scheduling; using ErsatzTV.Core.Scheduling.BlockScheduling; -using FluentAssertions; +using Shouldly; using Newtonsoft.Json; using NUnit.Framework; @@ -21,7 +21,7 @@ public static class BlockPlayoutChangeDetectionTests // test case: block has moved from one time to another time, nothing after // test case: block has moved from one time to another time, same block after // test case: block has moved from one time to another time, different block with same collection after - // test case: block was moved from one time to another time, different block with different collection after + // test case: block was moved from one time to another time, different block with different collection after // test case: block was removed, nothing after // test case: block was removed, same block after @@ -79,10 +79,10 @@ public static class BlockPlayoutChangeDetectionTests collectionEtags); // nothing to schedule - result.Item1.Should().HaveCount(0); + result.Item1.Count.ShouldBe(0); // do not need to remove any playout items or history - result.Item2.Should().HaveCount(0); + result.Item2.Count.ShouldBe(0); } private static List Blocks(DateTimeOffset dateUpdated) diff --git a/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs b/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs index 109c0a05..c442e396 100644 --- a/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/BlockScheduling/EffectiveBlockTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Core.Scheduling.BlockScheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling.BlockScheduling; @@ -64,7 +64,7 @@ public static class EffectiveBlockTests List result = EffectiveBlock.GetEffectiveBlocks(templates, start, 5); - result.Should().HaveCount(0); + result.Count.ShouldBe(0); } [Test] @@ -89,16 +89,16 @@ public static class EffectiveBlockTests List result = EffectiveBlock.GetEffectiveBlocks(templates, start, 5); - result.Should().HaveCount(3); + result.Count.ShouldBe(3); - result[0].Start.DayOfWeek.Should().Be(DayOfWeek.Monday); - result[0].Start.Date.Should().Be(GetLocalDate(2024, 1, 15).Date); + result[0].Start.DayOfWeek.ShouldBe(DayOfWeek.Monday); + result[0].Start.Date.ShouldBe(GetLocalDate(2024, 1, 15).Date); - result[1].Start.DayOfWeek.Should().Be(DayOfWeek.Wednesday); - result[1].Start.Date.Should().Be(GetLocalDate(2024, 1, 17).Date); + result[1].Start.DayOfWeek.ShouldBe(DayOfWeek.Wednesday); + result[1].Start.Date.ShouldBe(GetLocalDate(2024, 1, 17).Date); - result[2].Start.DayOfWeek.Should().Be(DayOfWeek.Friday); - result[2].Start.Date.Should().Be(GetLocalDate(2024, 1, 19).Date); + result[2].Start.DayOfWeek.ShouldBe(DayOfWeek.Friday); + result[2].Start.Date.ShouldBe(GetLocalDate(2024, 1, 19).Date); } // TODO: test when clocks spring forward diff --git a/ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs b/ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs index 83c1c158..4430b9f7 100644 --- a/ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -23,8 +23,8 @@ public class ChronologicalContentTests for (var i = 1; i <= 10; i++) { - chronologicalContent.Current.IsSome.Should().BeTrue(); - chronologicalContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); + chronologicalContent.Current.IsSome.ShouldBeTrue(); + chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); chronologicalContent.MoveNext(); } } @@ -39,7 +39,7 @@ public class ChronologicalContentTests for (var i = 0; i < 10; i++) { - chronologicalContent.State.Index.Should().Be(i % 10); + chronologicalContent.State.Index.ShouldBe(i % 10); chronologicalContent.MoveNext(); } } @@ -54,9 +54,9 @@ public class ChronologicalContentTests for (var i = 6; i <= 10; i++) { - chronologicalContent.Current.IsSome.Should().BeTrue(); - chronologicalContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); - chronologicalContent.State.Index.Should().Be(i - 1); + chronologicalContent.Current.IsSome.ShouldBeTrue(); + chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); + chronologicalContent.State.Index.ShouldBe(i - 1); chronologicalContent.MoveNext(); } } @@ -69,8 +69,8 @@ public class ChronologicalContentTests var chronologicalContent = new ChronologicalMediaCollectionEnumerator(contents, state); - chronologicalContent.State.Index.Should().Be(0); - chronologicalContent.State.Seed.Should().Be(0); + chronologicalContent.State.Index.ShouldBe(0); + chronologicalContent.State.Seed.ShouldBe(0); } private static List Episodes(int count) => diff --git a/ErsatzTV.Core.Tests/Scheduling/CustomOrderContentTests.cs b/ErsatzTV.Core.Tests/Scheduling/CustomOrderContentTests.cs index 8a4c750c..7a8b7a71 100644 --- a/ErsatzTV.Core.Tests/Scheduling/CustomOrderContentTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/CustomOrderContentTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -23,8 +23,8 @@ public class CustomOrderContentTests for (var i = 10; i >= 1; i--) { - customOrderContent.Current.IsSome.Should().BeTrue(); - customOrderContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); + customOrderContent.Current.IsSome.ShouldBeTrue(); + customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); customOrderContent.MoveNext(); } } @@ -40,7 +40,7 @@ public class CustomOrderContentTests for (var i = 0; i < 10; i++) { - customOrderContent.State.Index.Should().Be(i % 10); + customOrderContent.State.Index.ShouldBe(i % 10); customOrderContent.MoveNext(); } } @@ -56,9 +56,9 @@ public class CustomOrderContentTests for (var i = 5; i >= 1; i--) { - customOrderContent.Current.IsSome.Should().BeTrue(); - customOrderContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); - customOrderContent.State.Index.Should().Be(5 - i + 5); // 5 through 10 + customOrderContent.Current.IsSome.ShouldBeTrue(); + customOrderContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); + customOrderContent.State.Index.ShouldBe(5 - i + 5); // 5 through 10 customOrderContent.MoveNext(); } } diff --git a/ErsatzTV.Core.Tests/Scheduling/MultiPartEpisodeGrouperTests.cs b/ErsatzTV.Core.Tests/Scheduling/MultiPartEpisodeGrouperTests.cs index 3c34075a..55dc3246 100644 --- a/ErsatzTV.Core.Tests/Scheduling/MultiPartEpisodeGrouperTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/MultiPartEpisodeGrouperTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -24,7 +24,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveOneItem(result, mediaItems[0]); ShouldHaveTwoItems(result, mediaItems[1], mediaItems[2]); ShouldHaveOneItem(result, mediaItems[3]); @@ -47,7 +47,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(2); + result.Count.ShouldBe(2); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[1]); ShouldHaveOneItem(result, mediaItems[2]); } @@ -68,7 +68,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(2); + result.Count.ShouldBe(2); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[1]); ShouldHaveOneItem(result, mediaItems[2]); } @@ -89,7 +89,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(2); + result.Count.ShouldBe(2); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[1]); ShouldHaveOneItem(result, mediaItems[2]); } @@ -117,7 +117,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[1]); ShouldHaveOneItem(result, mediaItems[2]); ShouldHaveTwoItems(result, mediaItems[3], mediaItems[4]); @@ -140,7 +140,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(2); + result.Count.ShouldBe(2); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[1]); ShouldHaveTwoItems(result, mediaItems[2], mediaItems[3]); } @@ -162,7 +162,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveOneItem(result, mediaItems[0]); ShouldHaveOneItem(result, mediaItems[1]); ShouldHaveTwoItems(result, mediaItems[2], mediaItems[3]); @@ -185,7 +185,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveOneItem(result, mediaItems[0]); ShouldHaveTwoItems(result, mediaItems[1], mediaItems[2]); ShouldHaveOneItem(result, mediaItems[3]); @@ -208,7 +208,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(4); + result.Count.ShouldBe(4); ShouldHaveOneItem(result, mediaItems[0]); ShouldHaveOneItem(result, mediaItems[1]); ShouldHaveOneItem(result, mediaItems[2]); @@ -232,7 +232,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveOneItem(result, mediaItems[0]); ShouldHaveTwoItems(result, mediaItems[1], mediaItems[2]); ShouldHaveOneItem(result, mediaItems[3]); @@ -259,7 +259,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, false); - result.Count.Should().Be(3); + result.Count.ShouldBe(3); ShouldHaveTwoItems(result, mediaItems[0], mediaItems[2]); ShouldHaveOneItem(result, mediaItems[1]); ShouldHaveOneItem(result, mediaItems[3]); @@ -286,7 +286,7 @@ public class MultiPartEpisodeGrouperTests List result = MultiPartEpisodeGrouper.GroupMediaItems(mediaItems, true); - result.Count.Should().Be(2); + result.Count.ShouldBe(2); ShouldHaveMultipleItems(result, mediaItems[0], new List { mediaItems[1], mediaItems[2] }); ShouldHaveOneItem(result, mediaItems[3]); } @@ -313,14 +313,14 @@ public class MultiPartEpisodeGrouperTests private static void ShouldHaveOneItem(IEnumerable result, MediaItem item) => result.Filter(g => g.First == item && Optional(g.Additional).Flatten().HeadOrNone() == None) - .Should().HaveCount(1); + .Count().ShouldBe(1); private static void ShouldHaveTwoItems( IEnumerable result, MediaItem first, MediaItem additional) => result.Filter(g => g.First == first && Optional(g.Additional).Flatten().HeadOrNone() == Some(additional)) - .Should().HaveCount(1); + .Count().ShouldBe(1); private static void ShouldHaveMultipleItems( IEnumerable result, @@ -329,5 +329,5 @@ public class MultiPartEpisodeGrouperTests result.Filter( g => g.First == first && g.Additional != null && g.Additional.Count == additional.Count && additional.ForAll(g.Additional.Contains)) - .Should().HaveCount(1); + .Count().ShouldBe(1); } diff --git a/ErsatzTV.Core.Tests/Scheduling/PlaylistEnumeratorTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlaylistEnumeratorTests.cs index effb19fa..125f630c 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlaylistEnumeratorTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlaylistEnumeratorTests.cs @@ -1,7 +1,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NSubstitute; using NUnit.Framework; @@ -71,7 +71,7 @@ public class PlaylistEnumeratorTests totalLength += 1; } - totalLength.Should().Be(8); + totalLength.ShouldBe(8); } [Test] @@ -135,7 +135,7 @@ public class PlaylistEnumeratorTests totalLength += 1; } - totalLength.Should().Be(8); + totalLength.ShouldBe(8); } private static Movie FakeMovie(int id) => new() diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs index 40886bb8..ba82ff2d 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs @@ -6,7 +6,7 @@ using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Core.Interfaces.Scheduling; using ErsatzTV.Core.Scheduling; using ErsatzTV.Core.Tests.Fakes; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -52,7 +52,7 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, _cancellationToken); - result.Items.Should().BeEmpty(); + result.Items.ShouldBeEmpty(); } [Test] @@ -70,12 +70,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(2); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(2); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -98,7 +98,7 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, _cancellationToken); - result.Items.Should().BeEmpty(); + result.Items.ShouldBeEmpty(); } [Test] @@ -124,12 +124,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(2); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(2); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -152,7 +152,7 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, _cancellationToken); - result.Items.Should().BeEmpty(); + result.Items.ShouldBeEmpty(); } [Test] @@ -178,12 +178,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(2); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(2); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -208,11 +208,11 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -237,11 +237,11 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -258,11 +258,11 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); + result.Items.Count.ShouldBe(1); + result.Items.Head().StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items.Head().FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -279,12 +279,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(2); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[1].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); + result.Items.Count.ShouldBe(2); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[1].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(12)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(12)); } [Test] @@ -303,17 +303,17 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(2); - - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(4)); + result.Items.Count.ShouldBe(4); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(1); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(2); + + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(4)); } [Test] @@ -332,13 +332,13 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(1); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(1); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); DateTimeOffset start2 = HoursAfterMidnight(1); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); @@ -350,13 +350,13 @@ public class PlayoutBuilderTests finish2, _cancellationToken); - result2.Items.Count.Should().Be(2); - result2.Items.Last().StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result2.Items.Last().MediaItemId.Should().Be(2); + result2.Items.Count.ShouldBe(2); + result2.Items.Last().StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result2.Items.Last().MediaItemId.ShouldBe(2); - result2.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(12)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result2.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(12)); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); } [Test] @@ -375,12 +375,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(1); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(1); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); DateTimeOffset start2 = HoursAfterMidnight(1); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(12); @@ -392,15 +392,15 @@ public class PlayoutBuilderTests finish2, _cancellationToken); - result2.Items.Count.Should().Be(3); - result2.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result2.Items[1].MediaItemId.Should().Be(2); - result2.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result2.Items[2].MediaItemId.Should().Be(1); + result2.Items.Count.ShouldBe(3); + result2.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result2.Items[1].MediaItemId.ShouldBe(2); + result2.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result2.Items[2].MediaItemId.ShouldBe(1); - result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(18)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result2.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(18)); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); } [Test] @@ -422,11 +422,11 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); + result.Items.Count.ShouldBe(6); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; @@ -435,15 +435,15 @@ public class PlayoutBuilderTests Playout result2 = await builder.Build(playout, PlayoutBuildMode.Reset, start2, finish2, _cancellationToken); - result2.Items.Count.Should().Be(6); - result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); + result2.Items.Count.ShouldBe(6); + result2.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; - firstSeedValue.Should().NotBe(secondSeedValue); + firstSeedValue.ShouldNotBe(secondSeedValue); } [Test] @@ -462,13 +462,13 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Seed.Should().BeGreaterThan(0); + result.Items.Count.ShouldBe(6); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Seed.ShouldBeGreaterThan(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); DateTimeOffset start2 = HoursAfterMidnight(0); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); @@ -482,9 +482,9 @@ public class PlayoutBuilderTests int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; - firstSeedValue.Should().Be(secondSeedValue); + firstSeedValue.ShouldBe(secondSeedValue); - result2.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result2.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -572,19 +572,19 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(5); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); - result.Items[4].MediaItemId.Should().Be(2); - - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Items.Count.ShouldBe(5); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(1); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(3); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5)); + result.Items[4].MediaItemId.ShouldBe(2); + + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -672,65 +672,65 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(28); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); - result.Items[4].MediaItemId.Should().Be(2); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[5].MediaItemId.Should().Be(1); - result.Items[6].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7)); - result.Items[6].MediaItemId.Should().Be(2); - result.Items[7].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(8)); - result.Items[7].MediaItemId.Should().Be(1); - result.Items[8].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9)); - result.Items[8].MediaItemId.Should().Be(2); - result.Items[9].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10)); - result.Items[9].MediaItemId.Should().Be(1); - result.Items[10].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11)); - result.Items[10].MediaItemId.Should().Be(2); - result.Items[11].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[11].MediaItemId.Should().Be(1); - result.Items[12].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(13)); - result.Items[12].MediaItemId.Should().Be(2); - result.Items[13].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(14)); - result.Items[13].MediaItemId.Should().Be(1); - result.Items[14].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(15)); - result.Items[14].MediaItemId.Should().Be(2); - result.Items[15].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(16)); - result.Items[15].MediaItemId.Should().Be(1); - result.Items[16].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(17)); - result.Items[16].MediaItemId.Should().Be(2); - result.Items[17].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[17].MediaItemId.Should().Be(1); - result.Items[18].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(19)); - result.Items[18].MediaItemId.Should().Be(2); - result.Items[19].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(20)); - result.Items[19].MediaItemId.Should().Be(1); - result.Items[20].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(21)); - result.Items[20].MediaItemId.Should().Be(2); - result.Items[21].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(22)); - result.Items[21].MediaItemId.Should().Be(1); - result.Items[22].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(23)); - result.Items[22].MediaItemId.Should().Be(2); - result.Items[23].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[23].MediaItemId.Should().Be(1); - result.Items[24].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[24].MediaItemId.Should().Be(2); - result.Items[25].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[25].MediaItemId.Should().Be(1); - result.Items[26].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[26].MediaItemId.Should().Be(3); - result.Items[27].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); - result.Items[27].MediaItemId.Should().Be(2); - - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(30)); + result.Items.Count.ShouldBe(28); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(1); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(3); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5)); + result.Items[4].MediaItemId.ShouldBe(2); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[5].MediaItemId.ShouldBe(1); + result.Items[6].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(7)); + result.Items[6].MediaItemId.ShouldBe(2); + result.Items[7].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(8)); + result.Items[7].MediaItemId.ShouldBe(1); + result.Items[8].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(9)); + result.Items[8].MediaItemId.ShouldBe(2); + result.Items[9].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(10)); + result.Items[9].MediaItemId.ShouldBe(1); + result.Items[10].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(11)); + result.Items[10].MediaItemId.ShouldBe(2); + result.Items[11].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[11].MediaItemId.ShouldBe(1); + result.Items[12].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(13)); + result.Items[12].MediaItemId.ShouldBe(2); + result.Items[13].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(14)); + result.Items[13].MediaItemId.ShouldBe(1); + result.Items[14].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(15)); + result.Items[14].MediaItemId.ShouldBe(2); + result.Items[15].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(16)); + result.Items[15].MediaItemId.ShouldBe(1); + result.Items[16].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(17)); + result.Items[16].MediaItemId.ShouldBe(2); + result.Items[17].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[17].MediaItemId.ShouldBe(1); + result.Items[18].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(19)); + result.Items[18].MediaItemId.ShouldBe(2); + result.Items[19].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(20)); + result.Items[19].MediaItemId.ShouldBe(1); + result.Items[20].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(21)); + result.Items[20].MediaItemId.ShouldBe(2); + result.Items[21].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(22)); + result.Items[21].MediaItemId.ShouldBe(1); + result.Items[22].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(23)); + result.Items[22].MediaItemId.ShouldBe(2); + result.Items[23].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[23].MediaItemId.ShouldBe(1); + result.Items[24].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[24].MediaItemId.ShouldBe(2); + result.Items[25].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[25].MediaItemId.ShouldBe(1); + result.Items[26].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[26].MediaItemId.ShouldBe(3); + result.Items[27].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5)); + result.Items[27].MediaItemId.ShouldBe(2); + + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(30)); } [Test] @@ -820,24 +820,24 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); + result.Items.Count.ShouldBe(6); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); - result.Items[4].MediaItemId.Should().Be(4); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(3); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5)); + result.Items[4].MediaItemId.ShouldBe(4); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[5].MediaItemId.Should().Be(2); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[5].MediaItemId.ShouldBe(2); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(7)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(7)); } [Test] @@ -926,23 +926,23 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); + result.Items.Count.ShouldBe(6); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(8)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9)); - result.Items[2].MediaItemId.Should().Be(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10)); - result.Items[3].MediaItemId.Should().Be(2); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11)); - result.Items[4].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(7)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(8)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(9)); + result.Items[2].MediaItemId.ShouldBe(1); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(10)); + result.Items[3].MediaItemId.ShouldBe(2); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(11)); + result.Items[4].MediaItemId.ShouldBe(1); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[5].MediaItemId.Should().Be(3); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[5].MediaItemId.ShouldBe(3); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(31)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(31)); } [Test] @@ -1041,24 +1041,24 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(5); + result.Items.Count.ShouldBe(5); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11)); - result.Items[2].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(9)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(10)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(11)); + result.Items[2].MediaItemId.ShouldBe(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[3].MediaItemId.Should().Be(3); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[3].MediaItemId.ShouldBe(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7)); - result.Items[4].MediaItemId.Should().Be(2); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(7)); + result.Items[4].MediaItemId.ShouldBe(2); - result.Anchor.InFlood.Should().BeTrue(); + result.Anchor.InFlood.ShouldBeTrue(); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(32)); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(32)); } [Test] @@ -1149,27 +1149,27 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(7); + result.Items.Count.ShouldBe(7); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(3); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(3); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2.75)); - result.Items[3].MediaItemId.Should().Be(1); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3.75)); - result.Items[4].MediaItemId.Should().Be(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2.75)); + result.Items[3].MediaItemId.ShouldBe(1); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3.75)); + result.Items[4].MediaItemId.ShouldBe(2); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4.75)); - result.Items[5].MediaItemId.Should().Be(1); - result.Items[6].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5.75)); - result.Items[6].MediaItemId.Should().Be(2); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4.75)); + result.Items[5].MediaItemId.ShouldBe(1); + result.Items[6].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5.75)); + result.Items[6].MediaItemId.ShouldBe(2); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6.75)); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6.75)); } [Test] @@ -1261,25 +1261,25 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); + result.Items.Count.ShouldBe(6); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(3); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(3); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2.75)); - result.Items[3].MediaItemId.Should().Be(1); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3.75)); - result.Items[4].MediaItemId.Should().Be(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2.75)); + result.Items[3].MediaItemId.ShouldBe(1); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3.75)); + result.Items[4].MediaItemId.ShouldBe(2); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4.75)); - result.Items[5].MediaItemId.Should().Be(4); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4.75)); + result.Items[5].MediaItemId.ShouldBe(4); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6.25)); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6.25)); } [Test] @@ -1378,21 +1378,21 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); + result.Items.Count.ShouldBe(4); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[1].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[1].MediaItemId.ShouldBe(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[2].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[3].MediaItemId.Should().Be(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[2].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[3].MediaItemId.ShouldBe(2); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(1); - result.Anchor.MultipleRemaining.Should().Be(1); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(5)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(1); + result.Anchor.MultipleRemaining.ShouldBe(1); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(5)); } [Test] @@ -1484,23 +1484,23 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(5); + result.Items.Count.ShouldBe(5); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(3); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(3); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(4); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[4].MediaItemId.Should().Be(5); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(4); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[4].MediaItemId.ShouldBe(5); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(0); - result.Anchor.MultipleRemaining.Should().BeNull(); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(5)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(0); + result.Anchor.MultipleRemaining.ShouldBeNull(); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(5)); } [Test] @@ -1601,21 +1601,21 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); + result.Items.Count.ShouldBe(4); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[1].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[1].MediaItemId.ShouldBe(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[2].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[3].MediaItemId.Should().Be(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[2].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[3].MediaItemId.ShouldBe(2); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(1); - result.Anchor.DurationFinish.Should().Be(HoursAfterMidnight(6).UtcDateTime); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(5)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(1); + result.Anchor.DurationFinish.ShouldBe(HoursAfterMidnight(6).UtcDateTime); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(5)); } [Test] @@ -1729,40 +1729,40 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(12); - - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromMinutes(0)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromMinutes(55)); - result.Items[1].MediaItemId.Should().Be(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(new TimeSpan(1, 50, 0)); - result.Items[2].MediaItemId.Should().Be(1); - - result.Items[3].StartOffset.TimeOfDay.Should().Be(new TimeSpan(2, 45, 0)); - result.Items[3].MediaItemId.Should().Be(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(new TimeSpan(2, 50, 0)); - result.Items[4].MediaItemId.Should().Be(3); - result.Items[5].StartOffset.TimeOfDay.Should().Be(new TimeSpan(2, 55, 0)); - result.Items[5].MediaItemId.Should().Be(3); - - result.Items[6].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[6].MediaItemId.Should().Be(2); - result.Items[7].StartOffset.TimeOfDay.Should().Be(new TimeSpan(3, 55, 0)); - result.Items[7].MediaItemId.Should().Be(2); - result.Items[8].StartOffset.TimeOfDay.Should().Be(new TimeSpan(4, 50, 0)); - result.Items[8].MediaItemId.Should().Be(2); - - result.Items[9].StartOffset.TimeOfDay.Should().Be(new TimeSpan(5, 45, 0)); - result.Items[9].MediaItemId.Should().Be(3); - result.Items[10].StartOffset.TimeOfDay.Should().Be(new TimeSpan(5, 50, 0)); - result.Items[10].MediaItemId.Should().Be(3); - result.Items[11].StartOffset.TimeOfDay.Should().Be(new TimeSpan(5, 55, 0)); - result.Items[11].MediaItemId.Should().Be(3); - - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(0); - result.Anchor.DurationFinish.Should().BeNull(); - - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Items.Count.ShouldBe(12); + + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromMinutes(0)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromMinutes(55)); + result.Items[1].MediaItemId.ShouldBe(1); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(1, 50, 0)); + result.Items[2].MediaItemId.ShouldBe(1); + + result.Items[3].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(2, 45, 0)); + result.Items[3].MediaItemId.ShouldBe(3); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(2, 50, 0)); + result.Items[4].MediaItemId.ShouldBe(3); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(2, 55, 0)); + result.Items[5].MediaItemId.ShouldBe(3); + + result.Items[6].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[6].MediaItemId.ShouldBe(2); + result.Items[7].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(3, 55, 0)); + result.Items[7].MediaItemId.ShouldBe(2); + result.Items[8].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(4, 50, 0)); + result.Items[8].MediaItemId.ShouldBe(2); + + result.Items[9].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(5, 45, 0)); + result.Items[9].MediaItemId.ShouldBe(3); + result.Items[10].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(5, 50, 0)); + result.Items[10].MediaItemId.ShouldBe(3); + result.Items[11].StartOffset.TimeOfDay.ShouldBe(new TimeSpan(5, 55, 0)); + result.Items[11].MediaItemId.ShouldBe(3); + + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(0); + result.Anchor.DurationFinish.ShouldBeNull(); + + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -1849,16 +1849,16 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(2); + result.Items.Count.ShouldBe(2); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromMinutes(0)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromMinutes(61)); - result.Items[1].MediaItemId.Should().Be(2); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromMinutes(0)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromMinutes(61)); + result.Items[1].MediaItemId.ShouldBe(2); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(0); - result.Anchor.DurationFinish.Should().BeNull(); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddMinutes(65)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(0); + result.Anchor.DurationFinish.ShouldBeNull(); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddMinutes(65)); } [Test] @@ -1929,24 +1929,24 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - result.Items[0].MediaItemId.Should().Be(2); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[1].MediaItemId.Should().Be(4); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[2].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[3].MediaItemId.Should().Be(4); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[4].MediaItemId.Should().Be(2); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); - result.Items[5].MediaItemId.Should().Be(4); - - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(0); - result.Anchor.DurationFinish.Should().BeNull(); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(6)); + result.Items.Count.ShouldBe(6); + + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + result.Items[0].MediaItemId.ShouldBe(2); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[1].MediaItemId.ShouldBe(4); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[2].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[3].MediaItemId.ShouldBe(4); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[4].MediaItemId.ShouldBe(2); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(5)); + result.Items[5].MediaItemId.ShouldBe(4); + + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(0); + result.Anchor.DurationFinish.ShouldBeNull(); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(6)); } [Test] @@ -1965,40 +1965,40 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(8); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[1].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[2].MediaItemId.Should().Be(3); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[2].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[3].MediaItemId.Should().Be(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[3].FinishOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[4].MediaItemId.Should().Be(2); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[4].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[5].MediaItemId.Should().Be(3); - result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[5].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[6].MediaItemId.Should().Be(1); - result.Items[6].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[6].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[7].MediaItemId.Should().Be(2); - result.Items[7].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[7].FinishOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - - result.ProgramScheduleAnchors.Count.Should().Be(2); - result.ProgramScheduleAnchors.Count(a => a.EnumeratorState.Index == 4 % 3).Should().Be(1); - result.ProgramScheduleAnchors.Count(a => a.EnumeratorState.Index == 8 % 3).Should().Be(1); + result.Items.Count.ShouldBe(8); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[1].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[2].MediaItemId.ShouldBe(3); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[2].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[3].MediaItemId.ShouldBe(1); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[3].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[4].MediaItemId.ShouldBe(2); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[4].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[5].MediaItemId.ShouldBe(3); + result.Items[5].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[5].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[6].MediaItemId.ShouldBe(1); + result.Items[6].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[6].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[7].MediaItemId.ShouldBe(2); + result.Items[7].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[7].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + + result.ProgramScheduleAnchors.Count.ShouldBe(2); + result.ProgramScheduleAnchors.Count(a => a.EnumeratorState.Index == 4 % 3).ShouldBe(1); + result.ProgramScheduleAnchors.Count(a => a.EnumeratorState.Index == 8 % 3).ShouldBe(1); int seed = result.ProgramScheduleAnchors[0].EnumeratorState.Seed; - result.ProgramScheduleAnchors.All(a => a.EnumeratorState.Seed == seed).Should().BeTrue(); + result.ProgramScheduleAnchors.All(a => a.EnumeratorState.Seed == seed).ShouldBeTrue(); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddDays(2)); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddDays(2)); } } @@ -2024,11 +2024,11 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); + result.Items.Count.ShouldBe(6); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; @@ -2037,15 +2037,15 @@ public class PlayoutBuilderTests Playout result2 = await builder.Build(playout, PlayoutBuildMode.Reset, start2, finish2, _cancellationToken); - result2.Items.Count.Should().Be(6); - result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); + result2.Items.Count.ShouldBe(6); + result2.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; - firstSeedValue.Should().NotBe(secondSeedValue); + firstSeedValue.ShouldNotBe(secondSeedValue); } } @@ -2145,21 +2145,21 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Refresh, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); - result.Items[0].MediaItemId.Should().Be(2); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - result.Items[0].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[1].MediaItemId.Should().Be(3); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result.Items[1].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[2].MediaItemId.Should().Be(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[2].FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[3].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - result.Items[3].FinishOffset.TimeOfDay.Should().Be(TimeSpan.Zero); - - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(48)); + result.Items.Count.ShouldBe(4); + result.Items[0].MediaItemId.ShouldBe(2); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + result.Items[0].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[1].MediaItemId.ShouldBe(3); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result.Items[1].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[2].MediaItemId.ShouldBe(1); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[2].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[3].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + result.Items[3].FinishOffset.TimeOfDay.ShouldBe(TimeSpan.Zero); + + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(48)); } } @@ -2182,13 +2182,13 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(1); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(1); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); DateTimeOffset start2 = HoursAfterMidnight(1); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); @@ -2200,13 +2200,13 @@ public class PlayoutBuilderTests finish2, _cancellationToken); - result2.Items.Count.Should().Be(2); - result2.Items.Last().StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result2.Items.Last().MediaItemId.Should().Be(2); + result2.Items.Count.ShouldBe(2); + result2.Items.Last().StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result2.Items.Last().MediaItemId.ShouldBe(2); - result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(12)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result2.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(12)); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); } [Test] @@ -2225,12 +2225,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(1); - result.Items.Head().MediaItemId.Should().Be(1); + result.Items.Count.ShouldBe(1); + result.Items.Head().MediaItemId.ShouldBe(1); - result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(6)); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); DateTimeOffset start2 = HoursAfterMidnight(1); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(12); @@ -2242,15 +2242,15 @@ public class PlayoutBuilderTests finish2, _cancellationToken); - result2.Items.Count.Should().Be(3); - result2.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - result2.Items[1].MediaItemId.Should().Be(2); - result2.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result2.Items[2].MediaItemId.Should().Be(1); + result2.Items.Count.ShouldBe(3); + result2.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + result2.Items[1].MediaItemId.ShouldBe(2); + result2.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result2.Items[2].MediaItemId.ShouldBe(1); - result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(18)); - result2.ProgramScheduleAnchors.Count.Should().Be(1); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + result2.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(18)); + result2.ProgramScheduleAnchors.Count.ShouldBe(1); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); } [Test] @@ -2269,12 +2269,12 @@ public class PlayoutBuilderTests await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - playout.Items.Count.Should().Be(4); - playout.Items.Map(i => i.MediaItemId).ToList().Should().Equal(1, 2, 1, 2); + playout.Items.Count.ShouldBe(4); + playout.Items.Map(i => i.MediaItemId).ToList().ShouldBe([1, 2, 1, 2]); - playout.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddDays(1)); - playout.ProgramScheduleAnchors.Count.Should().Be(1); - playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + playout.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddDays(1)); + playout.ProgramScheduleAnchors.Count.ShouldBe(1); + playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); PlayoutProgramScheduleAnchor headAnchor = playout.ProgramScheduleAnchors.Head(); @@ -2306,22 +2306,22 @@ public class PlayoutBuilderTests await builder.Build(playout, PlayoutBuildMode.Continue, start2, finish2, _cancellationToken); - playout.Items.Count.Should().Be(5); - playout.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - playout.Items[0].MediaItemId.Should().Be(1); - playout.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - playout.Items[1].MediaItemId.Should().Be(2); - playout.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - playout.Items[2].MediaItemId.Should().Be(1); - playout.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - playout.Items[3].MediaItemId.Should().Be(2); - playout.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - playout.Items[4].MediaItemId.Should().Be(1); + playout.Items.Count.ShouldBe(5); + playout.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + playout.Items[0].MediaItemId.ShouldBe(1); + playout.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + playout.Items[1].MediaItemId.ShouldBe(2); + playout.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + playout.Items[2].MediaItemId.ShouldBe(1); + playout.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + playout.Items[3].MediaItemId.ShouldBe(2); + playout.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + playout.Items[4].MediaItemId.ShouldBe(1); - playout.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(30)); + playout.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(30)); - playout.ProgramScheduleAnchors.Count.Should().Be(2); - playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + playout.ProgramScheduleAnchors.Count.ShouldBe(2); + playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); // continue 1h later DateTimeOffset start3 = HoursAfterMidnight(2); @@ -2329,22 +2329,22 @@ public class PlayoutBuilderTests await builder.Build(playout, PlayoutBuildMode.Continue, start3, finish3, _cancellationToken); - playout.Items.Count.Should().Be(5); - playout.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - playout.Items[0].MediaItemId.Should().Be(1); - playout.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); - playout.Items[1].MediaItemId.Should().Be(2); - playout.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - playout.Items[2].MediaItemId.Should().Be(1); - playout.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(18)); - playout.Items[3].MediaItemId.Should().Be(2); - playout.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(0)); - playout.Items[4].MediaItemId.Should().Be(1); - - playout.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(30)); - - playout.ProgramScheduleAnchors.Count.Should().Be(2); - playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); + playout.Items.Count.ShouldBe(5); + playout.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + playout.Items[0].MediaItemId.ShouldBe(1); + playout.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(6)); + playout.Items[1].MediaItemId.ShouldBe(2); + playout.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + playout.Items[2].MediaItemId.ShouldBe(1); + playout.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(18)); + playout.Items[3].MediaItemId.ShouldBe(2); + playout.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(0)); + playout.Items[4].MediaItemId.ShouldBe(1); + + playout.Anchor.NextStartOffset.ShouldBe(DateTime.Today.AddHours(30)); + + playout.ProgramScheduleAnchors.Count.ShouldBe(2); + playout.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(1); } [Test] @@ -2363,10 +2363,10 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - result.ProgramScheduleAnchors.Count.Should().Be(1); - result.ProgramScheduleAnchors.Head().EnumeratorState.Seed.Should().BeGreaterThan(0); - result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result.Items.Count.ShouldBe(6); + result.ProgramScheduleAnchors.Count.ShouldBe(1); + result.ProgramScheduleAnchors.Head().EnumeratorState.Seed.ShouldBeGreaterThan(0); + result.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; @@ -2382,9 +2382,9 @@ public class PlayoutBuilderTests int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; - firstSeedValue.Should().Be(secondSeedValue); + firstSeedValue.ShouldBe(secondSeedValue); - result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); + result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.ShouldBe(0); } [Test] @@ -2402,15 +2402,15 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(53); - result.ProgramScheduleAnchors.Count.Should().Be(2); + result.Items.Count.ShouldBe(53); + result.ProgramScheduleAnchors.Count.ShouldBe(2); - result.ProgramScheduleAnchors.All(x => x.AnchorDate is not null).Should().BeTrue(); + result.ProgramScheduleAnchors.All(x => x.AnchorDate is not null).ShouldBeTrue(); PlayoutProgramScheduleAnchor lastCheckpoint = result.ProgramScheduleAnchors .OrderByDescending(a => a.AnchorDate ?? DateTime.MinValue) .First(); - lastCheckpoint.EnumeratorState.Seed.Should().BeGreaterThan(0); - lastCheckpoint.EnumeratorState.Index.Should().Be(3); + lastCheckpoint.EnumeratorState.Seed.ShouldBeGreaterThan(0); + lastCheckpoint.EnumeratorState.Index.ShouldBe(3); // we need to mess up the ordering to trigger the problematic behavior // this simulates the way the rows are loaded with EF @@ -2442,7 +2442,7 @@ public class PlayoutBuilderTests int secondSeedValue = continueAnchor.EnumeratorState.Seed; // the continue anchor should have the same seed as the most recent (last) checkpoint from the first run - firstSeedValue.Should().Be(secondSeedValue); + firstSeedValue.ShouldBe(secondSeedValue); } [Test] @@ -2462,12 +2462,12 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(6); - result.ProgramScheduleAnchors.Count.Should().Be(2); + result.Items.Count.ShouldBe(6); + result.ProgramScheduleAnchors.Count.ShouldBe(2); PlayoutProgramScheduleAnchor primaryAnchor = result.ProgramScheduleAnchors.First(a => a.SmartCollectionId == 1); - primaryAnchor.EnumeratorState.Seed.Should().BeGreaterThan(0); - primaryAnchor.EnumeratorState.Index.Should().Be(0); + primaryAnchor.EnumeratorState.Seed.ShouldBeGreaterThan(0); + primaryAnchor.EnumeratorState.Index.ShouldBe(0); int firstSeedValue = primaryAnchor.EnumeratorState.Seed; @@ -2484,9 +2484,9 @@ public class PlayoutBuilderTests primaryAnchor = result2.ProgramScheduleAnchors.First(a => a.SmartCollectionId == 1); int secondSeedValue = primaryAnchor.EnumeratorState.Seed; - firstSeedValue.Should().Be(secondSeedValue); + firstSeedValue.ShouldBe(secondSeedValue); - primaryAnchor.EnumeratorState.Index.Should().Be(0); + primaryAnchor.EnumeratorState.Index.ShouldBe(0); } [Test] @@ -2505,16 +2505,16 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Reset, start, finish, _cancellationToken); - result.Items.Count.Should().Be(53); - result.ProgramScheduleAnchors.Count.Should().Be(4); + result.Items.Count.ShouldBe(53); + result.ProgramScheduleAnchors.Count.ShouldBe(4); - result.ProgramScheduleAnchors.All(x => x.AnchorDate is not null).Should().BeTrue(); + result.ProgramScheduleAnchors.All(x => x.AnchorDate is not null).ShouldBeTrue(); PlayoutProgramScheduleAnchor lastCheckpoint = result.ProgramScheduleAnchors .Filter(psa => psa.SmartCollectionId == 1) .OrderByDescending(a => a.AnchorDate ?? DateTime.MinValue) .First(); - lastCheckpoint.EnumeratorState.Seed.Should().BeGreaterThan(0); - lastCheckpoint.EnumeratorState.Index.Should().Be(53); + lastCheckpoint.EnumeratorState.Seed.ShouldBeGreaterThan(0); + lastCheckpoint.EnumeratorState.Index.ShouldBe(53); int firstSeedValue = lastCheckpoint.EnumeratorState.Seed; @@ -2537,7 +2537,7 @@ public class PlayoutBuilderTests int secondSeedValue = continueAnchor.EnumeratorState.Seed; // the continue anchor should have the same seed as the most recent (last) checkpoint from the first run - firstSeedValue.Should().Be(secondSeedValue); + firstSeedValue.ShouldBe(secondSeedValue); } } @@ -2637,23 +2637,23 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(5); + result.Items.Count.ShouldBe(5); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10)); - result.Items[1].MediaItemId.Should().Be(2); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11)); - result.Items[2].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(9)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(10)); + result.Items[1].MediaItemId.ShouldBe(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(11)); + result.Items[2].MediaItemId.ShouldBe(1); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12)); - result.Items[3].MediaItemId.Should().Be(3); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(12)); + result.Items[3].MediaItemId.ShouldBe(3); - result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7)); - result.Items[4].MediaItemId.Should().Be(2); + result.Items[4].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(7)); + result.Items[4].MediaItemId.ShouldBe(2); - result.Anchor.InFlood.Should().BeTrue(); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(32)); + result.Anchor.InFlood.ShouldBeTrue(); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(32)); } [Test] @@ -2752,21 +2752,21 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); + result.Items.Count.ShouldBe(4); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[1].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[1].MediaItemId.ShouldBe(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[2].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[3].MediaItemId.Should().Be(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[2].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[3].MediaItemId.ShouldBe(2); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(1); - result.Anchor.MultipleRemaining.Should().Be(1); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(5)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(1); + result.Anchor.MultipleRemaining.ShouldBe(1); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(5)); } [Test] @@ -2867,21 +2867,21 @@ public class PlayoutBuilderTests Playout result = await builder.Build(playout, PlayoutBuildMode.Continue, start, finish, _cancellationToken); - result.Items.Count.Should().Be(4); + result.Items.Count.ShouldBe(4); - result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); - result.Items[0].MediaItemId.Should().Be(1); - result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); - result.Items[1].MediaItemId.Should().Be(1); + result.Items[0].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(1)); + result.Items[0].MediaItemId.ShouldBe(1); + result.Items[1].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(2)); + result.Items[1].MediaItemId.ShouldBe(1); - result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); - result.Items[2].MediaItemId.Should().Be(2); - result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4)); - result.Items[3].MediaItemId.Should().Be(2); + result.Items[2].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(3)); + result.Items[2].MediaItemId.ShouldBe(2); + result.Items[3].StartOffset.TimeOfDay.ShouldBe(TimeSpan.FromHours(4)); + result.Items[3].MediaItemId.ShouldBe(2); - result.Anchor.ScheduleItemsEnumeratorState.Index.Should().Be(1); - result.Anchor.DurationFinish.Should().Be(HoursAfterMidnight(6).UtcDateTime); - result.Anchor.NextStartOffset.Should().Be(HoursAfterMidnight(5)); + result.Anchor.ScheduleItemsEnumeratorState.Index.ShouldBe(1); + result.Anchor.DurationFinish.ShouldBe(HoursAfterMidnight(6).UtcDateTime); + result.Anchor.NextStartOffset.ShouldBe(HoursAfterMidnight(5)); } } diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs index 926e59a8..ea1da89e 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs @@ -2,7 +2,7 @@ using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Interfaces.Scheduling; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -61,7 +61,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase true, _cancellationToken); - playoutItems.Count.Should().Be(1); + playoutItems.Count.ShouldBe(1); } [Test] @@ -114,7 +114,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase true, _cancellationToken); - playoutItems.Count.Should().Be(1); + playoutItems.Count.ShouldBe(1); } [Test] @@ -181,13 +181,13 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase true, _cancellationToken); - playoutItems.Count.Should().Be(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(6)); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(11)); + playoutItems.Count.ShouldBe(3); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(6)); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(11)); } [Test] @@ -273,27 +273,27 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase true, _cancellationToken); - playoutItems.Count.Should().Be(5); + playoutItems.Count.ShouldBe(5); // content chapter 1 - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); // mid-roll 1 - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(6)); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(6)); // mid-roll 2 - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(11)); + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(11)); // content chapter 2 - playoutItems[3].MediaItemId.Should().Be(1); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(16)); + playoutItems[3].MediaItemId.ShouldBe(1); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(16)); // post-roll - playoutItems[4].MediaItemId.Should().Be(5); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55)); + playoutItems[4].MediaItemId.ShouldBe(5); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(55)); } [Test] @@ -379,27 +379,27 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase true, _cancellationToken); - playoutItems.Count.Should().Be(5); + playoutItems.Count.ShouldBe(5); // content chapter 1 - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); // mid-roll 1 - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(6)); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(6)); // content chapter 2 - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(11)); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(11)); // post-roll 1 - playoutItems[3].MediaItemId.Should().Be(5); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(50)); + playoutItems[3].MediaItemId.ShouldBe(5); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(50)); // post-roll 2 - playoutItems[4].MediaItemId.Should().Be(6); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55)); + playoutItems[4].MediaItemId.ShouldBe(6); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime + TimeSpan.FromMinutes(55)); } } @@ -428,7 +428,7 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase DateTimeOffset result = PlayoutModeSchedulerBase.GetStartTimeAfter(state, scheduleItem); - result.Should().Be(DateTime.Today.AddHours(6)); + result.ShouldBe(DateTime.Today.AddHours(6)); } } diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs index e3f7d740..4855b6d9 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerDurationTests.cs @@ -2,7 +2,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NUnit.Framework; using Serilog; @@ -68,40 +68,40 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); // one guide group here because of custom title - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(3); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - playoutItems[0].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - playoutItems[1].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - playoutItems[2].CustomTitle.Should().Be("CustomTitle"); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); // one guide group here because of custom title + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(3); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + playoutItems[0].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + playoutItems[1].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + playoutItems[2].CustomTitle.ShouldBe("CustomTitle"); } [Test] @@ -141,40 +141,40 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(3); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - playoutItems[0].CustomTitle.Should().Be("Custom Title"); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - playoutItems[1].CustomTitle.Should().Be("Custom Title"); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - playoutItems[2].CustomTitle.Should().Be("Custom Title"); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(3); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + playoutItems[0].CustomTitle.ShouldBe("Custom Title"); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + playoutItems[1].CustomTitle.ShouldBe("Custom Title"); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + playoutItems[2].CustomTitle.ShouldBe("Custom Title"); } [Test] @@ -213,37 +213,37 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(3); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(3); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); } [Test] @@ -283,39 +283,39 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase _cancellationToken); // duration block should end after exact duration, with gap - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(1); + enumerator.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); // offline should not set guide finish - playoutItems[2].GuideFinish.HasValue.Should().BeFalse(); + playoutItems[2].GuideFinish.HasValue.ShouldBeFalse(); } [Test] @@ -365,44 +365,44 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(4); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Fallback); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(4); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Fallback); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); } [Test] @@ -452,56 +452,56 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); } [Test] @@ -551,56 +551,56 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[4].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[5].GuideFinish.HasValue.Should().BeFalse(); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[4].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[5].GuideFinish.HasValue.ShouldBeFalse(); } [Test] @@ -667,63 +667,63 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(7); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].GuideFinish.HasValue.Should().BeTrue(); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[3].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[4].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); - playoutItems[5].GuideFinish.HasValue.Should().BeFalse(); - - playoutItems[6].MediaItemId.Should().Be(5); - playoutItems[6].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems[6].GuideGroup.Should().Be(3); - playoutItems[6].FillerKind.Should().Be(FillerKind.Fallback); - playoutItems[6].GuideFinish.HasValue.Should().BeFalse(); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(7); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].GuideFinish.HasValue.ShouldBeTrue(); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[3].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[4].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); + playoutItems[5].GuideFinish.HasValue.ShouldBeFalse(); + + playoutItems[6].MediaItemId.ShouldBe(5); + playoutItems[6].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems[6].GuideGroup.ShouldBe(3); + playoutItems[6].FillerKind.ShouldBe(FillerKind.Fallback); + playoutItems[6].GuideFinish.HasValue.ShouldBeFalse(); } [Test] @@ -818,25 +818,25 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddMinutes(30)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddMinutes(30)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); // THIS IS THE KEY TEST - needs to be exactly 30 minutes - (playoutItems.Last().FinishOffset - playoutItems.First().StartOffset).Should().Be(TimeSpan.FromMinutes(30)); + (playoutItems.Last().FinishOffset - playoutItems.First().StartOffset).ShouldBe(TimeSpan.FromMinutes(30)); - // playoutBuilderState.NextGuideGroup.Should().Be(3); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + // playoutBuilderState.NextGuideGroup.ShouldBe(3); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(0); - enumerator4.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(0); + enumerator4.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(12); + playoutItems.Count.ShouldBe(12); } [Test] @@ -882,17 +882,17 @@ public class PlayoutModeSchedulerDurationTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutItems.Should().BeEmpty(); + playoutItems.ShouldBeEmpty(); - playoutBuilderState.CurrentTime.Should().Be(HardStop(scheduleItemsEnumerator)); + playoutBuilderState.CurrentTime.ShouldBe(HardStop(scheduleItemsEnumerator)); - playoutBuilderState.NextGuideGroup.Should().Be(1); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(1); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(0); + enumerator.State.Index.ShouldBe(0); } } diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs index 843b4c45..6d1c37c6 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerFloodTests.cs @@ -1,7 +1,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -59,37 +59,37 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); // one guide group here because of custom title - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); - - enumerator.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(3); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].CustomTitle.Should().Be("CustomTitle"); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); // one guide group here because of custom title + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); + + enumerator.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(3); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].CustomTitle.ShouldBe("CustomTitle"); } [Test] @@ -134,55 +134,55 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(6)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); // one guide group here because of custom title - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeTrue(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator.State.Index.Should().Be(0); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[3].MediaItemId.Should().Be(2); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.None); - playoutItems[3].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[4].MediaItemId.Should().Be(1); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.AddHours(4)); - playoutItems[4].GuideGroup.Should().Be(1); - playoutItems[4].FillerKind.Should().Be(FillerKind.None); - playoutItems[4].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[5].MediaItemId.Should().Be(2); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.AddHours(5)); - playoutItems[5].GuideGroup.Should().Be(1); - playoutItems[5].FillerKind.Should().Be(FillerKind.None); - playoutItems[5].CustomTitle.Should().Be("CustomTitle"); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(6)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); // one guide group here because of custom title + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeTrue(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator.State.Index.ShouldBe(0); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[3].MediaItemId.ShouldBe(2); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.None); + playoutItems[3].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[4].MediaItemId.ShouldBe(1); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.AddHours(4)); + playoutItems[4].GuideGroup.ShouldBe(1); + playoutItems[4].FillerKind.ShouldBe(FillerKind.None); + playoutItems[4].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[5].MediaItemId.ShouldBe(2); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.AddHours(5)); + playoutItems[5].GuideGroup.ShouldBe(1); + playoutItems[5].FillerKind.ShouldBe(FillerKind.None); + playoutItems[5].CustomTitle.ShouldBe("CustomTitle"); } [Test] @@ -231,34 +231,34 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); - enumerator.State.Index.Should().Be(1); + enumerator.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -316,50 +316,50 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.PostRoll); - - playoutItems[2].MediaItemId.Should().Be(2); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[2].GuideGroup.Should().Be(2); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(4); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 55, 0))); - playoutItems[3].GuideGroup.Should().Be(2); - playoutItems[3].FillerKind.Should().Be(FillerKind.PostRoll); - - playoutItems[4].MediaItemId.Should().Be(1); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.None); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.PostRoll); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.PostRoll); + + playoutItems[2].MediaItemId.ShouldBe(2); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[2].GuideGroup.ShouldBe(2); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(4); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 55, 0))); + playoutItems[3].GuideGroup.ShouldBe(2); + playoutItems[3].FillerKind.ShouldBe(FillerKind.PostRoll); + + playoutItems[4].MediaItemId.ShouldBe(1); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.PostRoll); } [Test] @@ -404,34 +404,34 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); - enumerator.State.Index.Should().Be(1); + enumerator.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -486,50 +486,50 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -584,40 +584,40 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(4); + playoutItems.Count.ShouldBe(4); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Fallback); + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -672,50 +672,50 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -786,56 +786,56 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(7); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[6].MediaItemId.Should().Be(5); - playoutItems[6].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems[6].GuideGroup.Should().Be(3); - playoutItems[6].FillerKind.Should().Be(FillerKind.Fallback); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(7); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[6].MediaItemId.ShouldBe(5); + playoutItems[6].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems[6].GuideGroup.ShouldBe(3); + playoutItems[6].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -898,50 +898,50 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase hardStop, _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(7); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeTrue(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(0); - enumerator2.State.Index.Should().Be(0); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(20)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(40)); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(2); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(60)); - playoutItems[3].GuideGroup.Should().Be(4); - playoutItems[3].FillerKind.Should().Be(FillerKind.None); - - playoutItems[4].MediaItemId.Should().Be(1); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(80)); - playoutItems[4].GuideGroup.Should().Be(5); - playoutItems[4].FillerKind.Should().Be(FillerKind.None); - - playoutItems[5].MediaItemId.Should().Be(2); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(100)); - playoutItems[5].GuideGroup.Should().Be(6); - playoutItems[5].FillerKind.Should().Be(FillerKind.None); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(7); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeTrue(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(0); + enumerator2.State.Index.ShouldBe(0); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(20)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(40)); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(2); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(60)); + playoutItems[3].GuideGroup.ShouldBe(4); + playoutItems[3].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[4].MediaItemId.ShouldBe(1); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(80)); + playoutItems[4].GuideGroup.ShouldBe(5); + playoutItems[4].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[5].MediaItemId.ShouldBe(2); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(100)); + playoutItems[5].GuideGroup.ShouldBe(6); + playoutItems[5].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -1004,50 +1004,50 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase hardStop, _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(7); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeTrue(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(0); - enumerator2.State.Index.Should().Be(0); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(20)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(40)); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(2); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(60)); - playoutItems[3].GuideGroup.Should().Be(4); - playoutItems[3].FillerKind.Should().Be(FillerKind.None); - - playoutItems[4].MediaItemId.Should().Be(1); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(80)); - playoutItems[4].GuideGroup.Should().Be(5); - playoutItems[4].FillerKind.Should().Be(FillerKind.None); - - playoutItems[5].MediaItemId.Should().Be(2); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(100)); - playoutItems[5].GuideGroup.Should().Be(6); - playoutItems[5].FillerKind.Should().Be(FillerKind.None); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(7); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeTrue(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(0); + enumerator2.State.Index.ShouldBe(0); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(20)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(40)); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(2); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(60)); + playoutItems[3].GuideGroup.ShouldBe(4); + playoutItems[3].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[4].MediaItemId.ShouldBe(1); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(80)); + playoutItems[4].GuideGroup.ShouldBe(5); + playoutItems[4].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[5].MediaItemId.ShouldBe(2); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(100)); + playoutItems[5].GuideGroup.ShouldBe(6); + playoutItems[5].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -1118,36 +1118,36 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(1); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(1); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(0); - enumerator3.State.Index.Should().Be(0); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(0); + enumerator3.State.Index.ShouldBe(0); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -1192,18 +1192,18 @@ public class PlayoutModeSchedulerFloodTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutItems.Should().BeEmpty(); + playoutItems.ShouldBeEmpty(); - playoutBuilderState.CurrentTime.Should().Be(HardStop(scheduleItemsEnumerator)); + playoutBuilderState.CurrentTime.ShouldBe(HardStop(scheduleItemsEnumerator)); - playoutBuilderState.NextGuideGroup.Should().Be(1); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(1); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(0); + enumerator.State.Index.ShouldBe(0); } protected override ProgramScheduleItem NextScheduleItem => new ProgramScheduleItemOne diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs index 4bceb4bb..d1e95766 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerMultipleTests.cs @@ -1,7 +1,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -60,37 +60,37 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); // one guide group here because of custom title - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(3); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - playoutItems[1].CustomTitle.Should().Be("CustomTitle"); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - playoutItems[2].CustomTitle.Should().Be("CustomTitle"); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); // one guide group here because of custom title + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(3); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + playoutItems[1].CustomTitle.ShouldBe("CustomTitle"); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + playoutItems[2].CustomTitle.ShouldBe("CustomTitle"); } [Test] @@ -135,34 +135,34 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(1); + enumerator.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -218,50 +218,50 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -317,40 +317,40 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(4); + playoutItems.Count.ShouldBe(4); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Fallback); + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -406,50 +406,50 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(6); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(6); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -522,56 +522,56 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(7); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddMinutes(55)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); - - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[3].GuideGroup.Should().Be(3); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(4); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[4].GuideGroup.Should().Be(3); - playoutItems[4].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[5].MediaItemId.Should().Be(3); - playoutItems[5].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[5].GuideGroup.Should().Be(3); - playoutItems[5].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[6].MediaItemId.Should().Be(5); - playoutItems[6].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems[6].GuideGroup.Should().Be(3); - playoutItems[6].FillerKind.Should().Be(FillerKind.Fallback); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(7); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddMinutes(55)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(1, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[3].GuideGroup.ShouldBe(3); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(4); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[4].GuideGroup.ShouldBe(3); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[5].MediaItemId.ShouldBe(3); + playoutItems[5].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[5].GuideGroup.ShouldBe(3); + playoutItems[5].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[6].MediaItemId.ShouldBe(5); + playoutItems[6].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems[6].GuideGroup.ShouldBe(3); + playoutItems[6].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -644,36 +644,36 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(4); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(4); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(0); - enumerator3.State.Index.Should().Be(0); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(0); + enumerator3.State.Index.ShouldBe(0); - playoutItems.Count.Should().Be(3); + playoutItems.Count.ShouldBe(3); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(2); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(2); - playoutItems[1].FillerKind.Should().Be(FillerKind.None); + playoutItems[1].MediaItemId.ShouldBe(2); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(2); + playoutItems[1].FillerKind.ShouldBe(FillerKind.None); - playoutItems[2].MediaItemId.Should().Be(1); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.AddHours(2)); - playoutItems[2].GuideGroup.Should().Be(3); - playoutItems[2].FillerKind.Should().Be(FillerKind.None); + playoutItems[2].MediaItemId.ShouldBe(1); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.AddHours(2)); + playoutItems[2].GuideGroup.ShouldBe(3); + playoutItems[2].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -724,18 +724,18 @@ public class PlayoutModeSchedulerMultipleTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutItems.Should().BeEmpty(); + playoutItems.ShouldBeEmpty(); - playoutBuilderState.CurrentTime.Should().Be(HardStop(scheduleItemsEnumerator)); + playoutBuilderState.CurrentTime.ShouldBe(HardStop(scheduleItemsEnumerator)); - playoutBuilderState.NextGuideGroup.Should().Be(1); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(1); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(0); + enumerator.State.Index.ShouldBe(0); } protected override ProgramScheduleItem NextScheduleItem => new ProgramScheduleItemOne diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs index 66cbb5e6..f1b0d44f 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerOneTests.cs @@ -1,7 +1,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -53,25 +53,25 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(1); + enumerator.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(1); + playoutItems.Count.ShouldBe(1); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - playoutItems[0].CustomTitle.Should().Be("CustomTitle"); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + playoutItems[0].CustomTitle.ShouldBe("CustomTitle"); } [Test] @@ -136,26 +136,26 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(0); - enumerator3.State.Index.Should().Be(0); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(0); + enumerator3.State.Index.ShouldBe(0); - playoutItems.Count.Should().Be(1); + playoutItems.Count.ShouldBe(1); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -204,40 +204,40 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(4); + playoutItems.Count.ShouldBe(4); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.Tail); - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.Tail); - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -286,30 +286,30 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(2); + playoutItems.Count.ShouldBe(2); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.AddHours(1)); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.Fallback); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.AddHours(1)); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -358,40 +358,40 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(4); + playoutItems.Count.ShouldBe(4); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.Tail); - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.Tail); - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); } [Test] @@ -456,46 +456,46 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(1); - - playoutItems.Count.Should().Be(5); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.Tail); - - playoutItems[4].MediaItemId.Should().Be(5); - playoutItems[4].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); - playoutItems[4].GuideGroup.Should().Be(1); - playoutItems[4].FillerKind.Should().Be(FillerKind.Fallback); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(1); + + playoutItems.Count.ShouldBe(5); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 49, 0))); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 53, 0))); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.Tail); + + playoutItems[4].MediaItemId.ShouldBe(5); + playoutItems[4].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 57, 0))); + playoutItems[4].GuideGroup.ShouldBe(1); + playoutItems[4].FillerKind.ShouldBe(FillerKind.Fallback); } [Test] @@ -560,26 +560,26 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(0); - enumerator3.State.Index.Should().Be(0); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(0); + enumerator3.State.Index.ShouldBe(0); - playoutItems.Count.Should().Be(1); + playoutItems.Count.ShouldBe(1); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); } [Test] @@ -646,40 +646,40 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); - playoutItems.Count.Should().Be(4); + playoutItems.Count.ShouldBe(4); - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.PostRoll); + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.PostRoll); - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.PostRoll); + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.PostRoll); - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.PostRoll); + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.PostRoll); } [Test] @@ -746,41 +746,41 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutBuilderState.CurrentTime.Should().Be(startState.CurrentTime.AddHours(3)); - playoutItems.Last().FinishOffset.Should().Be(playoutBuilderState.CurrentTime); - - playoutBuilderState.NextGuideGroup.Should().Be(2); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); - - enumerator1.State.Index.Should().Be(1); - enumerator2.State.Index.Should().Be(1); - enumerator3.State.Index.Should().Be(0); - - playoutItems.Count.Should().Be(4); - - playoutItems[0].MediaItemId.Should().Be(1); - playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); - playoutItems[0].GuideGroup.Should().Be(1); - playoutItems[0].FillerKind.Should().Be(FillerKind.None); - - playoutItems[1].MediaItemId.Should().Be(3); - playoutItems[1].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); - playoutItems[1].GuideGroup.Should().Be(1); - playoutItems[1].FillerKind.Should().Be(FillerKind.PostRoll); - - playoutItems[2].MediaItemId.Should().Be(4); - playoutItems[2].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); - playoutItems[2].GuideGroup.Should().Be(1); - playoutItems[2].FillerKind.Should().Be(FillerKind.PostRoll); - - playoutItems[3].MediaItemId.Should().Be(3); - playoutItems[3].StartOffset.Should().Be(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); - playoutItems[3].GuideGroup.Should().Be(1); - playoutItems[3].FillerKind.Should().Be(FillerKind.PostRoll); + playoutBuilderState.CurrentTime.ShouldBe(startState.CurrentTime.AddHours(3)); + playoutItems.Last().FinishOffset.ShouldBe(playoutBuilderState.CurrentTime); + + playoutBuilderState.NextGuideGroup.ShouldBe(2); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); + + enumerator1.State.Index.ShouldBe(1); + enumerator2.State.Index.ShouldBe(1); + enumerator3.State.Index.ShouldBe(0); + + playoutItems.Count.ShouldBe(4); + + playoutItems[0].MediaItemId.ShouldBe(1); + playoutItems[0].StartOffset.ShouldBe(startState.CurrentTime); + playoutItems[0].GuideGroup.ShouldBe(1); + playoutItems[0].FillerKind.ShouldBe(FillerKind.None); + + playoutItems[1].MediaItemId.ShouldBe(3); + playoutItems[1].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 45, 0))); + playoutItems[1].GuideGroup.ShouldBe(1); + playoutItems[1].FillerKind.ShouldBe(FillerKind.PostRoll); + + playoutItems[2].MediaItemId.ShouldBe(4); + playoutItems[2].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 50, 0))); + playoutItems[2].GuideGroup.ShouldBe(1); + playoutItems[2].FillerKind.ShouldBe(FillerKind.PostRoll); + + playoutItems[3].MediaItemId.ShouldBe(3); + playoutItems[3].StartOffset.ShouldBe(startState.CurrentTime.Add(new TimeSpan(2, 55, 0))); + playoutItems[3].GuideGroup.ShouldBe(1); + playoutItems[3].FillerKind.ShouldBe(FillerKind.PostRoll); } [Test] @@ -825,18 +825,18 @@ public class PlayoutModeSchedulerOneTests : SchedulerTestBase HardStop(scheduleItemsEnumerator), _cancellationToken); - playoutItems.Should().BeEmpty(); + playoutItems.ShouldBeEmpty(); - playoutBuilderState.CurrentTime.Should().Be(HardStop(scheduleItemsEnumerator)); + playoutBuilderState.CurrentTime.ShouldBe(HardStop(scheduleItemsEnumerator)); - playoutBuilderState.NextGuideGroup.Should().Be(1); - playoutBuilderState.DurationFinish.IsNone.Should().BeTrue(); - playoutBuilderState.InFlood.Should().BeFalse(); - playoutBuilderState.MultipleRemaining.IsNone.Should().BeTrue(); - playoutBuilderState.InDurationFiller.Should().BeFalse(); - playoutBuilderState.ScheduleItemsEnumerator.State.Index.Should().Be(0); + playoutBuilderState.NextGuideGroup.ShouldBe(1); + playoutBuilderState.DurationFinish.IsNone.ShouldBeTrue(); + playoutBuilderState.InFlood.ShouldBeFalse(); + playoutBuilderState.MultipleRemaining.IsNone.ShouldBeTrue(); + playoutBuilderState.InDurationFiller.ShouldBeFalse(); + playoutBuilderState.ScheduleItemsEnumerator.State.Index.ShouldBe(0); - enumerator.State.Index.Should().Be(0); + enumerator.State.Index.ShouldBe(0); } protected override ProgramScheduleItem NextScheduleItem => new ProgramScheduleItemOne diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs index 55ba8124..7dd90d5c 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutTemplateSelectorTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -31,7 +31,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 3, 31, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -53,7 +53,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 4, 1, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -75,7 +75,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 4, 20, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -97,7 +97,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 6, 15, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -119,7 +119,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 6, 16, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -141,7 +141,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 2, 28, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -163,7 +163,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 3, 1, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -185,7 +185,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 2, 28, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -207,7 +207,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 3, 1, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -229,7 +229,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 6, 14, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -251,7 +251,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 6, 15, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -273,7 +273,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 7, 20, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -295,7 +295,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 4, 1, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -317,7 +317,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2024, 4, 2, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -339,7 +339,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 2, 28, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } [Test] @@ -361,7 +361,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 3, 1, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -383,7 +383,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 2, 28, 0, 0, 0, Offset)); - result.IsSome.Should().BeTrue(); + result.IsSome.ShouldBeTrue(); } [Test] @@ -405,7 +405,7 @@ public static class PlayoutTemplateSelectorTests new List { template }, new DateTimeOffset(2023, 3, 1, 0, 0, 0, Offset)); - result.IsNone.Should().BeTrue(); + result.IsNone.ShouldBeTrue(); } } } diff --git a/ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs b/ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs index 9b413a23..22230046 100644 --- a/ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -34,14 +34,14 @@ public class RandomizedContentTests var list = new List(); for (var i = 1; i <= 10; i++) { - randomizedContent.Current.IsSome.Should().BeTrue(); + randomizedContent.Current.IsSome.ShouldBeTrue(); randomizedContent.Current.Do(c => list.Add(c.Id)); randomizedContent.MoveNext(); } - list.Should().NotEqual(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - list.Should().NotEqual(new[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }); + list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + list.ShouldNotBe([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]); } [Test] @@ -54,7 +54,7 @@ public class RandomizedContentTests for (var i = 1; i <= 10; i++) { - randomizedContent.State.Index.Should().Be(i); + randomizedContent.State.Index.ShouldBe(i); randomizedContent.MoveNext(); } @@ -70,10 +70,10 @@ public class RandomizedContentTests for (var i = 6; i <= 99; i++) { - randomizedContent.Current.IsSome.Should().BeTrue(); + randomizedContent.Current.IsSome.ShouldBeTrue(); // this test data setup/expectation is confusing - randomizedContent.Current.Map(c => c.Id).IfNone(-1).Should().Be(_expected[i - 2]); - randomizedContent.State.Index.Should().Be(i); + randomizedContent.Current.Map(c => c.Id).IfNone(-1).ShouldBe(_expected[i - 2]); + randomizedContent.State.Index.ShouldBe(i); randomizedContent.MoveNext(); } diff --git a/ErsatzTV.Core.Tests/Scheduling/SeasonEpisodeContentTests.cs b/ErsatzTV.Core.Tests/Scheduling/SeasonEpisodeContentTests.cs index bbdb6679..b0407d51 100644 --- a/ErsatzTV.Core.Tests/Scheduling/SeasonEpisodeContentTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/SeasonEpisodeContentTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -23,8 +23,8 @@ public class SeasonEpisodeContentTests for (var i = 1; i <= 10; i++) { - chronologicalContent.Current.IsSome.Should().BeTrue(); - chronologicalContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); + chronologicalContent.Current.IsSome.ShouldBeTrue(); + chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); chronologicalContent.MoveNext(); } } @@ -39,7 +39,7 @@ public class SeasonEpisodeContentTests for (var i = 0; i < 10; i++) { - chronologicalContent.State.Index.Should().Be(i % 10); + chronologicalContent.State.Index.ShouldBe(i % 10); chronologicalContent.MoveNext(); } } @@ -54,9 +54,9 @@ public class SeasonEpisodeContentTests for (var i = 6; i <= 10; i++) { - chronologicalContent.Current.IsSome.Should().BeTrue(); - chronologicalContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); - chronologicalContent.State.Index.Should().Be(i - 1); + chronologicalContent.Current.IsSome.ShouldBeTrue(); + chronologicalContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); + chronologicalContent.State.Index.ShouldBe(i - 1); chronologicalContent.MoveNext(); } } @@ -69,8 +69,8 @@ public class SeasonEpisodeContentTests var chronologicalContent = new SeasonEpisodeMediaCollectionEnumerator(contents, state); - chronologicalContent.State.Index.Should().Be(0); - chronologicalContent.State.Seed.Should().Be(0); + chronologicalContent.State.Index.ShouldBe(0); + chronologicalContent.State.Seed.ShouldBe(0); } private static List Episodes(int count) => diff --git a/ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs b/ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs index 779d3161..ebfe8a29 100644 --- a/ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Scheduling; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.Core.Tests.Scheduling; @@ -30,7 +30,7 @@ public class ShuffledContentTests var list = new List(); for (var i = 1; i <= 1000; i++) { - shuffledContent.Current.IsSome.Should().BeTrue(); + shuffledContent.Current.IsSome.ShouldBeTrue(); shuffledContent.Current.Do(x => list.Add(x.Id)); shuffledContent.MoveNext(); } @@ -57,12 +57,12 @@ public class ShuffledContentTests var list = new List(); for (var i = 1; i <= 10; i++) { - shuffledContent.Current.IsSome.Should().BeTrue(); + shuffledContent.Current.IsSome.ShouldBeTrue(); shuffledContent.Current.Do(x => list.Add(x.Id)); shuffledContent.MoveNext(); } - list.Should().Equal(1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + list.ShouldBe([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); } [Test] @@ -78,13 +78,13 @@ public class ShuffledContentTests var list = new List(); for (var i = 1; i <= 10; i++) { - shuffledContent.Current.IsSome.Should().BeTrue(); + shuffledContent.Current.IsSome.ShouldBeTrue(); shuffledContent.Current.Do(x => list.Add(x.Id)); shuffledContent.MoveNext(); } - list.Should().NotEqual(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - list.Should().BeEquivalentTo(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + list.ShouldNotBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + list.ShouldBe([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ignoreOrder: true); } [Test] @@ -98,7 +98,7 @@ public class ShuffledContentTests for (var i = 0; i < 10; i++) { - shuffledContent.State.Index.Should().Be(i); + shuffledContent.State.Index.ShouldBe(i); shuffledContent.MoveNext(); } } @@ -114,9 +114,9 @@ public class ShuffledContentTests for (var i = 6; i <= 10; i++) { - shuffledContent.Current.IsSome.Should().BeTrue(); - shuffledContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); - shuffledContent.State.Index.Should().Be(i - 1); + shuffledContent.Current.IsSome.ShouldBeTrue(); + shuffledContent.Current.Map(x => x.Id).IfNone(-1).ShouldBe(i); + shuffledContent.State.Index.ShouldBe(i - 1); shuffledContent.MoveNext(); } } @@ -130,8 +130,8 @@ public class ShuffledContentTests var groupedMediaItems = contents.Map(mi => new GroupedMediaItem(mi, null)).ToList(); var shuffledContent = new ShuffledMediaCollectionEnumerator(groupedMediaItems, state, _cancellationToken); - shuffledContent.State.Index.Should().Be(0); - shuffledContent.State.Seed.Should().NotBe(MagicSeed); + shuffledContent.State.Index.ShouldBe(0); + shuffledContent.State.Seed.ShouldNotBe(MagicSeed); } private static List Episodes(int count) => diff --git a/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs b/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs index c2b1d45f..49ee1122 100644 --- a/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs +++ b/ErsatzTV.FFmpeg.Tests/Capabilities/Vaapi/VaapiCapabilityParserTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using ErsatzTV.FFmpeg.Capabilities.Vaapi; -using FluentAssertions; +using Shouldly; using NUnit.Framework; namespace ErsatzTV.FFmpeg.Tests.Capabilities.Vaapi; @@ -185,8 +185,8 @@ VAProfileNone/VAEntrypointVideoProc List brief = VaapiCapabilityParser.Parse(BriefOutput); List full = VaapiCapabilityParser.ParseFull(FullOutput); - brief.Count.Should().Be(20); - full.Count.Should().Be(20); + brief.Count.ShouldBe(20); + full.Count.ShouldBe(20); } [Test] @@ -194,11 +194,11 @@ VAProfileNone/VAEntrypointVideoProc { List full = VaapiCapabilityParser.ParseFull(FullOutput); - full.Count.Should().Be(20); - full.Count(e => e.VaapiEntrypoint.StartsWith("VAEntrypointEnc")).Should().BeGreaterThan(0); + full.Count.ShouldBe(20); + full.Count(e => e.VaapiEntrypoint.StartsWith("VAEntrypointEnc")).ShouldBeGreaterThan(0); foreach (VaapiProfileEntrypoint entrypoint in full.Where(e => e.VaapiEntrypoint.StartsWith("VAEntrypointEnc"))) { - entrypoint.RateControlModes.Count.Should().BeGreaterThan(0); + entrypoint.RateControlModes.Count.ShouldBeGreaterThan(0); } } } diff --git a/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj b/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj index 6ca0258d..d2ec859c 100644 --- a/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj +++ b/ErsatzTV.FFmpeg.Tests/ErsatzTV.FFmpeg.Tests.csproj @@ -8,12 +8,12 @@ - + diff --git a/ErsatzTV.FFmpeg.Tests/Filter/WatermarkOpacityFilterTests.cs b/ErsatzTV.FFmpeg.Tests/Filter/WatermarkOpacityFilterTests.cs index a6a06723..c8afde2e 100644 --- a/ErsatzTV.FFmpeg.Tests/Filter/WatermarkOpacityFilterTests.cs +++ b/ErsatzTV.FFmpeg.Tests/Filter/WatermarkOpacityFilterTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using ErsatzTV.FFmpeg.Filter; using ErsatzTV.FFmpeg.State; -using FluentAssertions; +using Shouldly; using LanguageExt; using NUnit.Framework; @@ -26,7 +26,7 @@ public class WatermarkOpacityFilterTests 75, false)); - filter.Filter.Should().Be("format=yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8,colorchannelmixer=aa=0.75"); + filter.Filter.ShouldBe("format=yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8,colorchannelmixer=aa=0.75"); } [Test] @@ -44,6 +44,6 @@ public class WatermarkOpacityFilterTests 75, false)); - filter.Filter.Should().Be("format=yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8,colorchannelmixer=aa=0.75"); + filter.Filter.ShouldBe("format=yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8,colorchannelmixer=aa=0.75"); } } diff --git a/ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs b/ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs index dd851cf9..dff1cfbe 100644 --- a/ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs +++ b/ErsatzTV.FFmpeg.Tests/PipelineBuilderBaseTests.cs @@ -8,7 +8,7 @@ using ErsatzTV.FFmpeg.OutputFormat; using ErsatzTV.FFmpeg.Pipeline; using ErsatzTV.FFmpeg.Preset; using ErsatzTV.FFmpeg.State; -using FluentAssertions; +using Shouldly; using LanguageExt; using Microsoft.Extensions.Logging; using NSubstitute; @@ -110,11 +110,11 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.Build(ffmpegState, desiredState); - result.PipelineSteps.Should().HaveCountGreaterThan(0); - result.PipelineSteps.Should().Contain(ps => ps is EncoderLibx265); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); + result.PipelineSteps.ShouldContain(ps => ps is EncoderLibx265); string command = PrintCommand(videoInputFile, audioInputFile, None, None, result); - command.Should().Be( + command.ShouldBe( "-threads 1 -nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -ss 00:00:01 -c:v h264 -readrate 1.0 -i /tmp/whatever.mkv -filter_complex [0:1]aresample=async=1:first_pts=0[a] -map 0:0 -map [a] -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -bf 0 -sc_threshold 0 -video_track_timescale 90000 -b:v 2000k -maxrate:v 2000k -bufsize:v 4000k -c:v libx265 -tag:v hvc1 -x265-params log-level=error -c:a aac -b:a 320k -maxrate:a 320k -bufsize:a 640k -ar 48k -f mpegts -mpegts_flags +initial_discontinuity pipe:1"); } @@ -206,11 +206,11 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.Build(ffmpegState, desiredState); - result.PipelineSteps.Should().HaveCountGreaterThan(0); - result.PipelineSteps.Should().Contain(ps => ps is EncoderLibx265); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); + result.PipelineSteps.ShouldContain(ps => ps is EncoderLibx265); string command = PrintCommand(videoInputFile, audioInputFile, None, None, result); - command.Should().Be( + command.ShouldBe( "-threads 1 -nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -ss 00:00:01 -c:v h264 -readrate 1.0 -i /tmp/whatever.mkv -filter_complex [0:1]aresample=async=1:first_pts=0[a] -map 0:0 -map [a] -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -bf 0 -sc_threshold 0 -video_track_timescale 90000 -b:v 2000k -maxrate:v 2000k -bufsize:v 4000k -c:v libx265 -tag:v hvc1 -x265-params log-level=error -c:a aac -ac 6 -b:a 320k -maxrate:a 320k -bufsize:a 640k -ar 48k -f mpegts -mpegts_flags +initial_discontinuity pipe:1"); } @@ -233,11 +233,11 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.Concat(concatInputFile, FFmpegState.Concat(false, "Some Channel")); - result.PipelineSteps.Should().HaveCountGreaterThan(0); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); string command = PrintCommand(None, None, None, concatInputFile, result); - command.Should().Be( + command.ShouldBe( "-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -f concat -safe 0 -protocol_whitelist file,http,tcp,https,tcp,tls -probesize 32 -readrate 1.0 -stream_loop -1 -i http://localhost:8080/ffmpeg/concat/1 -muxdelay 0 -muxpreload 0 -movflags +faststart -flags cgop -sc_threshold 0 -c copy -map_metadata -1 -metadata service_provider=\"ErsatzTV\" -metadata service_name=\"Some Channel\" -f mpegts -mpegts_flags +initial_discontinuity pipe:1"); } @@ -262,11 +262,11 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.WrapSegmenter(concatInputFile, FFmpegState.Concat(false, "Some Channel")); - result.PipelineSteps.Should().HaveCountGreaterThan(0); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); string command = PrintCommand(None, None, None, concatInputFile, result); - command.Should().Be( + command.ShouldBe( "-nostdin -threads 1 -hide_banner -loglevel error -nostats -fflags +genpts+discardcorrupt+igndts -readrate 1.0 -i http://localhost:8080/iptv/channel/1.m3u8?mode=segmenter -map 0 -c copy -metadata service_provider=\"ErsatzTV\" -metadata service_name=\"Some Channel\" -f mpegts pipe:1"); } @@ -358,15 +358,15 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.Build(ffmpegState, desiredState); - result.PipelineSteps.Should().HaveCountGreaterThan(0); - result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyVideo); - result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyAudio); - videoInputFile.InputOptions.Should().Contain(io => io is ReadrateInputOption); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); + result.PipelineSteps.ShouldContain(ps => ps is EncoderCopyVideo); + result.PipelineSteps.ShouldContain(ps => ps is EncoderCopyAudio); + videoInputFile.InputOptions.ShouldContain(io => io is ReadrateInputOption); string command = PrintCommand(videoInputFile, audioInputFile, None, None, result); // 0.4.0 reference: "-nostdin -threads 1 -hide_banner -loglevel error -nostats -fflags +genpts+discardcorrupt+igndts -re -ss 00:14:33.6195516 -i /tmp/whatever.mkv -map 0:0 -map 0:a -c:v copy -flags cgop -sc_threshold 0 -c:a copy -movflags +faststart -muxdelay 0 -muxpreload 0 -metadata service_provider="ErsatzTV" -metadata service_name="ErsatzTV" -t 00:06:39.6934484 -f mpegts -mpegts_flags +initial_discontinuity pipe:1" - command.Should().Be( + command.ShouldBe( "-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -readrate 1.0 -i /tmp/whatever.mkv -map 0:0 -map 0:1 -muxdelay 0 -muxpreload 0 -movflags +faststart+frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov+delay_moov -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mp4 pipe:1"); } @@ -448,13 +448,13 @@ public class PipelineBuilderBaseTests _logger); FFmpegPipeline result = builder.Build(ffmpegState, desiredState); - result.PipelineSteps.Should().HaveCountGreaterThan(0); - result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyVideo); - result.PipelineSteps.Should().Contain(ps => ps is EncoderCopyAudio); + result.PipelineSteps.Count.ShouldBeGreaterThan(0); + result.PipelineSteps.ShouldContain(ps => ps is EncoderCopyVideo); + result.PipelineSteps.ShouldContain(ps => ps is EncoderCopyAudio); string command = PrintCommand(videoInputFile, audioInputFile, None, None, result); - command.Should().Be( + command.ShouldBe( "-nostdin -hide_banner -nostats -loglevel error -fflags +genpts+discardcorrupt+igndts -readrate 1.0 -i /tmp/whatever.mkv -map 0:0 -map 0:a -muxdelay 0 -muxpreload 0 -movflags +faststart+frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov+delay_moov -flags cgop -sc_threshold 0 -c:v copy -c:a copy -f mp4 pipe:1"); } @@ -497,7 +497,7 @@ public class PipelineBuilderBaseTests string command = PrintCommand(videoInputFile, None, None, None, result); - command.Should().Be( + command.ShouldBe( "-nostdin -hide_banner -nostats -loglevel error -i /test/input/file.png -vf scale=-1:200:force_original_aspect_ratio=decrease /test/output/file.jpg"); } diff --git a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs index e5784dfb..a8760236 100644 --- a/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs +++ b/ErsatzTV.FFmpeg/Pipeline/NvidiaPipelineBuilder.cs @@ -83,7 +83,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder && videoStream.ColorParams.IsHdr && string.IsNullOrWhiteSpace(System.Environment.GetEnvironmentVariable("ETV_DISABLE_VULKAN")); - if (decodeCapability == FFmpegCapability.Hardware || encodeCapability == FFmpegCapability.Hardware) + if (decodeCapability == FFmpegCapability.Hardware) { pipelineSteps.Add(new CudaHardwareAccelerationOption(isHdrTonemap)); } @@ -118,18 +118,7 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder Option maybeDecoder = (ffmpegState.DecoderHardwareAccelerationMode, videoStream.Codec) switch { - (HardwareAccelerationMode.Nvenc, VideoFormat.Hevc) => new DecoderHevcCuvid(HardwareAccelerationMode.Nvenc), - (HardwareAccelerationMode.Nvenc, VideoFormat.H264) => new DecoderH264Cuvid(HardwareAccelerationMode.Nvenc), - (HardwareAccelerationMode.Nvenc, VideoFormat.Mpeg2Video) => new DecoderMpeg2Cuvid( - HardwareAccelerationMode.Nvenc, - context.ShouldDeinterlace), - (HardwareAccelerationMode.Nvenc, VideoFormat.Vc1) => new DecoderVc1Cuvid(HardwareAccelerationMode.Nvenc), - (HardwareAccelerationMode.Nvenc, VideoFormat.Vp9) => new DecoderVp9Cuvid(HardwareAccelerationMode.Nvenc), - (HardwareAccelerationMode.Nvenc, VideoFormat.Mpeg4) => - new DecoderMpeg4Cuvid(HardwareAccelerationMode.Nvenc), - (HardwareAccelerationMode.Nvenc, VideoFormat.Av1) => - new DecoderAv1Cuvid(HardwareAccelerationMode.Nvenc), - + (HardwareAccelerationMode.Nvenc, _) => new DecoderImplicitCuda(), _ => GetSoftwareDecoder(videoStream) }; diff --git a/ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs b/ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs index 4d84b124..714304d4 100644 --- a/ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs +++ b/ErsatzTV.Infrastructure.Tests/Data/Repositories/Caching/CachingSearchRepositoryTests.cs @@ -1,6 +1,6 @@ using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Infrastructure.Data.Repositories.Caching; -using FluentAssertions; +using Shouldly; using LanguageExt; using NSubstitute; using NUnit.Framework; @@ -25,9 +25,9 @@ public class CachingSearchRepositoryTests var repo = new CachingSearchRepository(searchRepo); List result1 = await repo.GetAllThreeLetterLanguageCodes(englishMediaCodes); - result1.Should().BeEquivalentTo(englishResult); + result1.ShouldBeEquivalentTo(englishResult); List result2 = await repo.GetAllThreeLetterLanguageCodes(frenchMediaCodes); - result2.Should().BeEquivalentTo(frenchResult); + result2.ShouldBeEquivalentTo(frenchResult); } } diff --git a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj index 72931117..3ffb2191 100644 --- a/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj +++ b/ErsatzTV.Infrastructure.Tests/ErsatzTV.Infrastructure.Tests.csproj @@ -9,7 +9,6 @@ - @@ -22,6 +21,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/ErsatzTV.Infrastructure.Tests/Metadata/LocalStatisticsProviderTests.cs b/ErsatzTV.Infrastructure.Tests/Metadata/LocalStatisticsProviderTests.cs index e7af238e..70330334 100644 --- a/ErsatzTV.Infrastructure.Tests/Metadata/LocalStatisticsProviderTests.cs +++ b/ErsatzTV.Infrastructure.Tests/Metadata/LocalStatisticsProviderTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Metadata; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Infrastructure.Metadata; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -43,6 +43,6 @@ public class LocalStatisticsProviderTests MediaVersion result = provider.ProjectToMediaVersion("test", input); - result.Duration.Should().Be(TimeSpan.FromSeconds(123.45)); + result.Duration.ShouldBe(TimeSpan.FromSeconds(123.45)); } } diff --git a/ErsatzTV.Infrastructure.Tests/Search/SearchQueryParserTests.cs b/ErsatzTV.Infrastructure.Tests/Search/SearchQueryParserTests.cs index 9fc0fb15..ddb2f3b1 100644 --- a/ErsatzTV.Infrastructure.Tests/Search/SearchQueryParserTests.cs +++ b/ErsatzTV.Infrastructure.Tests/Search/SearchQueryParserTests.cs @@ -1,5 +1,5 @@ using ErsatzTV.Infrastructure.Search; -using FluentAssertions; +using Shouldly; using Lucene.Net.Search; using NUnit.Framework; @@ -17,7 +17,7 @@ public class SearchQueryParserTests public void Test(string input, string expected) { Query result = SearchQueryParser.ParseQuery(input); - result.ToString().Should().Be(expected); + result.ToString().ShouldBe(expected); } } } diff --git a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs index 5b358d48..5d896b54 100644 --- a/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/FFmpeg/TranscodingTests.cs @@ -25,7 +25,7 @@ using ErsatzTV.FFmpeg.State; using ErsatzTV.Infrastructure.Images; using ErsatzTV.Infrastructure.Metadata; using ErsatzTV.Infrastructure.Runtime; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using NSubstitute; @@ -109,18 +109,18 @@ public class TranscodingTests { public static Watermark[] Watermarks = [ - Watermark.None - //Watermark.PermanentOpaqueScaled, - // Watermark.PermanentOpaqueActualSize, - //Watermark.PermanentTransparentScaled - // Watermark.PermanentTransparentActualSize + Watermark.None, + Watermark.PermanentOpaqueScaled, + Watermark.PermanentOpaqueActualSize, + Watermark.PermanentTransparentScaled, + Watermark.PermanentTransparentActualSize ]; public static Subtitle[] Subtitles = [ - Subtitle.None - //Subtitle.Picture, - //Subtitle.Text + Subtitle.None, + Subtitle.Picture, + Subtitle.Text ]; public static Padding[] Paddings = @@ -190,7 +190,7 @@ public class TranscodingTests public static FFmpegProfileVideoFormat[] VideoFormats = [ - FFmpegProfileVideoFormat.H264, + //FFmpegProfileVideoFormat.H264, FFmpegProfileVideoFormat.Hevc // FFmpegProfileVideoFormat.Mpeg2Video ]; @@ -199,7 +199,7 @@ public class TranscodingTests [ HardwareAccelerationKind.None, //HardwareAccelerationKind.Nvenc, - HardwareAccelerationKind.Vaapi + //HardwareAccelerationKind.Vaapi //HardwareAccelerationKind.Qsv, // HardwareAccelerationKind.VideoToolbox, // HardwareAccelerationKind.Amf @@ -209,7 +209,7 @@ public class TranscodingTests [ StreamingMode.TransportStream, //StreamingMode.HttpLiveStreamingSegmenter, - StreamingMode.HttpLiveStreamingSegmenterV2 + //StreamingMode.HttpLiveStreamingSegmenterV2 ]; public static string[] FilesToTest => [string.Empty]; @@ -245,6 +245,12 @@ public class TranscodingTests Arg.Any>()) .Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "ErsatzTV.png")); + mockImageCache.GetPathForImage( + Arg.Any(), + Arg.Is(x => x == ArtworkKind.Thumbnail), + Arg.Any>()) + .Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "song_album_cover_512.png")); + var oldService = new FFmpegProcessService( new FakeStreamSelector(), mockImageCache, @@ -484,7 +490,7 @@ public class TranscodingTests if (videoScanKind == VideoScanKind.Interlaced) { - v.VideoScanKind.Should().Be(VideoScanKind.Interlaced, file); + v.VideoScanKind.ShouldBe(VideoScanKind.Interlaced, file); } var subtitleStreams = v.Streams @@ -559,7 +565,7 @@ public class TranscodingTests bool hasDeinterlaceFilter = filterChain.VideoFilterSteps.Any( s => s is YadifFilter or YadifCudaFilter or DeinterlaceQsvFilter or DeinterlaceVaapiFilter); - hasDeinterlaceFilter.Should().Be(videoScanKind == VideoScanKind.Interlaced); + hasDeinterlaceFilter.ShouldBe(videoScanKind == VideoScanKind.Interlaced); bool hasScaling = filterChain.VideoFilterSteps.Filter( s => s is ScaleFilter or ScaleCudaFilter or ScaleQsvFilter or ScaleVaapiFilter) @@ -569,7 +575,7 @@ public class TranscodingTests // TODO: sometimes scaling is used for pixel format, so this is harder to assert the absence if (profileResolution.Width != 1920 && profileResolution.Width != 640) { - hasScaling.Should().BeTrue(); + hasScaling.ShouldBeTrue(); } // TODO: bit depth @@ -577,16 +583,16 @@ public class TranscodingTests bool hasPadding = filterChain.VideoFilterSteps.Any(s => s is PadFilter); // TODO: optimize out padding - // hasPadding.Should().Be(padding == Padding.WithPadding); + // hasPadding.ShouldBe(padding == Padding.WithPadding); if (padding is Padding.WithPadding && scalingBehavior is not ScalingBehavior.Crop) { - hasPadding.Should().BeTrue(); + hasPadding.ShouldBeTrue(); } bool hasCrop = filterChain.VideoFilterSteps.Any(s => s is CropFilter); if (scalingBehavior is ScalingBehavior.Crop) { - hasCrop.Should().BeTrue(); + hasCrop.ShouldBeTrue(); } bool hasSubtitleFilters = @@ -597,12 +603,12 @@ public class TranscodingTests or OverlaySubtitleQsvFilter or OverlaySubtitleVaapiFilter); - hasSubtitleFilters.Should().Be(subtitle != Subtitle.None); + hasSubtitleFilters.ShouldBe(subtitle != Subtitle.None); bool hasWatermarkFilters = filterChain.WatermarkOverlayFilterSteps.Any( s => s is OverlayWatermarkFilter or OverlayWatermarkCudaFilter or OverlayWatermarkQsvFilter); - hasWatermarkFilters.Should().Be(watermark != Watermark.None); + hasWatermarkFilters.ShouldBe(watermark != Watermark.None); } FFmpegLibraryProcessService service = GetService(); @@ -780,7 +786,7 @@ public class TranscodingTests ? p1.StandardError : p1.StandardOutput; - p1.ExitCode.Should().Be(0, output); + p1.ExitCode.ShouldBe(0, output); switch (subtitle) { @@ -813,7 +819,7 @@ public class TranscodingTests } } - p2.ExitCode.Should().Be(0); + p2.ExitCode.ShouldBe(0); await SetInterlacedFlag(tempFileName, sourceFile, file, videoScanKind == VideoScanKind.Interlaced); @@ -850,7 +856,7 @@ public class TranscodingTests } } - p.ExitCode.Should().Be(0); + p.ExitCode.ShouldBe(0); } private static string GetStringSha256Hash(string text) @@ -877,6 +883,12 @@ public class TranscodingTests Arg.Any>()) .Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "ErsatzTV.png")); + imageCache.GetPathForImage( + Arg.Any(), + Arg.Is(x => x == ArtworkKind.Thumbnail), + Arg.Any>()) + .Returns(Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "song_album_cover_512.png")); + var oldService = new FFmpegProcessService( new FakeStreamSelector(), imageCache, @@ -956,7 +968,7 @@ public class TranscodingTests if (profileAcceleration != HardwareAccelerationKind.None && isUnsupported) { - result.ExitCode.Should().Be(1, $"Error message with successful exit code? {process.Arguments}"); + result.ExitCode.ShouldBe(1, $"Error message with successful exit code? {process.Arguments}"); Assert.Warn($"Unsupported on this hardware: ffmpeg {process.Arguments}"); } else if (error.Contains("Impossible to convert between")) @@ -973,7 +985,7 @@ public class TranscodingTests ' ', process.Arguments.Split(" ").Map(a => a.Contains('[') ? $"\"{a}\"" : a)); - result.ExitCode.Should().Be(0, error + Environment.NewLine + arguments); + result.ExitCode.ShouldBe(0, error + Environment.NewLine + arguments); if (result.ExitCode == 0) { Console.WriteLine(process.Arguments); @@ -998,11 +1010,11 @@ public class TranscodingTests MediaVersion v = getFinalMediaVersion(); // verify de-interlace - v.VideoScanKind.Should().NotBe(VideoScanKind.Interlaced); + v.VideoScanKind.ShouldNotBe(VideoScanKind.Interlaced); // verify resolution - v.Height.Should().Be(profileResolution.Height); - v.Width.Should().Be(profileResolution.Width); + v.Height.ShouldBe(profileResolution.Height); + v.Width.ShouldBe(profileResolution.Width); foreach (MediaStream videoStream in v.Streams.Filter(s => s.MediaStreamKind == MediaStreamKind.Video)) { @@ -1014,7 +1026,7 @@ public class TranscodingTests _ => PixelFormat.YUV420P }; - videoStream.PixelFormat.Should().Be(expectedPixelFormat); + videoStream.PixelFormat.ShouldBe(expectedPixelFormat); // verify colors var colorParams = new ColorParams( @@ -1032,7 +1044,7 @@ public class TranscodingTests (profileAcceleration != HardwareAccelerationKind.Vaapi || vaapiDriver != VaapiDriver.RadeonSI) && streamingMode != StreamingMode.HttpLiveStreamingSegmenterV2) { - colorParams.IsBt709.Should().BeTrue($"{colorParams}"); + colorParams.IsBt709.ShouldBeTrue($"{colorParams}"); } } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/LocalSubtitlesProviderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/LocalSubtitlesProviderTests.cs index 1a90bdf3..526acdb9 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/LocalSubtitlesProviderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/LocalSubtitlesProviderTests.cs @@ -3,7 +3,7 @@ using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Scanner.Core.Metadata; using ErsatzTV.Scanner.Tests.Core.Fakes; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using NSubstitute; using NUnit.Framework; @@ -57,14 +57,14 @@ public class LocalSubtitlesProviderTests @"/Movies/Avatar (2009)/Avatar (2009).mkv", true); - result.Count.Should().Be(5); - result.Count(s => s.Language == "eng").Should().Be(3); - result.Count(s => s.Language == "deu").Should().Be(2); - result.Count(s => s.Forced).Should().Be(2); - result.Count(s => s.SDH).Should().Be(2); - result.Count(s => s.Codec == "subrip").Should().Be(4); - result.Count(s => s.Codec == "ass").Should().Be(1); - result.All(s => s.Path.Contains(@"/Movies/Avatar (2009)/")).Should().BeTrue(); + result.Count.ShouldBe(5); + result.Count(s => s.Language == "eng").ShouldBe(3); + result.Count(s => s.Language == "deu").ShouldBe(2); + result.Count(s => s.Forced).ShouldBe(2); + result.Count(s => s.SDH).ShouldBe(2); + result.Count(s => s.Codec == "subrip").ShouldBe(4); + result.Count(s => s.Codec == "ass").ShouldBe(1); + result.All(s => s.Path.Contains(@"/Movies/Avatar (2009)/")).ShouldBeTrue(); } [Test] @@ -102,13 +102,13 @@ public class LocalSubtitlesProviderTests @"/Movies/Avatar (2009)/Avatar (2009).mkv", false); - result.Count.Should().Be(7); - result.Count(s => s.Language == "eng").Should().Be(5); - result.Count(s => s.Language == "deu").Should().Be(2); - result.Count(s => s.Forced).Should().Be(3); - result.Count(s => s.SDH).Should().Be(3); - result.Count(s => s.Codec == "subrip").Should().Be(5); - result.Count(s => s.Codec == "ass").Should().Be(2); - result.Count(s => s.Path.Contains(@"/Movies/Avatar (2009)/")).Should().Be(0); + result.Count.ShouldBe(7); + result.Count(s => s.Language == "eng").ShouldBe(5); + result.Count(s => s.Language == "deu").ShouldBe(2); + result.Count(s => s.Forced).ShouldBe(3); + result.Count(s => s.SDH).ShouldBe(3); + result.Count(s => s.Codec == "subrip").ShouldBe(5); + result.Count(s => s.Codec == "ass").ShouldBe(2); + result.Count(s => s.Path.Contains(@"/Movies/Avatar (2009)/")).ShouldBe(0); } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs index e7d715e9..05c61cbf 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/MovieFolderScannerTests.cs @@ -11,7 +11,7 @@ using ErsatzTV.Scanner.Core.Interfaces.FFmpeg; using ErsatzTV.Scanner.Core.Interfaces.Metadata; using ErsatzTV.Scanner.Core.Metadata; using ErsatzTV.Scanner.Tests.Core.Fakes; -using FluentAssertions; +using Shouldly; using MediatR; using Microsoft.Extensions.Logging; using NSubstitute; @@ -109,7 +109,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -153,7 +153,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -196,7 +196,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -240,7 +240,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -288,7 +288,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -337,7 +337,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -386,7 +386,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -434,7 +434,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -478,7 +478,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -524,7 +524,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -564,7 +564,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _movieRepository.Received(1).GetOrAdd( Arg.Any(), @@ -609,7 +609,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _mediaItemRepository.Received(1).FlagFileNotFound(Arg.Any(), Arg.Any()); await _mediaItemRepository.Received(1).FlagFileNotFound(libraryPath, oldMoviePath); @@ -638,7 +638,7 @@ public class MovieFolderScannerTests 1, CancellationToken.None); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); await _mediaItemRepository.Received(1).FlagFileNotFound(Arg.Any(), Arg.Any()); await _mediaItemRepository.Received(1).FlagFileNotFound(libraryPath, oldMoviePath); diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs index c2da8f2e..f6da7b52 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ArtistNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using Microsoft.IO; using NSubstitute; @@ -44,7 +44,7 @@ public class ArtistNfoReaderTests Either result = await _artistNfoReader.Read(stream); - result.IsLeft.Should().BeTrue(); + result.IsLeft.ShouldBeTrue(); } [Test] @@ -54,7 +54,7 @@ public class ArtistNfoReaderTests Either result = await _artistNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -67,7 +67,7 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _artistNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -121,14 +121,14 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _artistNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ArtistNfo nfo in result.RightToSeq()) { - nfo.Name.Should().Be("Billy Joel"); - nfo.Disambiguation.Should().BeNullOrEmpty(); - nfo.Genres.Should().BeEquivalentTo(new List { "Pop/Rock" }); - nfo.Styles.Should().BeEquivalentTo( + nfo.Name.ShouldBe("Billy Joel"); + nfo.Disambiguation.ShouldBeNullOrEmpty(); + nfo.Genres.ShouldBeEquivalentTo(new List { "Pop/Rock" }); + nfo.Styles.ShouldBeEquivalentTo( new List { "Album Rock", @@ -137,7 +137,7 @@ https://www.themoviedb.org/movie/11-star-wars")); "Soft Rock", "Keyboard" }); - nfo.Moods.Should().BeEquivalentTo( + nfo.Moods.ShouldBeEquivalentTo( new List { "Amiable/Good-Natured", @@ -150,7 +150,7 @@ https://www.themoviedb.org/movie/11-star-wars")); "Cynical/Sarcastic", "Earnest" }); - nfo.Biography.Should().Be( + nfo.Biography.ShouldBe( NormalizeLineEndingsLF( @"William Martin ""Billy"" Joel (born May 9, 1949, New York, USA) is an American pianist, singer-songwriter, and composer. Since releasing his first hit song, ""Piano Man"", in 1973, Joel has become the sixth-best-selling recording artist and the third-best-selling solo artist in the United States, according to the RIAA. His compilation album Greatest Hits Vol. 1 & 2 is the third-best-selling album in the United States by discs shipped. Joel had Top 40 hits in the 1970s, 1980s, and 1990s, achieving 33 Top 40 hits in the United States, all of which he wrote himself. He is also a six-time Grammy Award winner, a 23-time Grammy nominee and one of the world's best-selling artists of all time, having sold over 150 million records worldwide. He was inducted into the Songwriter's Hall of Fame (1992), the Rock and Roll Hall of Fame (1999), and the Long Island Music Hall of Fame (2006). In 2008, Billboard magazine released a list of the Hot 100 All-Time Top Artists to celebrate the US singles chart's 50th anniversary, with Billy Joel positioned at No. 23. With the exception of the 2007 songs ""All My Life"" and ""Christmas in Fallujah"", Joel stopped writing and recording popular music after 1993's River of Dreams, but he continued to tour extensively until 2010. Joel was born in the Bronx, May 9, 1949 and raised in Hicksville, New York in a Levitt home. His father, Howard (born Helmuth), was born in Germany, the son of German merchant and manufacturer Karl Amson Joel, who, after the advent of the Nazi regime, emigrated to Switzerland and later to the United States. Billy Joel's mother, Rosalind Nyman, was born in England to Philip and Rebecca Nyman. Both of Joel's parents were Jewish. They divorced in 1960, and his father moved to Vienna, Austria. Billy has a sister, Judith Joel, and a half-brother, Alexander Joel, who is an acclaimed classical conductor in Europe and currently chief musical director of the Staatstheater Braunschweig. @@ -167,10 +167,10 @@ Joel attended Hicksville High School in 1967, but he did not graduate with his c Either result = await _artistNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ArtistNfo nfo in result.RightToSeq()) { - nfo.Disambiguation.Should().Be("Test Disambiguation"); + nfo.Disambiguation.ShouldBe("Test Disambiguation"); } } @@ -184,10 +184,10 @@ Joel attended Hicksville High School in 1967, but he did not graduate with his c "ArtistInvalidCharacters1.nfo"); Either result = await _artistNfoReader.ReadFromFile(sourceFile); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ArtistNfo nfo in result.RightToSeq()) { - nfo.Name.Should().Be("Test Name"); + nfo.Name.ShouldBe("Test Name"); } } @@ -201,12 +201,12 @@ Joel attended Hicksville High School in 1967, but he did not graduate with his c "ArtistInvalidCharacters2.nfo"); Either result = await _artistNfoReader.ReadFromFile(sourceFile); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ArtistNfo nfo in result.RightToSeq()) { - nfo.Name.Should().Be("Test Name"); - nfo.Moods.Should().BeEquivalentTo(new List { "Test Mood" }); - nfo.Styles.Count.Should().Be(1); + nfo.Name.ShouldBe("Test Name"); + nfo.Moods.ShouldBeEquivalentTo(new List { "Test Mood" }); + nfo.Styles.Count.ShouldBe(1); } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs index 2b53f601..152e8a49 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/EpisodeNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging; using Microsoft.IO; using NSubstitute; @@ -48,10 +48,10 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); + list.Count.ShouldBe(1); } } @@ -77,14 +77,14 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.All(nfo => nfo.ShowTitle == "show").Should().BeTrue(); - list.All(nfo => nfo.Season == 1).Should().BeTrue(); - list.Count(nfo => nfo.Title == "episode-one" && nfo.Episode == 1).Should().Be(1); - list.Count(nfo => nfo.Title == "episode-two" && nfo.Episode == 2).Should().Be(1); + list.Count.ShouldBe(2); + list.All(nfo => nfo.ShowTitle == "show").ShouldBeTrue(); + list.All(nfo => nfo.Season == 1).ShouldBeTrue(); + list.Count(nfo => nfo.Title == "episode-one" && nfo.Episode == 1).ShouldBe(1); + list.Count(nfo => nfo.Title == "episode-two" && nfo.Episode == 2).ShouldBe(1); } } @@ -102,13 +102,13 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].UniqueIds.Count.Should().Be(2); - list[0].UniqueIds.Count(id => id.Default && id.Type == "tvdb" && id.Guid == "12345").Should().Be(1); - list[0].UniqueIds.Count(id => !id.Default && id.Type == "imdb" && id.Guid == "tt54321").Should().Be(1); + list.Count.ShouldBe(1); + list[0].UniqueIds.Count.ShouldBe(2); + list[0].UniqueIds.Count(id => id.Default && id.Type == "tvdb" && id.Guid == "12345").ShouldBe(1); + list[0].UniqueIds.Count(id => !id.Default && id.Type == "imdb" && id.Guid == "tt54321").ShouldBe(1); } } @@ -125,11 +125,11 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].ContentRating.Should().BeNullOrEmpty(); + list.Count.ShouldBe(1); + list[0].ContentRating.ShouldBeNullOrEmpty(); } } @@ -149,12 +149,12 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.Count(nfo => nfo.ContentRating == "US:Something").Should().Be(1); - list.Count(nfo => nfo.ContentRating == "US:Something / US:SomethingElse").Should().Be(1); + list.Count.ShouldBe(2); + list.Count(nfo => nfo.ContentRating == "US:Something").ShouldBe(1); + list.Count(nfo => nfo.ContentRating == "US:Something / US:SomethingElse").ShouldBe(1); } } @@ -171,11 +171,11 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].Plot.Should().BeNullOrEmpty(); + list.Count.ShouldBe(1); + list[0].Plot.ShouldBeNullOrEmpty(); } } @@ -192,11 +192,11 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].Plot.Should().Be("Some Plot"); + list.Count.ShouldBe(1); + list[0].Plot.ShouldBe("Some Plot"); } } @@ -222,15 +222,15 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].Actors.Count.Should().Be(2); + list.Count.ShouldBe(1); + list[0].Actors.Count.ShouldBe(2); list[0].Actors.Count(a => a.Name == "Name 1" && a.Role == "Role 1" && a.Thumb == "Thumb 1") - .Should().Be(1); + .ShouldBe(1); list[0].Actors.Count(a => a.Name == "Name 2" && a.Role == "Role 2" && a.Thumb == "Thumb 2") - .Should().Be(1); + .ShouldBe(1); } } @@ -251,13 +251,13 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.Count(nfo => nfo.Writers.Count == 1 && nfo.Writers[0] == "Writer 1").Should().Be(1); + list.Count.ShouldBe(2); + list.Count(nfo => nfo.Writers.Count == 1 && nfo.Writers[0] == "Writer 1").ShouldBe(1); list.Count(nfo => nfo.Writers.Count == 2 && nfo.Writers[0] == "Writer 2" && nfo.Writers[1] == "Writer 3") - .Should().Be(1); + .ShouldBe(1); } } @@ -278,15 +278,15 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.Count(nfo => nfo.Directors.Count == 1 && nfo.Directors[0] == "Director 1").Should().Be(1); + list.Count.ShouldBe(2); + list.Count(nfo => nfo.Directors.Count == 1 && nfo.Directors[0] == "Director 1").ShouldBe(1); list.Count( nfo => nfo.Directors.Count == 2 && nfo.Directors[0] == "Director 2" && nfo.Directors[1] == "Director 3") - .Should().Be(1); + .ShouldBe(1); } } @@ -307,12 +307,12 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.Count(nfo => nfo.Genres is ["Genre 1"]).Should().Be(1); - list.Count(nfo => nfo.Genres is ["Genre 2", "Genre 3"]).Should().Be(1); + list.Count.ShouldBe(2); + list.Count(nfo => nfo.Genres is ["Genre 1"]).ShouldBe(1); + list.Count(nfo => nfo.Genres is ["Genre 2", "Genre 3"]).ShouldBe(1); } } @@ -333,12 +333,12 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(2); - list.Count(nfo => nfo.Tags is ["Tag 1"]).Should().Be(1); - list.Count(nfo => nfo.Tags is ["Tag 2", "Tag 3"]).Should().Be(1); + list.Count.ShouldBe(2); + list.Count(nfo => nfo.Tags is ["Tag 1"]).ShouldBe(1); + list.Count(nfo => nfo.Tags is ["Tag 2", "Tag 3"]).ShouldBe(1); } } @@ -434,25 +434,25 @@ public class EpisodeNfoReaderTests Either> result = await _episodeNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (EpisodeNfo nfo in result.RightToSeq().Flatten()) { - nfo.ShowTitle.Should().Be("WandaVision"); - nfo.Title.Should().Be("Filmed Before a Live Studio Audience"); - nfo.Episode.Should().Be(1); - nfo.Season.Should().Be(1); - nfo.ContentRating.Should().Be("Australia:TV-14"); + nfo.ShowTitle.ShouldBe("WandaVision"); + nfo.Title.ShouldBe("Filmed Before a Live Studio Audience"); + nfo.Episode.ShouldBe(1); + nfo.Season.ShouldBe(1); + nfo.ContentRating.ShouldBe("Australia:TV-14"); - nfo.Aired.IsSome.Should().BeTrue(); + nfo.Aired.IsSome.ShouldBeTrue(); foreach (DateTime aired in nfo.Aired) { - aired.Should().Be(new DateTime(2021, 01, 15)); + aired.ShouldBe(new DateTime(2021, 01, 15)); } - nfo.Plot.Should().Be( + nfo.Plot.ShouldBe( "Wanda and Vision struggle to conceal their powers during dinner with Vision’s boss and his wife."); - nfo.Actors.Should().BeEquivalentTo( + nfo.Actors.ShouldBeEquivalentTo( new List { new() @@ -466,9 +466,9 @@ public class EpisodeNfoReaderTests Thumb = "https://image.tmdb.org/t/p/original/rrfyo9z1wW5nY9ZsFlj1Ozfj9g2.jpg" } }); - nfo.Writers.Should().BeEquivalentTo(new List { "Jac Schaeffer" }); - nfo.Directors.Should().BeEquivalentTo(new List { "Matt Shakman" }); - nfo.UniqueIds.Should().BeEquivalentTo( + nfo.Writers.ShouldBeEquivalentTo(new List { "Jac Schaeffer" }); + nfo.Directors.ShouldBeEquivalentTo(new List { "Matt Shakman" }); + nfo.UniqueIds.ShouldBeEquivalentTo( new List { new() { Type = "imdb", Guid = "tt9601584", Default = false }, @@ -488,11 +488,11 @@ public class EpisodeNfoReaderTests "EpisodeInvalidCharacters.nfo"); Either> result = await _episodeNfoReader.ReadFromFile(sourceFile); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (List list in result.RightToSeq()) { - list.Count.Should().Be(1); - list[0].Title.Should().Be("Test Title"); + list.Count.ShouldBe(1); + list[0].Title.ShouldBe("Test Title"); } } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs index 468fb9f3..5319d8c4 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MovieNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IO; using NSubstitute; @@ -29,7 +29,7 @@ public class MovieNfoReaderTests Either result = await _movieNfoReader.Read(stream); - result.IsLeft.Should().BeTrue(); + result.IsLeft.ShouldBeTrue(); } [Test] @@ -39,7 +39,7 @@ public class MovieNfoReaderTests Either result = await _movieNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -52,7 +52,7 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _movieNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -170,29 +170,29 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _movieNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MovieNfo nfo in result.RightToSeq()) { - nfo.Title.Should().Be("Zack Snyder's Justice League"); - nfo.SortTitle.Should().Be("Justice League 2"); - nfo.Outline.Should().BeNullOrEmpty(); - nfo.Year.Should().Be(2021); - nfo.ContentRating.Should().Be("Australia:M"); + nfo.Title.ShouldBe("Zack Snyder's Justice League"); + nfo.SortTitle.ShouldBe("Justice League 2"); + nfo.Outline.ShouldBeNullOrEmpty(); + nfo.Year.ShouldBe(2021); + nfo.ContentRating.ShouldBe("Australia:M"); - nfo.Premiered.IsSome.Should().BeTrue(); + nfo.Premiered.IsSome.ShouldBeTrue(); foreach (DateTime premiered in nfo.Premiered) { - premiered.Should().Be(new DateTime(2021, 03, 18)); + premiered.ShouldBe(new DateTime(2021, 03, 18)); } - nfo.Plot.Should().Be( + nfo.Plot.ShouldBe( "Determined to ensure Superman's ultimate sacrifice was not in vain, Bruce Wayne aligns forces with Diana Prince with plans to recruit a team of metahumans to protect the world from an approaching threat of catastrophic proportions."); - // nfo.Tagline.Should().BeNullOrEmpty(); - nfo.Genres.Should().BeEquivalentTo(new List { "SuperHero" }); - nfo.Tags.Should().BeEquivalentTo(new List { "TV Recording" }); - nfo.Studios.Should().BeEquivalentTo(new List { "Warner Bros. Pictures" }); - nfo.Actors.Should().BeEquivalentTo( + // nfo.Tagline.ShouldBeNullOrEmpty(); + nfo.Genres.ShouldBeEquivalentTo(new List { "SuperHero" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "TV Recording" }); + nfo.Studios.ShouldBeEquivalentTo(new List { "Warner Bros. Pictures" }); + nfo.Actors.ShouldBeEquivalentTo( new List { new() @@ -211,9 +211,9 @@ https://www.themoviedb.org/movie/11-star-wars")); Thumb = "https://image.tmdb.org/t/p/original/fysvehTvU6bE3JgxaOTRfvQJzJ4.jpg" } }); - nfo.Writers.Should().BeEquivalentTo(new List { "Chris Terrio" }); - nfo.Directors.Should().BeEquivalentTo(new List { "Zack Snyder" }); - nfo.UniqueIds.Should().BeEquivalentTo( + nfo.Writers.ShouldBeEquivalentTo(new List { "Chris Terrio" }); + nfo.Directors.ShouldBeEquivalentTo(new List { "Zack Snyder" }); + nfo.UniqueIds.ShouldBeEquivalentTo( new List { new() { Type = "imdb", Guid = "tt12361974", Default = false }, @@ -229,10 +229,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _movieNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MovieNfo nfo in result.RightToSeq()) { - nfo.Tags.Should().BeEquivalentTo(new List { "Test Tag" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "Test Tag" }); } } @@ -244,10 +244,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _movieNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MovieNfo nfo in result.RightToSeq()) { - nfo.Outline.Should().Be("Test Outline"); + nfo.Outline.ShouldBe("Test Outline"); } } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs index f9c2cd1b..df5d7127 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/MusicVideoNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IO; using NSubstitute; @@ -29,7 +29,7 @@ public class MusicVideoNfoReaderTests Either result = await _musicVideoNfoReader.Read(stream); - result.IsLeft.Should().BeTrue(); + result.IsLeft.ShouldBeTrue(); } [Test] @@ -39,7 +39,7 @@ public class MusicVideoNfoReaderTests Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -52,7 +52,7 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -115,22 +115,22 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MusicVideoNfo nfo in result.RightToSeq()) { - nfo.Artists.Should().BeEquivalentTo(new List { "ABBA" }); - nfo.Title.Should().Be("Dancing Queen"); - nfo.Album.Should().Be("Arrival"); - nfo.Plot.Should().Be( + nfo.Artists.ShouldBeEquivalentTo(new List { "ABBA" }); + nfo.Title.ShouldBe("Dancing Queen"); + nfo.Album.ShouldBe("Arrival"); + nfo.Plot.ShouldBe( NormalizeLineEndingsLF( @"Dancing Queen est un des tubes emblématiques de l'ère disco produits par le groupe suédois ABBA en 1976. Ce tube connaît un regain de popularité en 1994 lors de la sortie de Priscilla, folle du désert, et fait « presque » partie de la distribution du film Muriel. Le groupe a également enregistré une version espagnole de ce titre, La reina del baile, pour le marché d'Amérique latine. On peut retrouver ces versions en espagnol des succès de ABBA sur l'abum Oro. Le 18 juin 1976, ABBA a interprété cette chanson lors d'un spectacle télévisé organisé en l'honneur du roi Charles XVI Gustave de Suède, qui venait de se marier. Le titre sera repris en 2011 par Glee dans la saison 2, épisode 20.")); - nfo.Year.Should().Be(1976); - nfo.Aired.IsNone.Should().BeTrue(); - nfo.Genres.Should().BeEquivalentTo(new List { "Pop" }); - nfo.Track.Should().Be(-1); + nfo.Year.ShouldBe(1976); + nfo.Aired.IsNone.ShouldBeTrue(); + nfo.Genres.ShouldBeEquivalentTo(new List { "Pop" }); + nfo.Track.ShouldBe(-1); } } @@ -142,10 +142,10 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MusicVideoNfo nfo in result.RightToSeq()) { - nfo.Tags.Should().BeEquivalentTo(new List { "Test Tag" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "Test Tag" }); } } @@ -157,13 +157,13 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MusicVideoNfo nfo in result.RightToSeq()) { - nfo.Aired.IsSome.Should().BeTrue(); + nfo.Aired.IsSome.ShouldBeTrue(); foreach (DateTime aired in nfo.Aired) { - aired.Should().Be(new DateTime(2022, 02, 03)); + aired.ShouldBe(new DateTime(2022, 02, 03)); } } } @@ -176,10 +176,10 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MusicVideoNfo nfo in result.RightToSeq()) { - nfo.Studios.Should().BeEquivalentTo(new List { "Test Studio" }); + nfo.Studios.ShouldBeEquivalentTo(new List { "Test Studio" }); } } @@ -191,10 +191,10 @@ Le groupe a également enregistré une version espagnole de ce titre, La reina d Either result = await _musicVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (MusicVideoNfo nfo in result.RightToSeq()) { - nfo.Directors.Should().BeEquivalentTo(new List { "Test Director" }); + nfo.Directors.ShouldBeEquivalentTo(new List { "Test Director" }); } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs index 9de36ac2..815b4bdc 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/OtherVideoNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IO; using NSubstitute; @@ -29,7 +29,7 @@ public class OtherVideoNfoReaderTests Either result = await _otherVideoNfoReader.Read(stream); - result.IsLeft.Should().BeTrue(); + result.IsLeft.ShouldBeTrue(); } [Test] @@ -39,7 +39,7 @@ public class OtherVideoNfoReaderTests Either result = await _otherVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -52,7 +52,7 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _otherVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -170,29 +170,29 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _otherVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (OtherVideoNfo nfo in result.RightToSeq()) { - nfo.Title.Should().Be("Zack Snyder's Justice League"); - nfo.SortTitle.Should().Be("Justice League 2"); - nfo.Outline.Should().BeNullOrEmpty(); - nfo.Year.Should().Be(2021); - nfo.ContentRating.Should().Be("Australia:M"); + nfo.Title.ShouldBe("Zack Snyder's Justice League"); + nfo.SortTitle.ShouldBe("Justice League 2"); + nfo.Outline.ShouldBeNullOrEmpty(); + nfo.Year.ShouldBe(2021); + nfo.ContentRating.ShouldBe("Australia:M"); - nfo.Premiered.IsSome.Should().BeTrue(); + nfo.Premiered.IsSome.ShouldBeTrue(); foreach (DateTime premiered in nfo.Premiered) { - premiered.Should().Be(new DateTime(2021, 03, 18)); + premiered.ShouldBe(new DateTime(2021, 03, 18)); } - nfo.Plot.Should().Be( + nfo.Plot.ShouldBe( "Determined to ensure Superman's ultimate sacrifice was not in vain, Bruce Wayne aligns forces with Diana Prince with plans to recruit a team of metahumans to protect the world from an approaching threat of catastrophic proportions."); - nfo.Tagline.Should().BeNullOrEmpty(); - nfo.Genres.Should().BeEquivalentTo(new List { "SuperHero" }); - nfo.Tags.Should().BeEquivalentTo(new List { "TV Recording" }); - nfo.Studios.Should().BeEquivalentTo(new List { "Warner Bros. Pictures" }); - nfo.Actors.Should().BeEquivalentTo( + nfo.Tagline.ShouldBeNullOrEmpty(); + nfo.Genres.ShouldBeEquivalentTo(new List { "SuperHero" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "TV Recording" }); + nfo.Studios.ShouldBeEquivalentTo(new List { "Warner Bros. Pictures" }); + nfo.Actors.ShouldBeEquivalentTo( new List { new() @@ -211,9 +211,9 @@ https://www.themoviedb.org/movie/11-star-wars")); Thumb = "https://image.tmdb.org/t/p/original/fysvehTvU6bE3JgxaOTRfvQJzJ4.jpg" } }); - nfo.Writers.Should().BeEquivalentTo(new List { "Chris Terrio" }); - nfo.Directors.Should().BeEquivalentTo(new List { "Zack Snyder" }); - nfo.UniqueIds.Should().BeEquivalentTo( + nfo.Writers.ShouldBeEquivalentTo(new List { "Chris Terrio" }); + nfo.Directors.ShouldBeEquivalentTo(new List { "Zack Snyder" }); + nfo.UniqueIds.ShouldBeEquivalentTo( new List { new() { Type = "imdb", Guid = "tt12361974", Default = false }, @@ -229,10 +229,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _otherVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (OtherVideoNfo nfo in result.RightToSeq()) { - nfo.Tags.Should().BeEquivalentTo(new List { "Test Tag" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "Test Tag" }); } } @@ -244,10 +244,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _otherVideoNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (OtherVideoNfo nfo in result.RightToSeq()) { - nfo.Outline.Should().Be("Test Outline"); + nfo.Outline.ShouldBe("Test Outline"); } } } diff --git a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs index 32ec119f..95e13749 100644 --- a/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs +++ b/ErsatzTV.Scanner.Tests/Core/Metadata/Nfo/ShowNfoReaderTests.cs @@ -2,7 +2,7 @@ using Bugsnag; using ErsatzTV.Core; using ErsatzTV.Scanner.Core.Metadata.Nfo; -using FluentAssertions; +using Shouldly; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IO; using NSubstitute; @@ -29,7 +29,7 @@ public class ShowNfoReaderTests Either result = await _showNfoReader.Read(stream); - result.IsLeft.Should().BeTrue(); + result.IsLeft.ShouldBeTrue(); } [Test] @@ -39,7 +39,7 @@ public class ShowNfoReaderTests Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -52,7 +52,7 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); } [Test] @@ -155,18 +155,18 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ShowNfo nfo in result.RightToSeq()) { - nfo.Title.Should().Be("WandaVision"); - nfo.Year.Should().Be(2021); - nfo.Plot.Should().Be( + nfo.Title.ShouldBe("WandaVision"); + nfo.Year.ShouldBe(2021); + nfo.Plot.ShouldBe( "Wanda Maximoff and Vision—two super-powered beings living idealized suburban lives—begin to suspect that everything is not as it seems."); - nfo.ContentRating.Should().Be("Australia:M"); - nfo.Genres.Should().BeEquivalentTo(new List { "SuperHero" }); - nfo.Studios.Should().BeEquivalentTo(new List { "Disney+" }); - nfo.Actors.Should().BeEquivalentTo( + nfo.ContentRating.ShouldBe("Australia:M"); + nfo.Genres.ShouldBeEquivalentTo(new List { "SuperHero" }); + nfo.Studios.ShouldBeEquivalentTo(new List { "Disney+" }); + nfo.Actors.ShouldBeEquivalentTo( new List { new() @@ -180,17 +180,17 @@ https://www.themoviedb.org/movie/11-star-wars")); Thumb = "https://image.tmdb.org/t/p/original/vcAVrAOZrpqmi37qjFdztRAv1u9.jpg" } }); - nfo.UniqueIds.Should().BeEquivalentTo( + nfo.UniqueIds.ShouldBeEquivalentTo( new List { new() { Type = "imdb", Guid = "tt9140560", Default = false }, new() { Type = "tmdb", Guid = "85271", Default = true }, new() { Type = "tvdb", Guid = "362392", Default = false } }); - nfo.Premiered.IsSome.Should().BeTrue(); + nfo.Premiered.IsSome.ShouldBeTrue(); foreach (DateTime premiered in nfo.Premiered) { - premiered.Should().Be(new DateTime(2021, 1, 15)); + premiered.ShouldBe(new DateTime(2021, 1, 15)); } } } @@ -203,10 +203,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ShowNfo nfo in result.RightToSeq()) { - nfo.Outline.Should().Be("Test Outline"); + nfo.Outline.ShouldBe("Test Outline"); } } @@ -218,10 +218,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ShowNfo nfo in result.RightToSeq()) { - nfo.Tagline.Should().Be("Test Tagline"); + nfo.Tagline.ShouldBe("Test Tagline"); } } @@ -232,10 +232,10 @@ https://www.themoviedb.org/movie/11-star-wars")); Either result = await _showNfoReader.Read(stream); - result.IsRight.Should().BeTrue(); + result.IsRight.ShouldBeTrue(); foreach (ShowNfo nfo in result.RightToSeq()) { - nfo.Tags.Should().BeEquivalentTo(new List { "Test Tag" }); + nfo.Tags.ShouldBeEquivalentTo(new List { "Test Tag" }); } } } diff --git a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj index a5563216..9dfe7ddb 100644 --- a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj +++ b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj @@ -9,7 +9,6 @@ - @@ -23,6 +22,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + @@ -53,4 +53,10 @@ + + + Always + + + diff --git a/ErsatzTV.Scanner.Tests/Resources/song_album_cover_512.png b/ErsatzTV.Scanner.Tests/Resources/song_album_cover_512.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d5b95f1a25b1f73af51c66b90763b4a479f209 GIT binary patch literal 171151 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 z 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

  • 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 aFM}44%>l$9a4C2)i1Kvxb6Mw<&;$SisFd6Q literal 0 HcmV?d00001