aboutsummaryrefslogtreecommitdiff
path: root/tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs
diff options
context:
space:
mode:
authorShadowghost <Shadowghost@users.noreply.github.com>2026-09-15 11:15:46 -0400
committerCody Robibero <cody@robibe.ro>2026-09-15 11:15:46 -0400
commit006ecadbe041ea422b34adf6a3fcf6638d189a70 (patch)
treec845d30aafd6cb23bf2e41dd955712db0f641ce4 /tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs
parent65bc888b07a25d1883d4d0a2f55a7f3e1ac35c87 (diff)
Backport pull request #17881 from jellyfin/release-12.z
Fix /UserViews exhausting memory and reporting random child counts Original-merge: a838a06aa51eac388a76e9e6421f1a80873c417b Merged-by: crobibero <cody@robibe.ro> Backported-by: Cody Robibero <cody@robibe.ro>
Diffstat (limited to 'tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs')
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs58
1 files changed, 58 insertions, 0 deletions
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs
new file mode 100644
index 0000000000..54fec0a0d3
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Entities/UserViewBuilderTests.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Jellyfin.Database.Implementations.Entities;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Library;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.Entities;
+
+public sealed class UserViewBuilderTests
+{
+ private static readonly User _user = new("view-filter-test", "provider", "reset");
+
+ [Fact]
+ public void Filter_IsPlayed_CountsAMovieWatchedOnAnAlternateVersionAsPlayed()
+ {
+ // The primary carries no played row of its own; the version that was watched is another file.
+ var onlyWatchedOnAlternate = new Movie { Id = Guid.NewGuid(), Name = "Watched as a second cut" };
+ var watched = new Movie { Id = Guid.NewGuid(), Name = "Watched outright" };
+ var unwatched = new Movie { Id = Guid.NewGuid(), Name = "Not watched" };
+
+ var items = new BaseItem[] { onlyWatchedOnAlternate, watched, unwatched };
+
+ var userDataManager = new Mock<IUserDataManager>();
+ userDataManager
+ .Setup(m => m.GetUserData(_user, It.IsAny<BaseItem>()))
+ .Returns((User _, BaseItem item) => new UserItemData { Key = item.Id.ToString("N"), Played = item.Id.Equals(watched.Id) });
+ userDataManager
+ .Setup(m => m.GetResumeUserDataBatch(It.IsAny<IReadOnlyList<BaseItem>>(), _user))
+ .Returns(new Dictionary<Guid, VersionResumeData>
+ {
+ [onlyWatchedOnAlternate.Id] = new(Guid.NewGuid(), new UserItemData { Key = "alternate", Played = true })
+ });
+
+ var libraryManager = new Mock<ILibraryManager>();
+
+ var played = UserViewBuilder.Filter(
+ items,
+ _user,
+ new InternalItemsQuery(_user) { IsPlayed = true },
+ userDataManager.Object,
+ libraryManager.Object).ToList();
+
+ var unplayed = UserViewBuilder.Filter(
+ items,
+ _user,
+ new InternalItemsQuery(_user) { IsPlayed = false },
+ userDataManager.Object,
+ libraryManager.Object).ToList();
+
+ // The alternate's playback settles the movie, exactly as the item's own dto reports it.
+ Assert.Equal([onlyWatchedOnAlternate.Id, watched.Id], played.Select(i => i.Id));
+ Assert.Equal([unwatched.Id], unplayed.Select(i => i.Id));
+ }
+}