Files
cursor-lang/CursorLang.Core.Tests/Resources/StringsTests.cs
T
alex dd0bbdea42
Pull request / build (pull_request) Successful in 52s
removed update
2026-08-13 14:58:26 +05:00

143 lines
4.2 KiB
C#

using System.Collections;
using System.Globalization;
using System.Resources;
using CursorLang.Core.Models;
using CursorLang.Core.Services;
namespace CursorLang.Core.Tests.Resources;
/// <summary>
/// Checks of the resources themselves: they carry every caption in the settings
/// window, and a missing key only shows on a live window.
/// </summary>
public sealed class StringsTests
{
private static readonly ResourceManager Resources =
new("CursorLang.Core.Resources.Strings", typeof(LocalizationService).Assembly);
private static readonly CultureInfo English = CultureInfo.GetCultureInfo("en");
private static readonly CultureInfo Russian = CultureInfo.GetCultureInfo("ru");
[Theory]
[MemberData(nameof(EnumKeys))]
public void Every_list_value_has_an_English_caption(string key)
{
Assert.False(string.IsNullOrWhiteSpace(Resources.GetString(key, English)));
}
[Theory]
[MemberData(nameof(EnumKeys))]
public void Every_list_value_has_a_Russian_caption(string key)
{
Assert.False(string.IsNullOrWhiteSpace(Resources.GetString(key, Russian)));
}
[Fact]
public void The_Russian_translation_covers_every_string()
{
List<string> missing = [];
foreach (string key in NeutralKeys())
{
// An untranslated resource falls back to English, so the Russian set
// is asked directly rather than through the string with a fallback
if (RussianSet().GetString(key) is null)
{
missing.Add(key);
}
}
Assert.Empty(missing);
}
[Fact]
public void The_Russian_translation_has_no_extra_strings()
{
HashSet<string> neutral = [.. NeutralKeys()];
List<string> extra = [];
foreach (DictionaryEntry entry in RussianSet())
{
var key = (string)entry.Key;
if (!neutral.Contains(key))
{
extra.Add(key);
}
}
Assert.Empty(extra);
}
[Fact]
public void There_are_no_empty_strings_in_the_resources()
{
foreach (string key in NeutralKeys())
{
Assert.False(string.IsNullOrWhiteSpace(Resources.GetString(key, English)), key);
Assert.False(string.IsNullOrWhiteSpace(Resources.GetString(key, Russian)), key);
}
}
/// <summary>
/// The version is put into the title by the app, so the place for it has to
/// be there in both languages: the title is the only place it is shown, and a
/// translation without the placeholder would quietly drop it.
/// </summary>
[Fact]
public void The_title_of_the_window_has_room_for_the_version()
{
Assert.Contains("{0}", Resources.GetString("SettingsTitle", English), StringComparison.Ordinal);
Assert.Contains("{0}", Resources.GetString("SettingsTitle", Russian), StringComparison.Ordinal);
}
public static TheoryData<string> EnumKeys()
{
var data = new TheoryData<string>();
foreach (string key in EnumKeysOf<AppTheme>())
{
data.Add(key);
}
foreach (string key in EnumKeysOf<PopupPlacementMode>())
{
data.Add(key);
}
foreach (string key in EnumKeysOf<AnchorSide>())
{
data.Add(key);
}
foreach (string key in EnumKeysOf<CaretSide>())
{
data.Add(key);
}
foreach (string key in EnumKeysOf<ScreenPosition>())
{
data.Add(key);
}
return data;
}
// A caption key is built from the type name and the value: PopupPlacementMode_AtCursor
private static IEnumerable<string> EnumKeysOf<TEnum>() where TEnum : struct, Enum =>
Enum.GetValues<TEnum>().Select(value => $"{typeof(TEnum).Name}_{value}");
private static IEnumerable<string> NeutralKeys()
{
ResourceSet set = Resources.GetResourceSet(CultureInfo.InvariantCulture, true, true)!;
foreach (DictionaryEntry entry in set)
{
yield return (string)entry.Key;
}
}
private static ResourceSet RussianSet() =>
Resources.GetResourceSet(Russian, createIfNotExists: true, tryParents: false)!;
}