diff --git a/tests/Jellyfin.Plugin.Multilang.Tests/Jellyfin.Plugin.Multilang.Tests.csproj b/tests/Jellyfin.Plugin.Multilang.Tests/Jellyfin.Plugin.Multilang.Tests.csproj index ef24ea9..f439f23 100644 --- a/tests/Jellyfin.Plugin.Multilang.Tests/Jellyfin.Plugin.Multilang.Tests.csproj +++ b/tests/Jellyfin.Plugin.Multilang.Tests/Jellyfin.Plugin.Multilang.Tests.csproj @@ -13,7 +13,8 @@ - + + diff --git a/tests/Jellyfin.Plugin.Multilang.Tests/TranslationStoreImportTests.cs b/tests/Jellyfin.Plugin.Multilang.Tests/TranslationStoreImportTests.cs new file mode 100644 index 0000000..6bb311e --- /dev/null +++ b/tests/Jellyfin.Plugin.Multilang.Tests/TranslationStoreImportTests.cs @@ -0,0 +1,99 @@ +using Jellyfin.Plugin.Multilang.Data; +using Jellyfin.Plugin.Multilang.Services.Providers; +using Jellyfin.Plugin.Multilang.Services.Refresh; +using MediaBrowser.Common.Configuration; + +namespace Jellyfin.Plugin.Multilang.Tests; + +public sealed class TranslationStoreImportTests +{ + [Fact] + public void ImportTranslationDatabaseKeepsOnlyLiveItemsAndAllowedLanguages() + { + var root = Path.Combine(Path.GetTempPath(), "multilang-test-" + Guid.NewGuid().ToString("N")); + try + { + var source = new TranslationStore(new TestApplicationPaths(Path.Combine(root, "source"))); + var destination = new TranslationStore(new TestApplicationPaths(Path.Combine(root, "destination"))); + var liveId = "11111111111111111111111111111111"; + var staleId = "22222222222222222222222222222222"; + SeedImportSource(source, liveId, staleId); + + var exportPath = Path.Combine(root, "export.sqlite"); + source.ExportTranslationDatabase(exportPath); + + var result = destination.ImportTranslationDatabase( + exportPath, + new HashSet(StringComparer.OrdinalIgnoreCase) { liveId }, + new HashSet(StringComparer.OrdinalIgnoreCase) { "en" }); + + Assert.Equal(new ImportDatabaseResult(Facts: 1, Translations: 1, Assets: 1, Genres: 2), result); + Assert.NotNull(destination.GetFacts(liveId)); + Assert.Null(destination.GetFacts(staleId)); + Assert.Equal("English title", Translation(destination, liveId, "en", "title")); + Assert.Null(Translation(destination, liveId, "fi", "title")); + Assert.Null(destination.GetAssetPath(liveId, "fi", "poster")); + Assert.Equal("https://asset/en.jpg", destination.GetAssetPath(liveId, "en", "poster")); + Assert.Equal(["en", "Original"], destination.GetGenres("movie").Select(g => g.Lang).OrderBy(v => v).ToArray()); + } + finally + { + if (Directory.Exists(root)) + Directory.Delete(root, recursive: true); + } + } + + private static void SeedImportSource(TranslationStore store, string liveId, string staleId) + { + store.UpsertFacts(Item(liveId), Metadata("Live"), 1, 2); + store.UpsertFacts(Item(staleId), Metadata("Stale"), 1, 2); + store.UpsertTranslation(liveId, "en", "title", "English title"); + store.UpsertTranslation(liveId, "fi", "title", "Finnish title"); + store.UpsertTranslation(staleId, "en", "title", "Stale English title"); + store.UpsertAsset(liveId, "en", "poster", "https://asset/en.jpg", 1); + store.UpsertAsset(liveId, "fi", "poster", "https://asset/fi.jpg", 1); + store.UpsertAsset(staleId, "en", "poster", "https://asset/stale.jpg", 1); + store.UpsertGenre(1, "movie", "en", "Action"); + store.UpsertGenre(1, "movie", "fi", "Toiminta"); + store.UpsertGenre(1, "movie", "Original", "Original action"); + } + + private static RefreshItemInfo Item(string itemId) + => new(itemId, "123", "movie", RefreshWorkClass.Movies, 0, 0, null, "Movie"); + + private static TmdbMetadata Metadata(string title) + => new(title, "Overview", "Tagline", title, "en", ["US"], ["US"], ["en"], [new TmdbGenre(1, "Action")]); + + private static string? Translation(TranslationStore store, string itemId, string lang, string field) + => store.GetTranslations([itemId], [lang]) + .GetValueOrDefault(itemId)? + .GetValueOrDefault(lang)? + .GetValueOrDefault(field); + + private sealed class TestApplicationPaths(string root) : IApplicationPaths + { + public string ProgramDataPath { get; } = root; + public string WebPath { get; } = Path.Combine(root, "web"); + public string ProgramSystemPath { get; } = Path.Combine(root, "system"); + public string DataPath { get; } = Path.Combine(root, "data"); + public string ImageCachePath { get; } = Path.Combine(root, "images"); + public string PluginsPath { get; } = Path.Combine(root, "plugins"); + public string PluginConfigurationsPath { get; } = Path.Combine(root, "plugin-configs"); + public string LogDirectoryPath { get; } = Path.Combine(root, "logs"); + public string ConfigurationDirectoryPath { get; } = Path.Combine(root, "config"); + public string SystemConfigurationFilePath { get; } = Path.Combine(root, "config", "system.xml"); + public string CachePath { get; } = Path.Combine(root, "cache"); + public string TempDirectory { get; } = Path.Combine(root, "temp"); + public string VirtualDataPath { get; } = "%AppDataPath%"; + public string TrickplayPath { get; } = Path.Combine(root, "trickplay"); + public string BackupPath { get; } = Path.Combine(root, "backups"); + + public void MakeSanityCheckOrThrow() + { + } + + public void CreateAndCheckMarker(string path, string marker, bool isTemporary = false) + { + } + } +}