summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Desktop.Tests')
-rw-r--r--src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj1
-rw-r--r--src/LivingVillage.Desktop.Tests/P61GlyphCoverageTests.fs97
-rw-r--r--src/LivingVillage.Desktop.Tests/PrototypeTests.fs6
3 files changed, 101 insertions, 3 deletions
diff --git a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
index 951e59b..e87ca23 100644
--- a/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
+++ b/src/LivingVillage.Desktop.Tests/LivingVillage.Desktop.Tests.fsproj
@@ -34,6 +34,7 @@
<Compile Include="P54ProfessionDailyTests.fs" />
<Compile Include="P55ProfessionRewardTests.fs" />
<Compile Include="P57MenuHighlightTests.fs" />
+ <Compile Include="P61GlyphCoverageTests.fs" />
<Compile Include="SampleTests.fs" />
</ItemGroup>
diff --git a/src/LivingVillage.Desktop.Tests/P61GlyphCoverageTests.fs b/src/LivingVillage.Desktop.Tests/P61GlyphCoverageTests.fs
new file mode 100644
index 0000000..f5f1a10
--- /dev/null
+++ b/src/LivingVillage.Desktop.Tests/P61GlyphCoverageTests.fs
@@ -0,0 +1,97 @@
+namespace LivingVillage.Desktop.Tests
+
+open System.IO
+open System.Text.RegularExpressions
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open LivingVillage.Desktop
+
+/// P61(G1 整改):中文界面字形覆盖。
+/// 断言 Desktop 全部用户可见中文文案所需字形 100% 在 CjkGlyphAtlas 内,
+/// 并对 G1 盘点缺的 16 字逐字断言。缺字会被 PixelText 置空(Game.fs:73-92),
+/// 因此该测试是「中文界面完整」的红→绿门。
+[<TestClass>]
+type P61GlyphCoverageTests () =
+
+ let isCjk (c: char) = c >= '\u4e00' && c <= '\u9fff'
+ let isInAtlas (c: char) = CjkGlyphAtlas.contains c
+
+ /// G1 盘点确认缺失、P61 修复的 16 个字。
+ let g1MissingChars = "冬包卷品夏料春玩秋第背车轴页香鱼".ToCharArray()
+
+ let repoRoot () : string =
+ let mutable dir = System.AppContext.BaseDirectory
+ let mutable found = None
+ while found.IsNone && not (System.String.IsNullOrEmpty dir) do
+ if File.Exists(Path.Combine(dir, "LivingVillage.sln")) then found <- Some dir
+ else
+ let parent = Path.GetDirectoryName dir
+ if parent = dir then dir <- "" else dir <- parent
+ match found with
+ | Some d -> d
+ | None -> failwith "找不到仓库根(LivingVillage.sln)"
+
+ /// 扫描 Desktop 源内字符串字面量里的 CJK 字符(跳过注释行)。
+ let sourceCjkChars () : Set<char> =
+ let root = repoRoot ()
+ let dir = Path.Combine(root, "src", "LivingVillage.Desktop")
+ let literal = Regex("\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"")
+ let mutable chars = Set.empty
+ for file in Directory.GetFiles(dir, "*.fs") do
+ for line in File.ReadAllLines file do
+ let trimmed = line.TrimStart()
+ if not (trimmed.StartsWith "//") then
+ for m in literal.Matches line do
+ for c in m.Groups.[1].Value do
+ if isCjk c then chars <- Set.add c chars
+ chars
+
+ [<TestMethod>]
+ member _.AllSourceChineseLiteralsHaveAtlasGlyphs () =
+ let chars = sourceCjkChars ()
+ let missing = chars |> Set.filter (fun c -> not (isInAtlas c)) |> Set.toList
+ CollectionAssert.AreEqual(
+ [||],
+ missing |> List.map string |> List.toArray,
+ sprintf "Desktop 用户可见中文文案缺字形 %d 个: %s(需补入 CjkGlyphAtlas.characterTable 并重生成图集)"
+ missing.Length (missing |> List.map string |> String.concat ""))
+
+ [<TestMethod>]
+ member _.G1MissingCharsAreNowInAtlas () =
+ let missing = g1MissingChars |> Array.filter (fun c -> not (isInAtlas c)) |> Array.toList
+ CollectionAssert.AreEqual(
+ [||],
+ missing |> List.map string |> List.toArray,
+ sprintf "G1 缺字仍未入图集: %s" (missing |> List.map string |> String.concat ""))
+
+ [<TestMethod>]
+ member _.RequiredUiLabelsAreAtlasBacked () =
+ let missing =
+ ChineseText.requiredUiLabels
+ |> List.collect (fun s -> s.ToCharArray() |> Array.toList)
+ |> List.filter isCjk
+ |> List.filter (fun c -> not (isInAtlas c))
+ |> List.distinct
+ CollectionAssert.AreEqual(
+ [||],
+ missing |> List.map string |> List.toArray,
+ sprintf "requiredUiLabels 缺字形: %s" (missing |> List.map string |> String.concat ""))
+
+ [<TestMethod>]
+ member _.CalendarAndFooterAndItemCopyAreAtlasBacked () =
+ // 派发词点名要可见完整的三类运行期文案,逐字钉住,防止再次缺字。
+ let pinned =
+ [ HudLayout.seasonNames |> String.concat ""
+ HudLayout.calendarLine1 { Season = "春"; DayNumber = 1L; Period = "清晨"; Clock = "06:00" }
+ "第 1/3 页 空格 翻页 Esc 关闭"
+ "背包物品×1"
+ "鱼"; "卷轴"; "香料"; "玩家"; "回车:接受任务" ]
+ let missing =
+ pinned
+ |> List.collect (fun s -> s.ToCharArray() |> Array.toList)
+ |> List.filter isCjk
+ |> List.distinct
+ |> List.filter (fun c -> not (isInAtlas c))
+ CollectionAssert.AreEqual(
+ [||],
+ missing |> List.map string |> List.toArray,
+ sprintf "运行期文案缺字形: %s" (missing |> List.map string |> String.concat ""))
diff --git a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
index 2de0996..55de3c8 100644
--- a/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
+++ b/src/LivingVillage.Desktop.Tests/PrototypeTests.fs
@@ -1094,14 +1094,14 @@ type PrototypeTests () =
[<TestMethod>]
member _.CjkGlyphAtlasHasAStableCharacterTableAndGeometry () =
- Assert.AreEqual<int>(307, characters.Length)
+ Assert.AreEqual<int>(323, characters.Length)
CollectionAssert.AreEqual(characters, characters |> Array.sort)
Assert.AreEqual<int>(characters.Length, characters |> Array.distinct |> Array.length)
Assert.AreEqual<int>(16, columns)
Assert.AreEqual<int>(24, cellPixels)
- Assert.AreEqual<int>(20, rowCount)
+ Assert.AreEqual<int>(21, rowCount)
Assert.AreEqual<int>(384, pixelWidth)
- Assert.AreEqual<int>(480, pixelHeight)
+ Assert.AreEqual<int>(504, pixelHeight)
Assert.AreEqual<string>("Assets/cjk-glyph-atlas.png", assetRelativePath)
Assert.AreEqual<string>("Assets/cjk-glyphs.txt", manifestRelativePath)