Files
jellyfin-ha-src/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
T

187 lines
6.1 KiB
C#

using System;
using System.Linq;
using Emby.Server.Implementations.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Database.Implementations;
using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Database.Implementations.Locking;
using Jellyfin.Database.Providers.Sqlite;
using Jellyfin.Server.Implementations.Item;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using Xunit;
using BaseItemKind = Jellyfin.Data.Enums.BaseItemKind;
namespace Jellyfin.Server.Implementations.Tests.Item;
public sealed class PeopleRepositoryUpdatePeopleTests : IDisposable
{
private static readonly Guid _itemId = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
private readonly SqliteConnection _connection;
private readonly DbContextOptions<JellyfinDbContext> _dbOptions;
private readonly PeopleRepository _repository;
public PeopleRepositoryUpdatePeopleTests()
{
_connection = new SqliteConnection("Data Source=:memory:");
_connection.Open();
_dbOptions = new DbContextOptionsBuilder<JellyfinDbContext>()
.UseSqlite(_connection)
.Options;
var itemTypeLookup = new ItemTypeLookup();
using (var ctx = CreateDbContext())
{
ctx.Database.EnsureCreated();
ctx.BaseItems.Add(new BaseItemEntity
{
Id = _itemId,
Type = itemTypeLookup.BaseItemKindNames[BaseItemKind.Movie],
Name = "Movie",
MediaType = "Video",
IsMovie = true,
IsFolder = false,
IsVirtualItem = false
});
ctx.SaveChanges();
}
var factory = new Mock<IDbContextFactory<JellyfinDbContext>>();
factory.Setup(f => f.CreateDbContext()).Returns(CreateDbContext);
_repository = new PeopleRepository(
factory.Object,
itemTypeLookup,
new Mock<IItemQueryHelpers>().Object);
}
public void Dispose()
{
_connection.Dispose();
}
[Fact]
public void UpdatePeople_SamePersonAndTypeWithDifferentRoles_KeepsEveryCredit()
{
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Writer, "Novel"),
CreatePerson("Person A", PersonKind.Writer, "Screenplay")
]);
using var ctx = CreateDbContext();
Assert.Single(ctx.Peoples);
Assert.Equal(
["Novel", "Screenplay"],
ctx.PeopleBaseItemMap.OrderBy(e => e.ListOrder).Select(e => e.Role ?? string.Empty).ToArray());
}
[Fact]
public void UpdatePeople_CreditsDifferingOnlyInCase_AreDeduped()
{
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Actor, "Hero"),
CreatePerson("person a", PersonKind.Actor, "hero")
]);
using var ctx = CreateDbContext();
Assert.Single(ctx.Peoples);
var map = Assert.Single(ctx.PeopleBaseItemMap);
Assert.Equal("Hero", map.Role);
}
[Fact]
public void UpdatePeople_SamePersonAsDifferentTypes_CreatesOnePersonPerType()
{
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Actor, "Hero"),
CreatePerson("Person A", PersonKind.Director, string.Empty)
]);
using var ctx = CreateDbContext();
Assert.Equal(2, ctx.Peoples.Count());
Assert.Equal(2, ctx.PeopleBaseItemMap.Count());
}
[Fact]
public void UpdatePeople_RepeatedUpdate_ReusesMappingsAndRefreshesOrder()
{
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Actor, "Hero"),
CreatePerson("Person B", PersonKind.Actor, "Sidekick")
]);
Guid[] peopleIdsBefore;
using (var ctx = CreateDbContext())
{
peopleIdsBefore = ctx.Peoples.Select(e => e.Id).OrderBy(e => e).ToArray();
}
// Reversed order, so the list order of both mappings has to be rewritten.
_repository.UpdatePeople(_itemId, [
CreatePerson("Person B", PersonKind.Actor, "Sidekick"),
CreatePerson("Person A", PersonKind.Actor, "Hero")
]);
using var after = CreateDbContext();
Assert.Equal(peopleIdsBefore, after.Peoples.Select(e => e.Id).OrderBy(e => e).ToArray());
Assert.Equal(
["Sidekick", "Hero"],
after.PeopleBaseItemMap.OrderBy(e => e.ListOrder).Select(e => e.Role ?? string.Empty).ToArray());
}
[Fact]
public void UpdatePeople_CreditRemoved_DropsOnlyThatMapping()
{
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Writer, "Novel"),
CreatePerson("Person A", PersonKind.Writer, "Screenplay")
]);
_repository.UpdatePeople(_itemId, [
CreatePerson("Person A", PersonKind.Writer, "Novel")
]);
using var ctx = CreateDbContext();
var map = Assert.Single(ctx.PeopleBaseItemMap);
Assert.Equal("Novel", map.Role);
}
[Fact]
public void UpdatePeople_RoleCaseChanged_KeepsExistingMapping()
{
_repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
_repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "HERO")]);
using var ctx = CreateDbContext();
var map = Assert.Single(ctx.PeopleBaseItemMap);
Assert.Equal("Hero", map.Role);
}
private static PersonInfo CreatePerson(string name, PersonKind type, string role)
{
return new PersonInfo
{
Name = name,
Type = type,
Role = role
};
}
private JellyfinDbContext CreateDbContext()
{
return new JellyfinDbContext(
_dbOptions,
NullLogger<JellyfinDbContext>.Instance,
new SqliteDatabaseProvider(null!, NullLogger<SqliteDatabaseProvider>.Instance),
new NoLockBehavior(NullLogger<NoLockBehavior>.Instance));
}
}