Files
jellyfin-multilang/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxyTransformerResolutionTests.cs
T
ajp_anton e36775f1a3 Release 0.2.5: harden proxy and streamline metadata fetching
Remove obsolete rule formats, batch SQLite work, preserve artwork source URLs, and coordinate refresh workers with maintenance. Add regression coverage and document backup format changes.
2026-09-09 01:18:43 +00:00

183 lines
5.8 KiB
C#

using Jellyfin.Plugin.Multilang.Data;
using Jellyfin.Plugin.Multilang.Services;
namespace Jellyfin.Plugin.Multilang.Tests;
public sealed class ItemsProxyTransformerResolutionTests
{
private const string TitleField = "title";
private const string OverviewField = "overview";
private const string TaglineField = "tagline";
private const string PosterKind = "poster";
private const string LogoKind = "logo";
private const string OriginalAction = "Original";
private const string LanguagePrefix = "Language:";
[Fact]
public void TraceUsesStoredOriginalTranslationWhenOriginalTitleIsEmpty()
{
var facts = Facts(originalTitle: "", originalLanguage: "fi");
var translations = TextTranslations((OriginalAction, TitleField, "Alkuperainen nimi"));
var attempts = new List<ItemsProxyResolutionAttempt>();
var normal = ItemsProxyTransformer.ResolveField(TitleField, [OriginalAction], facts, translations);
var traced = ItemsProxyTransformer.ResolveField(TitleField, [OriginalAction], facts, translations, attempts.Add);
Assert.Equal(normal, traced);
Assert.Equal("fi", traced.Language);
var chosen = Assert.Single(attempts);
Assert.True(chosen.Chosen);
Assert.Equal("Original/title", chosen.LookupKey);
Assert.Equal(traced.Value, chosen.Value);
}
[Fact]
public void ResolveFieldUsesFirstLanguageWithData()
{
var translations = TextTranslations(
("sv", OverviewField, ""),
("fi", OverviewField, "Finnish overview"),
("en", OverviewField, "English overview"));
var result = ItemsProxyTransformer.ResolveField(
OverviewField,
[LanguagePrefix + "sv", LanguagePrefix + "fi", LanguagePrefix + "en"],
Facts(),
translations);
Assert.True(result.Change);
Assert.Equal("Finnish overview", result.Value);
Assert.Equal("fi", result.Language);
}
[Fact]
public void ResolveFieldUsesOriginalTitleBeforeTranslations()
{
var result = ItemsProxyTransformer.ResolveField(
TitleField,
[OriginalAction, LanguagePrefix + "en"],
Facts(originalTitle: "Original title", originalLanguage: "en"),
TextTranslations(("en", TitleField, "English title")));
Assert.True(result.Change);
Assert.Equal("Original title", result.Value);
Assert.Equal("en", result.Language);
}
[Fact]
public void ResolveFieldFallsBackToJellyfinForMissingTitle()
{
var result = ItemsProxyTransformer.ResolveField(
TitleField,
[LanguagePrefix + "sv"],
Facts(),
TextTranslations());
Assert.False(result.Change);
Assert.Null(result.Value);
Assert.Null(result.Language);
}
[Fact]
public void ResolveFieldClearsMissingOptionalText()
{
var result = ItemsProxyTransformer.ResolveField(
TaglineField,
[LanguagePrefix + "sv"],
Facts(),
TextTranslations());
Assert.True(result.Change);
Assert.Equal(string.Empty, result.Value);
}
[Fact]
public void ResolveAssetUsesFirstLanguageWithData()
{
var assets = AssetTranslations(
(PosterKind, "sv", ""),
(PosterKind, "fi", "https://image/fi.jpg"),
(PosterKind, "en", "https://image/en.jpg"));
var result = ItemsProxyTransformer.ResolveAsset(
PosterKind,
[LanguagePrefix + "sv", LanguagePrefix + "fi", LanguagePrefix + "en"],
assets);
Assert.True(result.Change);
Assert.Equal("https://image/fi.jpg", result.Value);
}
[Fact]
public void ResolveAssetFallsBackToJellyfinForMissingPoster()
{
var result = ItemsProxyTransformer.ResolveAsset(
PosterKind,
[LanguagePrefix + "sv"],
AssetTranslations());
Assert.False(result.Change);
Assert.Null(result.Value);
}
[Fact]
public void ResolveAssetClearsMissingOptionalImage()
{
var result = ItemsProxyTransformer.ResolveAsset(
LogoKind,
[LanguagePrefix + "sv"],
AssetTranslations());
Assert.True(result.Change);
Assert.Equal(string.Empty, result.Value);
}
private static Dictionary<string, Dictionary<string, string>> TextTranslations(params (string Lang, string Field, string Value)[] rows)
{
var result = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
foreach (var (lang, field, value) in rows)
{
if (!result.TryGetValue(lang, out var byField))
{
byField = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
result[lang] = byField;
}
byField[field] = value;
}
return result;
}
private static Dictionary<string, Dictionary<string, string>> AssetTranslations(params (string Kind, string Lang, string Value)[] rows)
{
var result = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
foreach (var (kind, lang, value) in rows)
{
if (!result.TryGetValue(kind, out var byLang))
{
byLang = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
result[kind] = byLang;
}
byLang[lang] = value;
}
return result;
}
private static FactsData Facts(string originalTitle = "", string originalLanguage = "")
=> new(
"item",
"tmdb",
"movie",
originalTitle,
originalLanguage,
"",
"[]",
"[]",
"[]",
"",
"[]",
0,
0);
}