summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-28 09:27:14 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-28 09:27:14 +0800
commitcd9b8cc13c3f03abe4b6b2c98281fc9b926b4acd (patch)
tree57681dc8980a63205cbbc6930223073056696ead /src/LivingVillage.Desktop.Tests/P38HudIconTests.fs
parent70394b3e4ded4811b1f482e6d036b23b7dcb1765 (diff)
downloadliving-village-cd9b8cc13c3f03abe4b6b2c98281fc9b926b4acd.tar.gz
test(desktop): P38 HUD 图标布局与确定性回归
新增 P38HudIconTests(4 例):五段图标唯一且 7x7 点阵良构、段宽=图标+间隙+文本且 不重叠/在 1280 内、段与布局确定、昼夜底色半透明且覆盖图标与文本。
Diffstat (limited to 'src/LivingVillage.Desktop.Tests/P38HudIconTests.fs')
-rw-r--r--src/LivingVillage.Desktop.Tests/P38HudIconTests.fs71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs b/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs
new file mode 100644
index 0000000..72885fb
--- /dev/null
+++ b/src/LivingVillage.Desktop.Tests/P38HudIconTests.fs
@@ -0,0 +1,71 @@
+namespace LivingVillage.Desktop.Tests
+
+open Microsoft.VisualStudio.TestTools.UnitTesting
+open LivingVillage.Kernel
+open LivingVillage.Kernel.Sim
+open LivingVillage.Desktop
+
+/// P38 界面升级切片:顶部常驻 HUD 图标化(时段/时间/倍速/体力/钱币)的布局与确定性回归。
+[<TestClass>]
+type P38HudIconTests () =
+
+ let world = Sim.initialWorldN 42UL 4
+ let control = SimulationControl.initial
+ let segments = HudLayout.segments world control
+
+ [<TestMethod>]
+ member _.EveryHudSegmentCarriesAWellFormedDistinctIcon () =
+ let expected =
+ [ "时段", HudLayout.PeriodIcon
+ "时间", HudLayout.ClockIcon
+ "倍速", HudLayout.SpeedIcon
+ "体力", HudLayout.EnergyIcon
+ "钱币", HudLayout.MoneyIcon ]
+ Assert.AreEqual<string list>(expected |> List.map fst, segments |> List.map (fun segment -> segment.Label))
+ Assert.AreEqual<HudLayout.HudIcon list>(expected |> List.map snd, segments |> List.map (fun segment -> segment.Icon))
+ for segment in segments do
+ let rows = HudLayout.iconRows segment.Icon
+ Assert.IsTrue(rows.Length = HudLayout.iconGrid, sprintf "%s 图标行数" segment.Label)
+ for row in rows do
+ Assert.IsTrue(row.Length = HudLayout.iconGrid, sprintf "%s 图标行宽" segment.Label)
+ Assert.IsTrue(rows |> List.exists (fun row -> row.Contains "1"), sprintf "%s 图标必须有实心像素" segment.Label)
+ let distinct = segments |> List.map (fun segment -> segment.Icon) |> List.distinct |> List.length
+ Assert.IsTrue(segments.Length = distinct, "每个常驻段图标应互不相同")
+
+ [<TestMethod>]
+ member _.HudLayoutReservesIconThenTextAndFitsTheStrip () =
+ let placed = HudLayout.layout segments
+ Assert.AreEqual<int>(segments.Length, placed.Length)
+ let (firstX, _, _) = List.head placed
+ Assert.AreEqual<int>(HudLayout.paddingX, firstX)
+ for (x, width, segment) in placed do
+ let textWidth = FloatingPrompt.measureWidth (HudLayout.segmentText segment) HudLayout.textScale
+ Assert.AreEqual<int>(HudLayout.iconWidth + HudLayout.iconGap + textWidth, width)
+ // 图标与文本都必须落在段宽内。
+ Assert.IsTrue(x + HudLayout.iconWidth <= x + width, "图标越出段宽")
+ Assert.IsTrue(HudLayout.textOrigin x + textWidth <= x + width, "文本越出段宽")
+ Assert.IsTrue(HudLayout.iconHeight <= HudLayout.barHeight, "图标必须放进窄条")
+ placed
+ |> List.pairwise
+ |> List.iter (fun ((x1, w1, _), (x2, _, _)) ->
+ Assert.IsTrue(x2 >= x1 + w1, sprintf "段重叠:%d+%d vs %d" x1 w1 x2))
+ let (lastX, lastWidth, _) = List.last placed
+ Assert.IsTrue(lastX + lastWidth <= 1280, "最后一段必须留在 1280 视口内")
+
+ [<TestMethod>]
+ member _.HudSegmentsAndLayoutAreDeterministic () =
+ Assert.AreEqual<HudLayout.Segment list>(segments, HudLayout.segments world control)
+ Assert.AreEqual<(int * int * HudLayout.Segment) list>(HudLayout.layout segments, HudLayout.layout segments)
+ for segment in segments do
+ Assert.AreEqual<string list>(HudLayout.iconRows segment.Icon, HudLayout.iconRows segment.Icon)
+
+ [<TestMethod>]
+ member _.HudBackdropCoversIconAndTextInBothPeriods () =
+ for mode in [ Day; Night ] do
+ let palette = HudLayout.palette mode
+ Assert.IsTrue(palette.SegmentBackdrop.A > 0uy && palette.SegmentBackdrop.A < 255uy, "底色必须半透明")
+ for (x, width, _) in HudLayout.layout segments do
+ let rect = HudLayout.segmentBackdrop x width
+ Assert.IsTrue(rect.X <= x, "底色未覆盖图标左沿")
+ Assert.IsTrue(rect.X + rect.Width >= HudLayout.textOrigin x, "底色未覆盖文本区")
+ Assert.IsTrue(rect.Y >= 0 && rect.Y + rect.Height <= HudLayout.barHeight, "底色必须留在窄条内")