using System; using System.Collections.Generic; using Emby.Server.Implementations.Library; using Jellyfin.Database.Implementations; using Jellyfin.Database.Implementations.Entities; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using Microsoft.EntityFrameworkCore; using Moq; using Xunit; using AudioBook = MediaBrowser.Controller.Entities.AudioBook; namespace Jellyfin.Server.Implementations.Tests.Library; public class UserDataManagerTests { private readonly UserDataManager _userDataManager; private readonly User _user; public UserDataManagerTests() { var config = new Mock(); config.SetupGet(c => c.Configuration).Returns(new ServerConfiguration()); var repository = Mock.Of>(); _userDataManager = new UserDataManager(config.Object, repository); _user = new User("user", "auth-provider", "reset-provider") { Id = Guid.NewGuid() }; } private AudioBook CreateAudioBook() { // GetUserDataKeys(): ["Author-Series-0001Book Title", ""] return new AudioBook { Id = Guid.NewGuid(), Name = "Book Title", Album = "Series", AlbumArtists = new[] { "Author" }, IndexNumber = 1 }; } private UserData CreateUserDataRow(AudioBook item, string key, long positionTicks) { return new UserData { ItemId = item.Id, Item = null, UserId = _user.Id, User = null, CustomDataKey = key, PlaybackPositionTicks = positionTicks }; } [Fact] public void GetUserData_RowsUnderCurrentAndRetiredKeys_PrefersCurrentKeyRow() { var item = CreateAudioBook(); var currentKey = item.GetUserDataKeys()[0]; // the retired-key row comes first to ensure selection is by key, not row order item.UserData = new List { CreateUserDataRow(item, "Author-Old Album-0001Old File Name", 111), CreateUserDataRow(item, currentKey, 222) }; var userData = _userDataManager.GetUserData(_user, item); Assert.NotNull(userData); Assert.Equal(currentKey, userData.Key); Assert.Equal(222, userData.PlaybackPositionTicks); } [Fact] public void GetUserData_NoPrimaryKeyRow_UsesNextCurrentKeyRow() { var item = CreateAudioBook(); var idKey = item.GetUserDataKeys()[1]; item.UserData = new List { CreateUserDataRow(item, "Author-Old Album-0001Old File Name", 111), CreateUserDataRow(item, idKey, 333) }; var userData = _userDataManager.GetUserData(_user, item); Assert.NotNull(userData); Assert.Equal(idKey, userData.Key); Assert.Equal(333, userData.PlaybackPositionTicks); } [Fact] public void GetUserData_OnlyRetiredKeyRows_ReturnsRetiredKeyRow() { var item = CreateAudioBook(); item.UserData = new List { CreateUserDataRow(item, "Author-Old Album-0001Old File Name", 111) }; var userData = _userDataManager.GetUserData(_user, item); Assert.NotNull(userData); Assert.Equal(111, userData.PlaybackPositionTicks); } [Fact] public void GetUserData_NoRows_ReturnsDefaultWithPrimaryKey() { var item = CreateAudioBook(); item.UserData = new List(); var userData = _userDataManager.GetUserData(_user, item); Assert.NotNull(userData); Assert.Equal(item.GetUserDataKeys()[0], userData.Key); Assert.Equal(0, userData.PlaybackPositionTicks); } [Fact] public void GetUserData_RowsForOtherUsers_AreIgnored() { var item = CreateAudioBook(); var currentKey = item.GetUserDataKeys()[0]; var otherUserRow = CreateUserDataRow(item, currentKey, 999); otherUserRow.UserId = Guid.NewGuid(); item.UserData = new List { otherUserRow, CreateUserDataRow(item, currentKey, 222) }; var userData = _userDataManager.GetUserData(_user, item); Assert.NotNull(userData); Assert.Equal(222, userData.PlaybackPositionTicks); } }