extends SceneTree ## Smoke test for the player character scene and its spawn behavior. ## ## Run with: ## godot --headless --path . --script res://scripts/smoke_test_player.gd ## ## Loads the test level, verifies the player is present, spawned at the ## PlayerSpawn marker, and has the expected CharacterBody3D structure. var _passed := 0 var _failed := 0 func _initialize() -> void: print("SMOKE: starting player smoke test") _run() func _run() -> void: await process_frame print("SMOKE: loading test level scene") # Load the test level scene (which includes the player). var packed: PackedScene = load("res://scenes/worlds/test_level.tscn") var level: Node3D = packed.instantiate() # Order matters: set_current_scene() requires the node's parent to already # be root, so add_child() must come first. This mirrors what a real # change_scene_to_packed() does at runtime. root.add_child(level) current_scene = level print("SMOKE: level instantiated, waiting for ready") await level.ready print("SMOKE: level ready") # 1. Verify the player node exists in the scene tree. var player: Node = level.get_node("Player") _check("Player node exists in test level", player != null) _check("Player is a CharacterBody3D", player is CharacterBody3D) # 2. Verify the player has the expected child structure. var collision: Node = player.get_node("CollisionShape3D") _check("Player has CollisionShape3D", collision != null) _check("CollisionShape3D has a shape", collision is CollisionShape3D and (collision as CollisionShape3D).shape != null) var mesh: Node = player.get_node("CapsuleMesh") _check("Player has CapsuleMesh", mesh != null) _check("CapsuleMesh has a mesh", mesh is MeshInstance3D and (mesh as MeshInstance3D).mesh != null) # 3. Verify the player spawned at the PlayerSpawn marker position. var spawn_marker: Marker3D = level.get_node("PlayerSpawn") _check("PlayerSpawn marker exists", spawn_marker != null) # The player's _ready() should have moved it to the spawn marker's # global position. Since both are direct children of the level root # (and the level root is at the origin), their global positions equal # their local positions. var expected_pos: Vector3 = spawn_marker.global_position _check("Player spawned at PlayerSpawn position", player.global_position == expected_pos) # 4. Verify the player script class_name is correct and has the # movement constants defined. var script: GDScript = player.get_script() as GDScript _check("Player has a script attached", script != null) var constants: Dictionary = script.get_script_constant_map() _check("Player has WALK_SPEED constant", constants.has("WALK_SPEED")) _check("Player has GRAVITY constant", constants.has("GRAVITY")) _check("Player has JUMP_VELOCITY constant", constants.has("JUMP_VELOCITY")) print("\n=== SMOKE RESULT: %d/%d passed ===" % [_passed, _passed + _failed]) quit(0 if _failed == 0 else 1) func _check(description: String, condition: bool) -> void: if condition: print(" PASS: ", description) _passed += 1 else: printerr(" FAIL: ", description) _failed += 1