aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-08-05 12:22:55 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-08-05 13:21:57 +0200
commit61e75599b30cd346eab743529271ab3e002f0474 (patch)
treee552741eb659ecfdbf36b6f8bcf1b1cc1ce70ee8 /tests
parentb2485af6e9b29c8a6491deb934569e591b4858d2 (diff)
Project the lowered person credit values once when updating people
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs186
1 files changed, 186 insertions, 0 deletions
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
new file mode 100644
index 0000000000..70d8e1f833
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
@@ -0,0 +1,186 @@
+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));
+ }
+}