Files
jellyfin-multilang/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxySortingTests.cs
T
ajp_anton 096c6be8c7 Release 0.3.4: Jellyfin 12 stable support and audit fixes
Harden proxy permissions and cache behavior, streamline metadata fetching, remove obsolete rules, and validate the stable SDK with expanded regression coverage. Document backup format changes.
2026-09-09 01:18:43 +00:00

176 lines
5.8 KiB
C#

using System.Globalization;
using System.Text.Json.Nodes;
using Jellyfin.Plugin.Multilang.Configuration;
using Jellyfin.Plugin.Multilang.Services;
namespace Jellyfin.Plugin.Multilang.Tests;
public sealed class ItemsProxySortingTests
{
[Fact]
public void TranslationOnlyDoesNotRewriteUpstreamPaging()
{
var root = JsonNode.Parse("""{"Items":[{"Name":"One"},{"Name":"Two"}],"TotalRecordCount":200,"StartIndex":100}""")!;
var original = root.ToJsonString();
ItemsProxySorting.Apply(root, new ItemsProxyControls("", "", "", 0, 0, "", "", false), CultureInfo.InvariantCulture, []);
Assert.Equal(original, root.ToJsonString());
}
[Fact]
public void GetSortArticlesUsesBuiltInLanguageFallback()
{
var articles = ItemsProxySorting.GetSortArticles(new SortArticleCatalog(), [], "sv-FI");
Assert.Equal(["en", "ett"], articles);
}
[Fact]
public void GetSortArticlesUsesConfiguredLanguageFallback()
{
var articles = ItemsProxySorting.GetSortArticles(
new SortArticleCatalog(),
[new SortArticleEntry { Language = "en", Articles = "one, two" }],
"en-CA");
Assert.Equal(["one", "two"], articles);
}
[Fact]
public void GetSortArticlesPrefersConfiguredExactLanguage()
{
var articles = ItemsProxySorting.GetSortArticles(
new SortArticleCatalog(),
[
new SortArticleEntry { Language = "en", Articles = "language" },
new SortArticleEntry { Language = "en-GB", Articles = "exact" }
],
"en-GB");
Assert.Equal(["exact"], articles);
}
[Fact]
public void GetSortArticlesIncludesAlwaysIgnoredArticlesFromOtherLanguages()
{
var articles = ItemsProxySorting.GetSortArticles(
new SortArticleCatalog(),
[
new SortArticleEntry { Language = "en", Articles = "a, an, the", AlwaysApply = true },
new SortArticleEntry { Language = "it", Articles = "il, lo, la" }
],
"it");
Assert.Equal(["a", "an", "the", "il", "lo", "la"], articles);
}
[Fact]
public void GetSortArticlesReturnsNoneWhenArticleIgnoringIsDisabled()
{
var articles = ItemsProxySorting.GetSortArticles(
new SortArticleCatalog(),
[new SortArticleEntry { Language = "en", Articles = "a, an, the", AlwaysApply = true }],
"en",
ignoreArticles: false);
Assert.Empty(articles);
}
[Fact]
public void ApplySortsByTitleAfterLeadingArticles()
{
var root = ItemsRoot("The Matrix", "A Beautiful Mind", "Avatar");
ItemsProxySorting.Apply(
root,
new ItemsProxyControls("SortName", "Ascending", "", 0, 0, "en-US", ""),
CultureInfo.GetCultureInfo("en-US"),
["a", "an", "the"]);
Assert.Equal(["Avatar", "A Beautiful Mind", "The Matrix"], ItemNames(root));
}
[Fact]
public void ApplyUsesEachTitlesLanguageForArticleRemoval()
{
var root = ItemsRoot("La La Land", "La vita e bella", "Terminator", "The Matrix");
var articles = new Dictionary<string, string[]>(StringComparer.Ordinal)
{
["La La Land"] = [],
["La vita e bella"] = ["il", "lo", "la"],
["Terminator"] = [],
["The Matrix"] = ["a", "an", "the"]
};
ItemsProxySorting.Apply(
root,
new ItemsProxyControls("SortName", "Ascending", "", 0, 0, "en-US", ""),
CultureInfo.GetCultureInfo("en-US"),
item => articles[item["Name"]!.GetValue<string>()]);
Assert.Equal(["La La Land", "The Matrix", "Terminator", "La vita e bella"], ItemNames(root));
}
[Fact]
public void ApplyStripsApostropheArticles()
{
var root = ItemsRoot("L'avventura", "The Matrix");
ItemsProxySorting.Apply(
root,
new ItemsProxyControls("SortName", "Ascending", "", 0, 0, "en-US", ""),
CultureInfo.GetCultureInfo("en-US"),
item => item["Name"]!.GetValue<string>() == "L'avventura" ? ["l'"] : ["the"]);
Assert.Equal(["L'avventura", "The Matrix"], ItemNames(root));
}
[Fact]
public void ApplyPadsNumbersDuringTitleSort()
{
var root = ItemsRoot("Movie 10", "Movie 2", "Movie 1");
ItemsProxySorting.Apply(
root,
new ItemsProxyControls("SortName", "Ascending", "", 0, 0, "en-US", ""),
CultureInfo.GetCultureInfo("en-US"),
[]);
Assert.Equal(["Movie 1", "Movie 2", "Movie 10"], ItemNames(root));
}
[Fact]
public void ApplyFiltersAndSlicesAfterLocalSort()
{
var root = ItemsRoot("The Matrix", "Magnolia", "A Monster Calls", "Avatar");
ItemsProxySorting.Apply(
root,
new ItemsProxyControls("SortName", "Ascending", "M", 1, 1, "en-US", ""),
CultureInfo.GetCultureInfo("en-US"),
["a", "an", "the"]);
Assert.Equal(["The Matrix"], ItemNames(root));
Assert.Equal(3, root["TotalRecordCount"]!.GetValue<int>());
Assert.Equal(1, root["StartIndex"]!.GetValue<int>());
}
private static JsonObject ItemsRoot(params string[] names)
{
var items = new JsonArray();
foreach (var name in names)
items.Add(new JsonObject { ["Name"] = name, ["SortName"] = name });
return new JsonObject
{
["Items"] = items,
["TotalRecordCount"] = names.Length,
["StartIndex"] = 0
};
}
private static string[] ItemNames(JsonObject root)
=> root["Items"]!.AsArray()
.OfType<JsonObject>()
.Select(item => item["Name"]!.GetValue<string>())
.ToArray();
}