Files
aetherbound-guild/runtime/tests/foundation/readiness_page_controller_test.gd
T

129 lines
7.1 KiB
GDScript

extends SceneTree
const Controller = preload("res://entry/readiness_page_controller.gd")
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
var controller := Controller.new()
var company := _fixture_company()
var ordered := _fixture_formation("ordered")
var warnings: Array = [
{"severity": "notice", "text": "NO SUSTAIN", "owner": "coverage"},
{"severity": "warning", "text": "Outcome not guaranteed", "owner": "risk"},
{"severity": "info", "text": "Reserve: none", "owner": "formation"},
]
var view: Dictionary = controller.snapshot(company, ordered, warnings, "r-2", "en")
expect(view.ok and view.page_id == "readiness_review", "snapshot identifies Readiness")
expect(view.company.owned_count == 4 and view.company.line_capacity == 4, "snapshot copies Company and capacity facts")
expect(view.contract.contract_id == "CTR-R1-01" and view.contract.difficulty == "stormbound", "snapshot copies Contract facts")
expect(view.formation.status == "ordered" and view.formation.state == "ordered", "ordered status is classified")
expect(view.formation.orientation == "rear_left_front_right" and view.formation.front_position == 0, "snapshot exposes frozen orientation")
expect(view.order.front_to_rear_ids == ["r-1", "r-2", "r-3", "r-4"], "snapshot preserves saved order")
expect(view.order.front_recruit.recruit_id == "r-1" and view.order.reviewed_recruit_id == "r-2", "snapshot binds front Recruit and review selection")
expect(view.order.ordered_recruits[0].relation.first_threat_target, "snapshot binds relation facts")
expect(view.formation.coverage.protection == 2 and view.warnings.count == 3, "snapshot copies coverage and warning rows")
expect(view.commands.accept_enabled and not view.commands.risk_enabled and view.commands.revise_enabled, "ordered command eligibility is truthful")
expect(view.receipt.present == false and view.accepted_party_snapshot.is_empty(), "ordered state has no readiness receipt")
var ready_formation := _fixture_formation("ready")
var ready: Dictionary = controller.snapshot(company, ready_formation, warnings, "missing", "zh_CN")
expect(ready.ok and ready.formation.state == "ready", "ready status is classified")
expect(ready.order.reviewed_recruit_id.is_empty() and ready.order.review_reason == "no_selection", "stale review selection falls back")
expect(not ready.commands.accept_enabled and ready.commands.risk_enabled, "ready command eligibility enables Risk only")
expect(ready.receipt.present and ready.receipt.latest.receipt_hash == "receipt-hash-001", "ready snapshot exposes receipt")
var duplicate: Dictionary = controller.snapshot(company, _formation_with_order("r-1", "r-1", "r-3", "r-4"), warnings)
expect(not duplicate.ok and duplicate.code == "READINESS_RECRUIT_DUPLICATE", "duplicate saved order is rejected")
var unknown: Dictionary = controller.snapshot(company, _formation_with_order("r-1", "r-2", "r-3", "missing"), warnings)
expect(not unknown.ok and unknown.code == "READINESS_RECRUIT_UNKNOWN", "unknown saved Recruit is rejected")
var no_order_formation := _fixture_formation("draft")
no_order_formation.saved_front_to_rear_ids = []
var no_order: Dictionary = controller.snapshot(company, no_order_formation, warnings)
expect(not no_order.ok and no_order.code == "READINESS_ORDER_REQUIRED", "missing saved order is rejected")
var invalid_status := _fixture_formation("draft")
invalid_status.saved_front_to_rear_ids = ["r-1", "r-2", "r-3", "r-4"]
var bad_status: Dictionary = controller.snapshot(company, invalid_status, warnings)
expect(not bad_status.ok and bad_status.code == "READINESS_STATUS_INVALID", "invalid status is rejected")
var missing: Dictionary = controller.snapshot({}, ordered, warnings)
expect(not missing.ok and missing.code == "COMPANY_REQUIRED", "missing Company is rejected")
var no_formation: Dictionary = controller.snapshot(company, {}, warnings)
expect(not no_formation.ok and no_formation.code == "FORMATION_REQUIRED", "missing Formation is rejected")
var copied_recruit: Dictionary = view.order.ordered_recruits[0].recruit
copied_recruit.rendered_name_snapshot.display_name = "changed"
view.formation.relations[0].protected_by_recruit_ids.append("changed")
view.warnings.rows[0].text = "changed"
expect(company.owned_recruits[0].rendered_name_snapshot.display_name == "Ari", "Recruit facts are deep copied")
expect(ordered.relations[0].protected_by_recruit_ids.is_empty(), "relation facts are deep copied")
expect(warnings[0].text == "NO SUSTAIN", "warning facts are deep copied")
if failures.is_empty():
print("ABG_M22_READINESS_CONTROLLER_OK company=4 order=4 status=ordered,ready selection=normalized warnings=copied commands=revise,back,accept,risk receipt=copied")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func _fixture_company() -> Dictionary:
return {
"company_id": "company-001",
"owned_recruits": [
{"recruit_id": "r-1", "profession_id": "PF-B01", "rendered_name_snapshot": {"display_name": "Ari"}},
{"recruit_id": "r-2", "profession_id": "PF-B05", "rendered_name_snapshot": {"display_name": "Bram"}},
{"recruit_id": "r-3", "profession_id": "PF-B07", "rendered_name_snapshot": {"display_name": "Cera"}},
{"recruit_id": "r-4", "profession_id": "PF-B03", "rendered_name_snapshot": {"display_name": "Dain"}},
],
"active_contract": {
"contract_id": "CTR-R1-01",
"run_id": "run-001",
"difficulty": "stormbound",
"coin": 38,
"line_capacity": 4,
},
}
func _fixture_formation(status: String) -> Dictionary:
var formation := {
"status": status,
"orientation": "rear_left_front_right",
"front_position": 0,
"line_capacity": 4,
"saved_front_to_rear_ids": ["r-1", "r-2", "r-3", "r-4"],
"order_revision": 2,
"relations": [
{"position": 0, "recruit_id": "r-1", "first_threat_target": true, "protected_by_recruit_ids": []},
{"position": 1, "recruit_id": "r-2", "first_threat_target": false, "protected_by_recruit_ids": ["r-1"]},
{"position": 2, "recruit_id": "r-3", "first_threat_target": false, "protected_by_recruit_ids": ["r-1"]},
{"position": 3, "recruit_id": "r-4", "first_threat_target": false, "protected_by_recruit_ids": []},
],
"coverage": {"protection": 2, "long_reach": 2, "sustain": 1, "control": 1},
"first_threat": {"target_position": 0, "target_recruit_id": "r-1", "enemy_count": 3, "wave_count": 2},
"risk_options": [{"risk_option_id": "risk-1"}, {"risk_option_id": "risk-2"}, {"risk_option_id": "risk-3"}],
"readiness_receipts": [],
"accepted_party_snapshot": {},
}
if status == "ready":
formation.readiness_receipts = [{"receipt_hash": "receipt-hash-001", "snapshot_id": "snapshot-001"}]
formation.accepted_party_snapshot = {"snapshot_id": "snapshot-001", "risk_option_ids": ["risk-1", "risk-2", "risk-3"]}
return formation
func _formation_with_order(first: String, second: String, third: String, fourth: String) -> Dictionary:
var formation := _fixture_formation("ordered")
formation.saved_front_to_rear_ids = [first, second, third, fourth]
return formation
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("M22 Readiness Controller: %s" % message)