Files
gplan-2/game/tests/unit/presentation/battle_narrator_test.gd
T

102 lines
5.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tests/unit/presentation/battle_narrator_test.gd — 战斗叙述直接单测
# 断言面 = 纯函数文案:休整/商店/终局三类叙述把数值带进去(玩家读数面由这里出)、
# 胜负两态文案互异、未知输入有兜底不吐空串。期望值由注入内容数出来。
# 运行:godot --headless --path game --script res://tests/unit/presentation/battle_narrator_test.gd
extends SceneTree
const Kit := preload("res://tests/unit/test_kit.gd")
const NarratorScript := preload("res://presentation/battle_narrator.gd")
# 叙述寻址的 runner 替身:只提供 boss_name 实际读的两项(当前节点、关卡行)
class _BossRunner:
var level_row: Dictionary = {"level_index": 1}
var node: Dictionary = {}
func current_node() -> Dictionary:
return node
func _init() -> void:
_test_numeric_lines_carry_values()
_test_end_text_differs_by_result()
_test_phase_text_nonempty()
_test_boss_name_uses_boss_rowset()
_test_level_clear_wording()
quit(Kit.finish("battle_narrator_test"))
func _test_numeric_lines_carry_values() -> void:
var rest: String = NarratorScript.rest_line(12, 30, 40)
Kit.check("休整叙述带入回复量与当前血量(实际「%s」)" % rest,
rest.contains("12") and rest.contains("30") and rest.contains("40"))
var shop: String = NarratorScript.shop_line(77)
Kit.check("商店叙述带入 GP 数(实际「%s」)" % shop, shop.contains("77"))
Kit.check("奖励行与休整行互异(不是同一句套所有场景)",
NarratorScript.reward_line() != rest)
func _test_end_text_differs_by_result() -> void:
# 关卡收束(level_end=true)恒为「关卡完成!」——单场胜负文案只在非收束态出现
var level: String = NarratorScript.battle_end_text("lose", true)
Kit.check("关卡收束态恒为「关卡完成!」(实际「%s」)" % level, level == "关卡完成!")
var win: String = NarratorScript.battle_end_text("victory", false)
var lose: String = NarratorScript.battle_end_text("lose", false)
Kit.check("单场胜负文案互异(胜「%s」/负「%s」)" % [win, lose], win != lose)
Kit.check("胜利文案非空(实际「%s」)" % win, win != "")
var unknown: String = NarratorScript.battle_end_text("something_else", false)
Kit.check("未知结果有兜底文案不吐空串(实际「%s」)" % unknown, unknown != "")
func _test_phase_text_nonempty() -> void:
var t: String = NarratorScript.phase_text(1, "", false, false, "")
Kit.check("相位叙述非空(实际「%s」)" % t, t != "")
var boss: String = NarratorScript.phase_text(2, "", false, true, "灰矮人石君王")
Kit.check("Boss 在场时叙述带入 Boss 名(实际「%s」)" % boss, boss.contains("灰矮人石君王"))
# 叙述寻址按行类取 Boss 行集(S 清单 S15 换代):Boss 节点名必须来自 (关卡, boss, 带) 行集,
# 不能落到同深度的战斗行集——期望名由表行集首行读出,不写死字面量。
func _test_boss_name_uses_boss_rowset() -> void:
var db = load("res://core/config_db.gd").new()
var loaded: bool = db.load_tables("res://data/tables", false)
Kit.check_quiet(loaded, "叙述寻址用例:数值表加载成功")
if not loaded:
return
var boss_row := {}
for row in db.combat.enemy.rows:
if int(row.level_index) == 1 and String(row.get("row_kind", "")) == "boss":
boss_row = row
break
Kit.check_quiet(not boss_row.is_empty(), "叙述寻址用例:第一关有 Boss 行")
if boss_row.is_empty():
return
var boss_depth: int = int(boss_row.depth_band)
var boss_rows: Array = db.combat.enemy.resolve_rowset(1, boss_depth, "boss")
var battle_rows: Array = db.combat.enemy.resolve_rowset(1, boss_depth, "battle")
var boss_expect := String(boss_rows[0].get("display_name", ""))
var battle_name := String(battle_rows[0].get("display_name", ""))
var runner := _BossRunner.new()
runner.node = {"node_depth": boss_depth, "type": "boss"}
var got: String = NarratorScript.boss_name(runner, db)
Kit.check("Boss 名取自 Boss 行集首行(期望「%s」实际「%s」)〔fv24〕" % [boss_expect, got], got == boss_expect)
Kit.check("Boss 名与同深度战斗行集名不同(期望「%s」≠「%s」——行类路由可判别)〔fv24〕" % [boss_expect, battle_name], boss_expect != battle_name)
# 关卡完成停点文案族措辞钉子(口径换代批):回血行/满血合法态/渠道句/摘要关数行——
# 旧措辞退役后玩家可见面由本组断言钉在新措辞上(撤销证明:回退 battle_narrator 对应行→断言红→复原复绿)
func _test_level_clear_wording() -> void:
var healed: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 5, "hp_before": 10, "hp_after": 15})
Kit.check("关卡完成回血行带入回血量与生命区间(实际「%s」)〔口径换代 V1〕" % healed,
healed.contains("关卡完成回血 +5(生命 10 → 15)"))
var full_hp: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 0, "hp_before": 12, "hp_after": 12})
Kit.check("满血零回血合法态文案(实际「%s」)〔口径换代 V1〕" % full_hp,
full_hp.contains("生命已满——关卡完成回血 0(合法态)"))
var node_header: String = NarratorScript.node_curio_header()
Kit.check("奖励节点头部行渠道句点明关卡完成三选一(实际「%s」)〔口径换代 V2〕" % node_header,
node_header.contains("与关卡完成专长三选一同库分流"))
var summary: String = NarratorScript.adventure_summary_text(
{"cleared": false, "result": "failed", "levels_cleared": 1, "stopped_at": 2, "keystone_total": 4, "master_seed": 42})
Kit.check("冒险摘要完成关数行(实际「%s」)〔口径换代 V3〕" % summary,
summary.contains("完成 1 关 · 止步第 2 层") and not summary.contains("通关"))