From 68a554f1f027c869a37002532abe7949eb4cdcd9 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Thu, 12 Feb 2026 02:01:54 +0100 Subject: [PATCH] =?UTF-8?q?fix(client):=20address=20PR=20#13=20review=20?= =?UTF-8?q?=E2=80=94=20LOS=20tests,=20reset=20consistency,=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use reset_test_state() consistently in test_snapshot_parsing.gd (Tyre critical) - Fix misleading wall comment: (12,9) → (12,10) (Hoshe warning) - Add coordinate space documentation to _test_snapshot() (Tyre warning) - Add 4 Bresenham LOS unit tests: clear, blocked, diagonal, self (Hoshe warning) - Check OS.is_process_running() in connection loop (Hoshe warning) - Verify NPC position in corner reveal test (Hoshe suggestion) Co-Authored-By: Claude Opus 4.6 --- client/scripts/autoloads/sim_bridge.gd | 6 +++++- client/tests/test_snapshot_parsing.gd | 22 ++++++++++++++++++---- client/tests/test_sprint2_proof.gd | 5 +++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/client/scripts/autoloads/sim_bridge.gd b/client/scripts/autoloads/sim_bridge.gd index 604ab2514..98aad66b8 100644 --- a/client/scripts/autoloads/sim_bridge.gd +++ b/client/scripts/autoloads/sim_bridge.gd @@ -250,6 +250,10 @@ static func _action_enum_to_wire(action: int) -> String: # Dynamic test snapshot — processes queued inputs to move player, generates # visibility based on current position. Matches Protocol.decode_snapshot() format. +# NOTE: Test coordinate space (player at 10,10; NPC at 12,9; wall at 12,10) +# is intentionally decoupled from the E2E proof room (player at 16,16; NPC at +# 16,13; wall at 16,14). This ensures standalone tests don't depend on server +# map layout and can exercise the rendering pipeline independently. func _test_snapshot() -> Dictionary: _test_tick += 1 @@ -276,7 +280,7 @@ func _test_snapshot() -> Dictionary: "visibility": "Forward", }] - # NPC at (12, 9) — visible if within range and not blocked by wall at (12, 9) + # NPC at (12, 9) — visible if within range and not blocked by wall at (12, 10) var npc_pos := Vector2i(12, 9) var npc_dist := absi(px - npc_pos.x) + absi(py - npc_pos.y) if npc_dist <= 4 and _test_has_los(Vector2i(px, py), npc_pos): diff --git a/client/tests/test_snapshot_parsing.gd b/client/tests/test_snapshot_parsing.gd index 7c15c7657..3fd78c17e 100644 --- a/client/tests/test_snapshot_parsing.gd +++ b/client/tests/test_snapshot_parsing.gd @@ -51,11 +51,25 @@ func test_missing_fields_partial_update() -> void: assert_that(GameState.player_position).is_equal(Vector2(10, 15)) assert_that(GameState.current_tick).is_equal(2) +func test_sim_bridge_los_clear_path() -> void: + # No wall between (10,10) and (10,8) — clear LOS + assert_that(SimBridge._test_has_los(Vector2i(10, 10), Vector2i(10, 8))).is_true() + +func test_sim_bridge_los_blocked_by_wall() -> void: + # Wall at (12,10) blocks LOS from (10,10) to (12,9) via east path + # Direct line from (10,10) → (12,9) passes through (11,10) then (12,10) — wall + assert_that(SimBridge._test_has_los(Vector2i(10, 10), Vector2i(14, 10))).is_false() + +func test_sim_bridge_los_diagonal() -> void: + # Diagonal LOS from (10,10) to (11,9) — no wall in path + assert_that(SimBridge._test_has_los(Vector2i(10, 10), Vector2i(11, 9))).is_true() + +func test_sim_bridge_los_same_position() -> void: + # LOS to self is always true + assert_that(SimBridge._test_has_los(Vector2i(10, 10), Vector2i(10, 10))).is_true() + func test_sim_bridge_test_snapshot_deterministic() -> void: - SimBridge._test_tick = 0 - SimBridge._test_player_pos = Vector2i(10, 10) - SimBridge._test_facing = "North" - SimBridge._test_input_queue.clear() + SimBridge.reset_test_state() var snap1 = SimBridge._test_snapshot() var snap2 = SimBridge._test_snapshot() diff --git a/client/tests/test_sprint2_proof.gd b/client/tests/test_sprint2_proof.gd index ce35da77c..21a0164d6 100644 --- a/client/tests/test_sprint2_proof.gd +++ b/client/tests/test_sprint2_proof.gd @@ -91,6 +91,9 @@ func _connect_to_server() -> bool: _bridge = LocalBridge.new() var elapsed := 0.0 while elapsed < CONNECT_TIMEOUT: + if _server_pid > 0 and not OS.is_process_running(_server_pid): + push_warning("Server process died during connection") + return false if _bridge.get_status() == StreamPeerTCP.STATUS_NONE: _bridge.connect_to_server("127.0.0.1", _test_port) _bridge.poll() @@ -174,6 +177,8 @@ func test_proof_corner_reveal() -> void: var npc_found := false for entity in snapshot.entities: if entity.kind.variant == "Npc": + assert_float(entity.x).is_equal_approx(16.5, 0.001) + assert_float(entity.y).is_equal_approx(13.5, 0.001) npc_found = true break assert_that(npc_found).is_true()