using NSubstitute; using TeleWave.Application.Common.Interfaces; using TeleWave.Application.Metadata.FindMissingSeasons; using TeleWave.Application.Tests.Support; using TeleWave.Domain.Library; using Xunit; namespace TeleWave.Application.Tests.Metadata; public class FindMissingSeasonsTests { [Fact] public async Task ReportsSeasonsWithoutAnyLoadedEpisode() { var fixture = new TestDb(); var show = Show.Create("A", ShowKind.Series); show.ApplyMetadata("tmdb", "123", "desc", 2000, null); // Загружены сезоны 1 и 3; у источника их четыре — не хватает 2 и 4. var e11 = show.AddEpisode(Guid.NewGuid()); e11.SetNumbers(1, 1); var e31 = show.AddEpisode(Guid.NewGuid()); e31.SetNumbers(3, 1); await using (var seed = fixture.New()) { seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } var resolver = ResolverFor("123", [1, 2, 3, 4]); await using var db = fixture.New(); var result = await new FindMissingSeasonsQueryHandler(db, resolver).Handle( new FindMissingSeasonsQuery(show.Id), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Equal(4, result.Value.Expected); Assert.Equal([1, 3], result.Value.Loaded); Assert.Equal([2, 4], result.Value.Missing); Assert.Empty(result.Value.Unknown); } [Fact] public async Task ReportsLoadedSeasonsUnknownToSource() { var fixture = new TestDb(); var show = Show.Create("A", ShowKind.Series); show.ApplyMetadata("tmdb", "123", null, 2000, null); var e91 = show.AddEpisode(Guid.NewGuid()); e91.SetNumbers(9, 1); await using (var seed = fixture.New()) { seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } var resolver = ResolverFor("123", [1, 2]); await using var db = fixture.New(); var result = await new FindMissingSeasonsQueryHandler(db, resolver).Handle( new FindMissingSeasonsQuery(show.Id), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Equal([1, 2], result.Value.Missing); Assert.Equal([9], result.Value.Unknown); } [Fact] public async Task ReportsExpectedNull_WhenSourceReturnsNothing() { // Источник промолчал: ни отсутствующих, ни лишних сезонов утверждать нельзя. var fixture = new TestDb(); var show = Show.Create("A", ShowKind.Series); show.ApplyMetadata("tmdb", "123", null, 2000, null); var e11 = show.AddEpisode(Guid.NewGuid()); e11.SetNumbers(1, 1); await using (var seed = fixture.New()) { seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } var resolver = ResolverFor("123", []); await using var db = fixture.New(); var result = await new FindMissingSeasonsQueryHandler(db, resolver).Handle( new FindMissingSeasonsQuery(show.Id), CancellationToken.None ); Assert.True(result.IsSuccess); Assert.Null(result.Value.Expected); Assert.Equal([1], result.Value.Loaded); Assert.Empty(result.Value.Missing); Assert.Empty(result.Value.Unknown); } [Fact] public async Task Fails_ForNonSeries() { var fixture = new TestDb(); var show = Show.Create("A", ShowKind.Single); show.ApplyMetadata("tmdb", "123", null, 2000, null); await using (var seed = fixture.New()) { seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } var resolver = Substitute.For(); await using var db = fixture.New(); var result = await new FindMissingSeasonsQueryHandler(db, resolver).Handle( new FindMissingSeasonsQuery(show.Id), CancellationToken.None ); Assert.False(result.IsSuccess); } [Fact] public async Task Fails_WhenNoLinkedSource() { var fixture = new TestDb(); var show = Show.Create("A", ShowKind.Series); await using (var seed = fixture.New()) { seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } var resolver = Substitute.For(); await using var db = fixture.New(); var result = await new FindMissingSeasonsQueryHandler(db, resolver).Handle( new FindMissingSeasonsQuery(show.Id), CancellationToken.None ); Assert.False(result.IsSuccess); } private static IMetadataProviderResolver ResolverFor(string externalId, int[] seasons) { var provider = Substitute.For(); provider .GetSeasonNumbersAsync(externalId, Arg.Any()) .Returns(seasons.ToList()); var resolver = Substitute.For(); resolver.Resolve("tmdb").Returns(provider); return resolver; } }