using NSubstitute; using TeleWave.Application.Common.Interfaces; using TeleWave.Application.Library.Genres; using TeleWave.Application.Metadata; using TeleWave.Application.Metadata.EnrichShows; using TeleWave.Application.Tests.Support; using TeleWave.Domain.Library; using Xunit; namespace TeleWave.Application.Tests.Metadata; /// /// Массовое обогащение метаданными. Главное свойство — осторожность: чужой постер и чужой рейтинг /// у шоу в эфире хуже, чем непроставленные метаданные. /// public class EnrichShowsTests { [Fact] public async Task Applies_WhenTitleMatchesExactly() { var fixture = new TestDb(); var show = Show.Create("Гравити Фолз", ShowKind.Series); show.SetOriginalName("Gravity Falls"); await SeedAsync(fixture, show); var provider = ProviderWith([ new MetadataCandidate("42", "Gravity Falls", 2012, null, null, ShowKind.Series), ]); provider .GetShowAsync("42", Arg.Any(), Arg.Any()) .Returns(new ShowMetadata("42", "Gravity Falls", 2012, "desc", null, [], null)); var result = await RunAsync(fixture, provider, show.Id); Assert.Equal(1, result.Applied); Assert.Empty(result.Skipped); } [Fact] public async Task Skips_WhenSeveralCandidatesShareTheTitle() { // Два одноимённых — угадывать нельзя: у них разные постеры и разные рейтинги. var fixture = new TestDb(); var show = Show.Create("Gravity Falls", ShowKind.Series); await SeedAsync(fixture, show); var provider = ProviderWith([ new MetadataCandidate("1", "Gravity Falls", null, null, null, ShowKind.Series), new MetadataCandidate("2", "Gravity Falls", null, null, null, ShowKind.Series), ]); var result = await RunAsync(fixture, provider, show.Id); Assert.Equal(0, result.Applied); Assert.Single(result.Skipped); } [Fact] public async Task Skips_WhenOnlyLooseMatchFound() { var fixture = new TestDb(); var show = Show.Create("Пилот", ShowKind.Series); await SeedAsync(fixture, show); var provider = ProviderWith([ new MetadataCandidate("7", "Совсем другое шоу", null, null, null, ShowKind.Series), ]); var result = await RunAsync(fixture, provider, show.Id); Assert.Equal(0, result.Applied); Assert.Single(result.Skipped); } [Fact] public async Task Skips_AlreadyLinked() { // Ручной выбор источника массовая операция переписывать не должна. var fixture = new TestDb(); var show = Show.Create("Gravity Falls", ShowKind.Series); show.ApplyMetadata("tmdb", "999", null, null, null); await SeedAsync(fixture, show); var provider = ProviderWith([ new MetadataCandidate("42", "Gravity Falls", null, null, null, ShowKind.Series), ]); var result = await RunAsync(fixture, provider, show.Id); Assert.Equal(0, result.Applied); Assert.Single(result.Skipped); } private static async Task SeedAsync(TestDb fixture, Show show) { await using var seed = fixture.New(); seed.Shows.Add(show); await seed.SaveChangesAsync(CancellationToken.None); } private static IMetadataProvider ProviderWith(IReadOnlyList candidates) { var provider = Substitute.For(); provider .SearchShowsAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns(candidates); return provider; } private static async Task RunAsync( TestDb fixture, IMetadataProvider provider, Guid showId ) { var resolver = Substitute.For(); resolver.Resolve("tmdb").Returns(provider); await using var db = fixture.New(); var applier = new ShowMetadataApplier( db, resolver, Substitute.For(), Substitute.For(), new GenreMatcher(db) ); var result = await new EnrichShowsMetadataCommandHandler(db, resolver, applier).Handle( new EnrichShowsMetadataCommand([showId], "tmdb"), CancellationToken.None ); Assert.True(result.IsSuccess); await db.SaveChangesAsync(CancellationToken.None); return result.Value; } }