aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCody Robibero <cody@robibe.ro>2026-08-25 18:28:52 -0400
committerGitHub <noreply@github.com>2026-08-25 18:28:52 -0400
commitf682c22b08fd842e5642e4c19be6f0a9dd32f588 (patch)
tree7336324e9d8fa4dbcc2385942e23944ff07533c1 /tests
parenta68793d08a83ddfa91bd3a22c3be0eb634579134 (diff)
parent6978dfc29441eb1a37571be14fe165c622bff3c7 (diff)
Merge pull request #17715 from Shadowghost/fix-people-cleanup
Delete credits nothing maps to and bound item-by-name folder names
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs52
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs73
2 files changed, 125 insertions, 0 deletions
diff --git a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
index e34eb0bda3..86bac4256a 100644
--- a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
+++ b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Database.Implementations.Entities;
@@ -27,6 +28,57 @@ namespace Jellyfin.Controller.Tests.Entities;
public class BaseItemTests
{
+ [Fact]
+ public void GetItemByNameFolderName_ShortName_IsKeptAsIs()
+ {
+ SetupPassThroughFileSystem();
+
+ Assert.Equal("Mairghread Scott", BaseItem.GetItemByNameFolderName("Mairghread Scott."));
+ }
+
+ [Fact]
+ public void GetItemByNameFolderName_OverlongName_FitsInAPathComponent()
+ {
+ SetupPassThroughFileSystem();
+
+ // What a provider result that concatenated a whole credit list into one name looks like.
+ var name = string.Join(", ", Enumerable.Repeat("Jerry Siegel (created by: Superman)", 20));
+
+ var folderName = BaseItem.GetItemByNameFolderName(name);
+
+ Assert.True(Encoding.UTF8.GetByteCount(folderName) <= 128);
+ Assert.StartsWith("Jerry Siegel (created by: Superman)", folderName, StringComparison.Ordinal);
+ }
+
+ [Fact]
+ public void GetItemByNameFolderName_OverlongNamesSharingAPrefix_StayApart()
+ {
+ SetupPassThroughFileSystem();
+
+ var prefix = new string('a', 200);
+
+ Assert.NotEqual(
+ BaseItem.GetItemByNameFolderName(prefix + "Joe Shuster"),
+ BaseItem.GetItemByNameFolderName(prefix + "Bob Kane"));
+ }
+
+ [Fact]
+ public void GetItemByNameFolderName_OverlongName_IsStable()
+ {
+ SetupPassThroughFileSystem();
+
+ var name = new string('a', 300);
+
+ Assert.Equal(BaseItem.GetItemByNameFolderName(name), BaseItem.GetItemByNameFolderName(name));
+ }
+
+ private static void SetupPassThroughFileSystem()
+ {
+ var fileSystem = new Mock<IFileSystem>();
+ fileSystem.Setup(x => x.GetValidFilename(It.IsAny<string>())).Returns((string name) => name);
+ BaseItem.FileSystem = fileSystem.Object;
+ }
+
[Theory]
[InlineData("", "")]
[InlineData("1", "0000000001")]
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
index 54565c5787..649458f733 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Item/PeopleRepositoryUpdatePeopleTests.cs
@@ -142,6 +142,79 @@ public sealed class PeopleRepositoryUpdatePeopleTests : SqliteDbTestFixture
Assert.Equal("Hero", map.Role);
}
+ [Fact]
+ public void UpdatePeople_CreditDroppedByTheProvider_LeavesNoCreditRowBehind()
+ {
+ _repository.UpdatePeople(_itemId, [
+ CreatePerson("Person A", PersonKind.Actor, "Hero"),
+ CreatePerson("Person B", PersonKind.Actor, "Villain")
+ ]);
+
+ _repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
+
+ using var ctx = CreateDbContext();
+ Assert.Equal(["Person A"], ctx.Peoples.Select(e => e.Name).ToArray());
+ }
+
+ [Fact]
+ public void UpdatePeople_CreditStillHeldByAnotherItem_IsKept()
+ {
+ _repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
+ _repository.UpdatePeople(AddMovie("Other Movie"), [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
+
+ _repository.UpdatePeople(_itemId, []);
+
+ using var after = CreateDbContext();
+ Assert.Single(after.Peoples);
+ Assert.Single(after.PeopleBaseItemMap);
+ }
+
+ [Fact]
+ public void DeleteOrphanedCredits_CreditNoItemMapsTo_IsDeleted()
+ {
+ _repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
+ using (var ctx = CreateDbContext())
+ {
+ // The state a credit was left in before UpdatePeople cleaned up after itself.
+ ctx.PeopleBaseItemMap.RemoveRange(ctx.PeopleBaseItemMap);
+ ctx.SaveChanges();
+ }
+
+ Assert.Equal(1, _repository.DeleteOrphanedCredits());
+
+ using var after = CreateDbContext();
+ Assert.Empty(after.Peoples);
+ }
+
+ [Fact]
+ public void DeleteOrphanedCredits_CreditAnItemMapsTo_IsKept()
+ {
+ _repository.UpdatePeople(_itemId, [CreatePerson("Person A", PersonKind.Actor, "Hero")]);
+
+ Assert.Equal(0, _repository.DeleteOrphanedCredits());
+
+ using var after = CreateDbContext();
+ Assert.Single(after.Peoples);
+ }
+
+ private Guid AddMovie(string name)
+ {
+ var id = Guid.NewGuid();
+ using var ctx = CreateDbContext();
+ ctx.BaseItems.Add(new BaseItemEntity
+ {
+ Id = id,
+ Type = new ItemTypeLookup().BaseItemKindNames[BaseItemKind.Movie],
+ Name = name,
+ MediaType = "Video",
+ IsMovie = true,
+ IsFolder = false,
+ IsVirtualItem = false
+ });
+ ctx.SaveChanges();
+ return id;
+ }
+
private static PersonInfo CreatePerson(string name, PersonKind type, string role)
{
return new PersonInfo