Files
TeleWave/backend/tests/TeleWave.Application.Tests/Metadata/ApplyShowMetadataTests.cs
T

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);
}
}