Files
settled-reach/client/tests/test_free_camera.gd
T
jpmschweitzerandClaude Opus 4.6 e002f811f0 fix(client): free camera review fixes — action toggle, zoom reset, discrete guard, tests (#898)
- Replace raw KEY_F4 check with Input.is_action_just_pressed("free_camera") to
  consume the registered project action (matches F3/F12 dev toggle pattern)
- Reset camera.zoom to Vector2.ONE when toggling free camera off so zoom does
  not bleed into normal gameplay
- Add free_camera_mode guard to InputMapper._unhandled_input() so discrete
  actions (INTERACT, stance, pause) are suppressed alongside movement
- Add client/tests/test_free_camera.gd: flag default, movement suppression,
  discrete action suppression, zoom constant contracts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-02 18:03:06 +02:00

89 lines
3.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Free camera mode tests (#898).
## Covers GameState flag default, InputMapper suppression, and zoom clamping.
class_name TestFreeCamera
extends GdUnitTestSuite
func before_test() -> void:
GameState.free_camera_mode = false
func after_test() -> void:
GameState.free_camera_mode = false
# -- GameState.free_camera_mode default ----------------------------------------
func test_free_camera_mode_starts_false() -> void:
## #898: Free camera is off by default — normal gameplay on startup.
assert_bool(GameState.free_camera_mode).override_failure_message(
"GameState.free_camera_mode must default to false"
).is_false()
# -- InputMapper suppression ---------------------------------------------------
func test_input_mapper_suppresses_movement_in_free_camera_mode() -> void:
## #898: While free camera is active, InputMapper._process() returns early so
## no movement actions enter the queue.
GameState.free_camera_mode = true
var before := InputMapper.input_queue.size()
InputMapper._process(0.016)
var after := InputMapper.input_queue.size()
assert_int(after).override_failure_message(
"InputMapper must not enqueue movement while free_camera_mode is true"
).is_equal(before)
InputMapper.input_queue.clear()
func test_input_mapper_suppresses_discrete_actions_in_free_camera_mode() -> void:
## #898: _unhandled_input returns early in free camera — INTERACT and stance
## actions must not be queued.
GameState.free_camera_mode = true
var before := InputMapper.input_queue.size()
var fake_event := InputEventAction.new()
fake_event.action = "interact"
fake_event.pressed = true
InputMapper._unhandled_input(fake_event)
assert_int(InputMapper.input_queue.size()).override_failure_message(
"InputMapper must not enqueue discrete actions while free_camera_mode is true"
).is_equal(before)
InputMapper.input_queue.clear()
func test_input_mapper_resumes_after_free_camera_off() -> void:
## Turning free camera off lifts the suppression — _process runs normally again.
GameState.free_camera_mode = true
GameState.free_camera_mode = false
## _process should no longer return early (queue may or may not grow depending
## on held keys, but no crash and guard is lifted).
InputMapper._process(0.016)
assert_bool(true).is_true() # no crash = pass
InputMapper.input_queue.clear()
# -- Zoom clamp contract -------------------------------------------------------
func test_zoom_min_constant_is_0_5() -> void:
## #898: Minimum zoom keeps the world recognisable.
var main_script = load("res://scripts/main.gd")
assert_float(main_script.FREE_CAMERA_ZOOM_MIN).override_failure_message(
"FREE_CAMERA_ZOOM_MIN must be 0.5"
).is_equal_approx(0.5, 0.001)
func test_zoom_max_constant_is_8() -> void:
## #898: Maximum zoom must not exceed 8× per spec.
var main_script = load("res://scripts/main.gd")
assert_float(main_script.FREE_CAMERA_ZOOM_MAX).override_failure_message(
"FREE_CAMERA_ZOOM_MAX must be 8.0"
).is_equal_approx(8.0, 0.001)
func test_zoom_step_is_positive() -> void:
## Zoom step must be > 0 so scroll wheel does something.
var main_script = load("res://scripts/main.gd")
assert_float(main_script.FREE_CAMERA_ZOOM_STEP).override_failure_message(
"FREE_CAMERA_ZOOM_STEP must be positive"
).is_greater(0.0)