extends "res://addons/gut/test.gd" const SCENE := "res://scenes/flow/GameFlow.tscn" const ContentDB = preload("res://scripts/content/content_db.gd") const FakeTransport = preload("res://tests/doubles/fake_transport.gd") const DmResponse = preload("res://scripts/net/dm_response.gd") func _flow() -> Node: # Inject fakes BEFORE _ready (add_child): a real world + a network-free service, # so the shell's initial narrate never touches HTTP. var node = load(SCENE).instantiate() var world = ContentDB.new() world.load_from(ContentDB.default_content_root()) node.world = world node.origin = ContentDB.load_json(ContentDB.origin_path("deserter")) var transport = FakeTransport.new() transport.set_response(DmResponse.ok(200, {"prose": "Rain on the cobbles."})) node.service = DmService.new(transport, FallbackLibrary.new()) add_child_autofree(node) return node func _creation() -> Dictionary: return { "name": "Dagnet", "race_id": "human", "calling_id": "sellsword", "seed": 8675309, "spend": {}, "skills": ["athletics", "endurance"], "bonus_skill": "perception", } func test_boots_into_the_title(): var flow := _flow() assert_true(flow._current is TitleScreen, "GameFlow opens on the title") func test_new_game_shows_creation(): var flow := _flow() flow._current.emit_signal("menu_activated", &"new_game") assert_true(flow._current is CharacterCreation, "new game routes to creation") func test_confirming_creation_reaches_the_shell_as_the_created_character(): var flow := _flow() flow._current.emit_signal("menu_activated", &"new_game") flow._current.emit_signal("creation_confirmed", _creation()) assert_true(flow._current is MainWindowShell, "creation routes to the shell") assert_eq(flow._current._log.player.name, "Dagnet", "the CREATED character flowed through — not a seed, not a swap alone") func _assert_stays_on_creation(bad: Dictionary, why: String) -> void: var flow := _flow() flow._current.emit_signal("menu_activated", &"new_game") # Drive the REAL signal with an invalid dict. The CTA gates this out via the UI, # but §2 forbids GameFlow trusting the caller and §13 forbids surfacing an error. flow._current.emit_signal("creation_confirmed", bad) assert_false(flow._current is MainWindowShell, "a failed construct never reaches the shell (§13): %s" % why) assert_true(flow._current is CharacterCreation, "the player stays on the valid creation screen: %s" % why) func test_construct_failure_empty_name_stays_on_creation(): var bad := _creation() bad["name"] = "" # empty name fails NewGame.validate _assert_stays_on_creation(bad, "empty name") func test_construct_failure_bad_calling_stays_on_creation(): var bad := _creation() bad["calling_id"] = "bard" # NPC-only / not a real calling — fails NewGame.validate _assert_stays_on_creation(bad, "unknown calling")