133 lines
6.3 KiB
GDScript
133 lines
6.3 KiB
GDScript
extends SceneTree
|
|
|
|
const Controller = preload("res://entry/recovery_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 battle := _fixture_battle()
|
|
|
|
var ready: Dictionary = controller.snapshot(company, battle, battle.result, battle.reward_draft, [], "ready", "en")
|
|
expect(ready.ok and ready.page_id == "recovery", "snapshot identifies Recovery")
|
|
expect(ready.company.owned_count == 4 and ready.contract.coin == 51, "snapshot copies Company and Contract facts")
|
|
expect(ready.battle.status == "result" and ready.battle.operation_id == "battle-op-001", "snapshot copies settled Battle identity")
|
|
expect(ready.knockouts.ids == ["r-1"] and ready.knockouts.identities[0].recruit.recruit_id == "r-1", "snapshot copies stable return identity")
|
|
expect(ready.reward.status == "claimed" and ready.reward.completed and not ready.reward.pending, "completed reward permits Recovery")
|
|
expect(not ready.receipt.present and ready.commands.commit_enabled and ready.continuation.target == "market", "uncommitted Recovery exposes Commit and Market target")
|
|
expect(ready.continuation.same_identity and ready.knockouts.returns_next_stage, "Recovery preserves same Recruit identity")
|
|
|
|
ready.knockouts.identities[0].recruit.rendered_name_snapshot.display_name = "changed"
|
|
ready.reward.draft.selected_reward_id = "changed"
|
|
ready.result.outcome = "changed"
|
|
expect(String(company.owned_recruits[0].rendered_name_snapshot.display_name) == "Ari", "Recruit identity is deeply copied")
|
|
expect(String(battle.reward_draft.selected_reward_id) == "reward-1", "reward draft is deeply copied")
|
|
expect(String(battle.result.outcome) == "victory", "result facts are deeply copied")
|
|
|
|
var recovered := battle.duplicate(true)
|
|
recovered.status = "recovered"
|
|
recovered.recovery_receipt = _fixture_recovery_receipt()
|
|
var recovered_company := company.duplicate(true)
|
|
recovered_company.active_contract.recovery_receipts = [_fixture_recovery_receipt()]
|
|
var already: Dictionary = controller.snapshot(recovered_company, recovered, recovered.result, recovered.reward_draft, recovered_company.active_contract.recovery_receipts, "already", "zh_CN")
|
|
expect(already.ok and already.receipt.present and not already.commands.commit_enabled and already.commands.market_enabled, "existing Recovery receipt disables duplicate Commit")
|
|
expect(already.receipt.duplicate_safe and already.receipt.receipt_hash == "recovery-hash-001", "Recovery receipt identity is duplicate-safe")
|
|
|
|
var missing: Dictionary = controller.snapshot({}, battle, battle.result, battle.reward_draft)
|
|
expect(not missing.ok and missing.code == "COMPANY_REQUIRED", "missing Company is rejected")
|
|
var active := battle.duplicate(true)
|
|
active.status = "active"
|
|
var unsettled: Dictionary = controller.snapshot(company, active, active.result, active.reward_draft)
|
|
expect(not unsettled.ok and unsettled.code == "RECOVERY_RESULT_REQUIRED", "unsettled Battle is rejected")
|
|
var open_draft: Dictionary = battle.reward_draft.duplicate(true)
|
|
open_draft.status = "open"
|
|
var blocked: Dictionary = controller.snapshot(company, battle, battle.result, open_draft)
|
|
expect(not blocked.ok and blocked.code == "RECOVERY_REWARD_REQUIRED", "open reward draft blocks Recovery")
|
|
var unknown := battle.duplicate(true)
|
|
unknown.result = battle.result.duplicate(true)
|
|
unknown.result.knocked_out_ids = ["missing"]
|
|
unknown.knocked_out_ids = ["missing"]
|
|
var unknown_result: Dictionary = controller.snapshot(company, unknown, unknown.result, unknown.reward_draft)
|
|
expect(not unknown_result.ok and unknown_result.code == "RECOVERY_RECRUIT_UNKNOWN", "unknown return identity is rejected")
|
|
var duplicate := company.duplicate(true)
|
|
duplicate.active_contract.recovery_receipts = [_fixture_recovery_receipt(), _fixture_recovery_receipt()]
|
|
var duplicate_result: Dictionary = controller.snapshot(duplicate, battle, battle.result, battle.reward_draft, duplicate.active_contract.recovery_receipts)
|
|
expect(not duplicate_result.ok and duplicate_result.code == "RECOVERY_RECEIPT_DUPLICATE", "duplicate Recovery receipt is rejected")
|
|
|
|
if failures.is_empty():
|
|
print("ABG_M30_RECOVERY_CONTROLLER_OK company=4 settled=result reward=claimed knockout=r-1 receipt=none,existing commit=true,false market=true identity=same duplicate_safe=true copies=true")
|
|
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", "rendered_name_snapshot": {"display_name": "Ari"}},
|
|
{"recruit_id": "r-2", "rendered_name_snapshot": {"display_name": "Bram"}},
|
|
{"recruit_id": "r-3", "rendered_name_snapshot": {"display_name": "Cera"}},
|
|
{"recruit_id": "r-4", "rendered_name_snapshot": {"display_name": "Dain"}},
|
|
],
|
|
"active_contract": {
|
|
"contract_id": "CTR-R1-01",
|
|
"run_id": "run-001",
|
|
"status": "result",
|
|
"coin": 51,
|
|
"line_capacity": 4,
|
|
"contract_hash": "contract-hash-001",
|
|
"recovery_receipts": [],
|
|
},
|
|
}
|
|
|
|
|
|
func _fixture_battle() -> Dictionary:
|
|
return {
|
|
"status": "result",
|
|
"operation_id": "battle-op-001",
|
|
"battle_hash": "battle-hash-001",
|
|
"snapshot_id": "snapshot-001",
|
|
"snapshot_hash": "snapshot-hash-001",
|
|
"front_to_rear_ids": ["r-1", "r-2", "r-3", "r-4"],
|
|
"enemy_ids": ["enemy-1", "enemy-2", "enemy-3"],
|
|
"knocked_out_ids": ["r-1"],
|
|
"result": {
|
|
"outcome": "victory",
|
|
"reward_coin": 27,
|
|
"xp_award": 48,
|
|
"coin_before": 24,
|
|
"coin_after": 51,
|
|
"knocked_out_ids": ["r-1"],
|
|
"result_hash": "result-hash-001",
|
|
},
|
|
"reward_draft": {
|
|
"draft_id": "draft-001",
|
|
"status": "claimed",
|
|
"selected_reward_id": "reward-1",
|
|
"options": [{"reward_id": "reward-1", "kind": "equipment"}],
|
|
},
|
|
"settlement_receipt": _fixture_settlement_receipt(),
|
|
}
|
|
|
|
|
|
func _fixture_settlement_receipt() -> Dictionary:
|
|
return {"operation_id": "battle-op-001", "battle_operation_id": "battle-op-001", "receipt_hash": "settlement-hash-001"}
|
|
|
|
|
|
func _fixture_recovery_receipt() -> Dictionary:
|
|
return {"operation_id": "recovery-op-001", "battle_operation_id": "battle-op-001", "receipt_hash": "recovery-hash-001", "recruited_ids": ["r-1"], "next_stage_ready": true}
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("M30 Recovery Controller: %s" % message)
|