132 lines
4.6 KiB
C#
132 lines
4.6 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using NSubstitute;
|
|
using TeleWave.Application.Common.Interfaces;
|
|
using TeleWave.Application.Library.Genres;
|
|
using TeleWave.Application.Metadata;
|
|
using TeleWave.Application.Metadata.ApplyShowMetadata;
|
|
using TeleWave.Application.Tests.Support;
|
|
using TeleWave.Domain.Library;
|
|
using Xunit;
|
|
|
|
namespace TeleWave.Application.Tests.Metadata;
|
|
|
|
public class ApplyShowMetadataTests
|
|
{
|
|
[Theory]
|
|
[InlineData(ShowKind.Series)]
|
|
[InlineData(ShowKind.Single)]
|
|
public async Task PassesShowKindToProvider(ShowKind kind)
|
|
{
|
|
// Тип определяет, в какое пространство идентификаторов пойдёт TMDb, и берётся он у самого
|
|
// шоу, а не из команды: иначе запросом можно было бы записать сериалу метаданные
|
|
// одноимённого фильма.
|
|
var arranged = await ArrangeAsync(kind);
|
|
Respond(arranged.Provider, new ShowMetadata("42", "A", 2000, null, null));
|
|
|
|
var result = await ApplyAsync(arranged);
|
|
|
|
Assert.True(result);
|
|
await arranged
|
|
.Provider.Received(1)
|
|
.GetShowAsync("42", kind, Arg.Any<CancellationToken>());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AppliesRecognizedRating()
|
|
{
|
|
var arranged = await ArrangeAsync(ShowKind.Single);
|
|
Respond(arranged.Provider, new ShowMetadata("42", "A", 2000, null, null, null, "PG-13"));
|
|
|
|
await ApplyAsync(arranged);
|
|
|
|
Assert.Equal(ShowAudience.Pg13, await SavedAudienceAsync(arranged));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task KeepsRating_WhenSourceGivesNothingUsable()
|
|
{
|
|
// «Not Rated» — это отсутствие данных. Снять им проставленный рейтинг нельзя: обновление
|
|
// метаданных тихо открыло бы взрослому шоу дорогу в детское время.
|
|
var arranged = await ArrangeAsync(ShowKind.Single, ShowAudience.R);
|
|
Respond(arranged.Provider, new ShowMetadata("42", "A", 2000, null, null, null, "Not Rated"));
|
|
|
|
await ApplyAsync(arranged);
|
|
|
|
Assert.Equal(ShowAudience.R, await SavedAudienceAsync(arranged));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Fails_ForInterstitial()
|
|
{
|
|
var arranged = await ArrangeAsync(ShowKind.Interstitial);
|
|
|
|
Assert.False(await ApplyAsync(arranged));
|
|
await arranged
|
|
.Provider.DidNotReceive()
|
|
.GetShowAsync(
|
|
Arg.Any<string>(),
|
|
Arg.Any<ShowKind>(),
|
|
Arg.Any<CancellationToken>()
|
|
);
|
|
}
|
|
|
|
private static void Respond(IMetadataProvider provider, ShowMetadata meta) =>
|
|
provider
|
|
.GetShowAsync("42", Arg.Any<ShowKind>(), Arg.Any<CancellationToken>())
|
|
.Returns(meta);
|
|
|
|
private static async Task<bool> ApplyAsync(Arranged arranged)
|
|
{
|
|
await using var db = arranged.Fixture.New();
|
|
var handler = new ApplyShowMetadataCommandHandler(
|
|
db,
|
|
arranged.Resolver,
|
|
Substitute.For<IImageDownloader>(),
|
|
Substitute.For<IImageStore>(),
|
|
new GenreMatcher(db)
|
|
);
|
|
|
|
var result = await handler.Handle(
|
|
new ApplyShowMetadataCommand(arranged.ShowId, "tmdb", "42"),
|
|
CancellationToken.None
|
|
);
|
|
|
|
// В обычном пути сохраняет UnitOfWorkBehavior; при прямом вызове хендлера его нет.
|
|
if (result.IsSuccess)
|
|
await db.SaveChangesAsync(CancellationToken.None);
|
|
return result.IsSuccess;
|
|
}
|
|
|
|
private static async Task<ShowAudience?> SavedAudienceAsync(Arranged arranged)
|
|
{
|
|
await using var db = arranged.Fixture.New();
|
|
return (await db.Shows.FirstAsync(s => s.Id == arranged.ShowId)).Audience;
|
|
}
|
|
|
|
private sealed record Arranged(
|
|
TestDb Fixture,
|
|
IMetadataProvider Provider,
|
|
IMetadataProviderResolver Resolver,
|
|
Guid ShowId
|
|
);
|
|
|
|
private static async Task<Arranged> ArrangeAsync(ShowKind kind, ShowAudience? audience = null)
|
|
{
|
|
var fixture = new TestDb();
|
|
var show = Show.Create("A", kind);
|
|
show.SetAudience(audience);
|
|
|
|
await using (var seed = fixture.New())
|
|
{
|
|
seed.Shows.Add(show);
|
|
await seed.SaveChangesAsync(CancellationToken.None);
|
|
}
|
|
|
|
var provider = Substitute.For<IMetadataProvider>();
|
|
var resolver = Substitute.For<IMetadataProviderResolver>();
|
|
resolver.Resolve("tmdb").Returns(provider);
|
|
|
|
return new Arranged(fixture, provider, resolver, show.Id);
|
|
}
|
|
}
|