using Jellyfin.Plugin.Multilang.Data; using Jellyfin.Plugin.Multilang.Services.Providers; using Jellyfin.Plugin.Multilang.Services.Refresh; namespace Jellyfin.Plugin.Multilang.Tests; public sealed class TranslationStoreCleanupTests { [Fact] public void CleanupForConfigurationRemovesStaleLanguagesItemsAndFiles() { var root = TestPaths.CreateRoot(); try { var store = new TranslationStore(new TestApplicationPaths(root)); const string live = "11111111111111111111111111111111"; const string stale = "22222222222222222222222222222222"; SeedFacts(store, live); SeedFacts(store, stale); store.UpsertTranslation(live, "en", "title", "English"); store.UpsertTranslation(live, "fi", "title", "Finnish"); store.UpsertTranslation(stale, "en", "title", "Stale"); store.UpsertGenre(1, "movie", "en", "Action"); store.UpsertGenre(1, "movie", "fi", "Toiminta"); AddLocalAsset(store, live, "en", "poster"); AddLocalAsset(store, live, "fi", "poster"); AddLocalAsset(store, stale, "en", "poster"); var orphan = Path.Combine(store.AssetsDirectory, "orphan.jpg"); File.WriteAllText(orphan, "orphan"); var result = store.CleanupForConfiguration( new HashSet(StringComparer.OrdinalIgnoreCase) { live }, ["en"], localAssetStorage: false); Assert.Equal(new LocalCleanupResult(TranslationsDeleted: 1, AssetsDeleted: 2, GenresDeleted: 1, AssetFilesDeleted: 4), result); Assert.NotNull(store.GetFacts(live)); Assert.Null(store.GetFacts(stale)); Assert.Equal("English", Translation(store, live, "en", "title")); Assert.Null(Translation(store, live, "fi", "title")); Assert.Null(store.GetAssetPath(live, "en", "poster")); Assert.Empty(Directory.EnumerateFiles(store.AssetsDirectory, "*", SearchOption.AllDirectories)); } finally { TestPaths.DeleteRoot(root); } } private static void SeedFacts(TranslationStore store, string itemId) => store.UpsertFacts( new RefreshItemInfo(itemId, "1", "movie", RefreshWorkClass.Movies, 0, 0, null, "Movie"), new TmdbMetadata("Title", "", "", "Title", "en", [], [], [], []), 1, 1); private static void AddLocalAsset(TranslationStore store, string itemId, string lang, string kind) { var relative = Path.Combine(itemId, lang, kind + ".jpg"); var path = Path.Combine(store.AssetsDirectory, relative); Directory.CreateDirectory(Path.GetDirectoryName(path)!); File.WriteAllText(path, kind); store.UpsertAsset(itemId, lang, kind, TranslationStore.LocalAssetUrlPrefix + relative.Replace('\\', '/'), 1); } private static string? Translation(TranslationStore store, string itemId, string lang, string field) => store.GetTranslations([itemId], [lang]) .GetValueOrDefault(itemId)? .GetValueOrDefault(lang)? .GetValueOrDefault(field); }