# tests/unit/presentation/hud_presenter_test.gd — HUD 投影直接单测 # 断言面 = 纯函数投影:动作结果文案按拒绝原因逐类落字(玩家看到的每句提示都由这里出)、 # 未知原因有兜底文案(不吐空串)、棋盘变异行投影随表走。期望值由注入内容数出来。 # 运行:godot --headless --path game --script res://tests/unit/presentation/hud_presenter_test.gd extends SceneTree const Kit := preload("res://tests/unit/test_kit.gd") const HudScript := preload("res://presentation/hud_presenter.gd") func _init() -> void: _test_accepted_text() _test_reject_text_by_reason() _test_unknown_reason_fallback() quit(Kit.finish("hud_presenter_test")) func _test_accepted_text() -> void: var t: String = HudScript.outcome_text({"accepted": true}) Kit.check("受理态文案固定为「执行完成。」(实际「%s」)" % t, t == "执行完成。") func _test_reject_text_by_reason() -> void: var cases := { "not_adjacent": "不能执行:目标与小人不相邻", "target_revealed": "不能执行:目标已开", "seal_present": "不能封印:此格已有封印印记(封印为一次性承诺——相邻时左键直接挖开)", } var bad: Array[String] = [] for sub in cases: var got: String = HudScript.outcome_text({ "accepted": false, "reject_reason": "board_face", "sub_reason": sub, }) if got != String(cases[sub]): bad.append("%s→「%s」" % [sub, got]) Kit.check("棋盘面各拒绝原因文案逐类正确(错 %d 项 %s)" % [bad.size(), str(bad)], bad.is_empty()) var ap: String = HudScript.outcome_text({"accepted": false, "reject_reason": "resource_face"}) Kit.check("资源面拒绝文案为「AP 不足。」(实际「%s」)" % ap, ap == "AP 不足。") func _test_unknown_reason_fallback() -> void: var t: String = HudScript.outcome_text({"accepted": false, "reject_reason": "brand_new_reason"}) Kit.check("未知拒绝原因兜底为「动作被拒。」而非空串(实际「%s」)" % t, t == "动作被拒。") var sub: String = HudScript.outcome_text({ "accepted": false, "reject_reason": "board_face", "sub_reason": "brand_new_sub", }) Kit.check("棋盘面未知子因兜底带前缀可诊断(实际「%s」)" % sub, sub.begins_with("棋盘面拒绝: "))