Files

135 lines
6.5 KiB
C#
Raw Permalink Normal View History

using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
namespace Ironspore.Tests
{
public sealed class LocalizationTests
{
LocalizationCatalog catalog;
bool hadPreference;
string preference;
[SetUp]
public void Setup()
{
hadPreference = PlayerPrefs.HasKey(GameLocalization.PreferenceKey);
preference = PlayerPrefs.GetString(GameLocalization.PreferenceKey, "");
catalog = AssetDatabase.LoadAssetAtPath<LocalizationCatalog>("Assets/Game/Localization/LocalizationCatalog.asset");
Assert.IsNotNull(catalog, "Run Ironspore/Configure Localization first.");
GameLocalization.Initialize(catalog);
}
[TearDown]
public void Cleanup()
{
if (hadPreference)
PlayerPrefs.SetString(GameLocalization.PreferenceKey, preference);
else
PlayerPrefs.DeleteKey(GameLocalization.PreferenceKey);
if (catalog)
GameLocalization.Initialize(catalog);
PlayerPrefs.Save();
}
[TestCase("en", "zh-CN", "en")]
[TestCase("zh-Hans", "en-US", "zh-Hans")]
[TestCase("", "zh-TW", "zh-Hans")]
[TestCase("", "en-GB", "en")]
[TestCase("obsolete", "zh-HK", "zh-Hans")]
[TestCase("", "ja-JP", "en")]
[TestCase(null, null, "en")]
public void SavedSystemAndFallbackPriority(string saved, string system, string expected)
{
Assert.AreEqual(expected, GameLocalization.ResolveInitialLocale(saved, system));
}
[Test]
public void AdditionalLocalesCanUseTheSameSelector()
{
Assert.AreEqual("fr", GameLocalization.ResolveInitialLocale("fr", "en-US", new[] { "en", "zh-Hans", "fr" }));
Assert.AreEqual("fr", GameLocalization.ResolveInitialLocale("", "fr-CA", new[] { "en", "fr" }));
}
[Test]
public void EveryKeyAndFormatArgumentMatchesAndRequiredGlyphsExist()
{
var english = GameLocalization.ReadTable(catalog.locales.Single(x => x.code == "en").table);
foreach (var locale in catalog.locales)
{
var translated = GameLocalization.ReadTable(locale.table);
CollectionAssert.AreEquivalent(english.Keys, translated.Keys, locale.code);
foreach (var entry in translated)
{
var pattern = @"\{(\d+)(?:[^}]*)\}";
string[] expected = Regex.Matches(english[entry.Key], pattern).Cast<Match>().Select(x => x.Groups[1].Value).ToArray();
string[] actual = Regex.Matches(entry.Value, pattern).Cast<Match>().Select(x => x.Groups[1].Value).ToArray();
CollectionAssert.AreEquivalent(expected, actual, locale.code + ":" + entry.Key);
int count = expected.Length == 0 ? 0 : expected.Select(int.Parse).Max() + 1;
Assert.DoesNotThrow(() => string.Format(entry.Value, Enumerable.Repeat<object>("sample", count).ToArray()), entry.Key);
foreach (char character in entry.Value.Where(c => !char.IsControl(c)))
// Dynamic atlases are cleared on build; verify that the source font can supply each glyph.
Assert.IsTrue(catalog.uiFont.HasCharacter(character, false, true), "Missing glyph: " + character + " in " + entry.Key);
}
}
}
[Test]
public void SelectionPersistsAndInvalidSelectionDoesNotChangePreference()
{
Assert.IsTrue(GameLocalization.SelectLocale("zh-Hans"));
GameLocalization.Initialize(catalog);
Assert.AreEqual("zh-Hans", GameLocalization.CurrentCode);
Assert.IsFalse(GameLocalization.SelectLocale("unavailable"));
Assert.AreEqual("zh-Hans", PlayerPrefs.GetString(GameLocalization.PreferenceKey));
Assert.IsTrue(GameLocalization.SelectLocale("en"));
GameLocalization.Initialize(catalog);
Assert.AreEqual("en", GameLocalization.CurrentCode);
}
[Test]
public void ExistingMessagesAndNamesReformatWithoutMutatingSaveOrIdentifiers()
{
var state = new GameSave();
state.run.cargo.Add(new CargoStack("blueprint_coil_capacitor", 1));
string before = JsonUtility.ToJson(state);
var notice = GameLocalization.Message("notice.recovered", GameLocalization.Message("item.blueprint_coil_capacitor"), 3);
GameLocalization.SelectLocale("en", false);
StringAssert.Contains("COIL CAPACITOR", notice.ToString());
GameLocalization.SelectLocale("zh-Hans", false);
StringAssert.Contains("电磁电容", notice.ToString());
StringAssert.Contains("×3", notice.ToString());
StringAssert.Contains("电磁电容", state.run.cargo[0].Name);
Assert.AreEqual(before, JsonUtility.ToJson(state));
Assert.AreEqual(GameSave.CurrentVersion, state.version);
}
[Test]
public void MissingTranslationUsesEnglishFallback()
{
var temporary = ScriptableObject.CreateInstance<LocalizationCatalog>();
var english = new UnityEngine.TextAsset("{\"entries\":[{\"key\":\"test.fallback\",\"value\":\"Readable English {0}\"}]}");
var chinese = new UnityEngine.TextAsset("{\"entries\":[]}");
try
{
temporary.locales = new[] { new GameLocale { code = "en", table = english }, new GameLocale { code = "zh-Hans", table = chinese } };
GameLocalization.Initialize(temporary);
GameLocalization.SelectLocale("zh-Hans", false);
Assert.AreEqual("Readable English 7", GameLocalization.Text("test.fallback", 7));
}
finally
{
UnityEngine.Object.DestroyImmediate(temporary);
UnityEngine.Object.DestroyImmediate(english);
UnityEngine.Object.DestroyImmediate(chinese);
}
}
[Test]
public void DuplicateKeysAreRejected()
{
var table = new UnityEngine.TextAsset("{\"entries\":[{\"key\":\"same\",\"value\":\"one\"},{\"key\":\"same\",\"value\":\"two\"}]}");
try
{
Assert.Throws<ArgumentException>(() => GameLocalization.ReadTable(table));
}
finally { UnityEngine.Object.DestroyImmediate(table); }
}
}
}