extends GutTest ## Unit tests for online game helper functions in Main.gd ## Tests the logic for determining if local player can act # Mock classes for testing class MockTurnManager: var current_player_index: int = 0 var turn_number: int = 1 var current_phase: int = 0 class MockGameState: var turn_manager: MockTurnManager func _init(): turn_manager = MockTurnManager.new() # Simulated Main.gd helper functions for testing # These mirror the actual functions in Main.gd var is_online_game: bool = false var local_player_index: int = 0 var mock_game_state: MockGameState = null func before_each(): is_online_game = false local_player_index = 0 mock_game_state = MockGameState.new() # Helper function that mirrors Main.gd._is_local_player_turn() func _is_local_player_turn() -> bool: if not is_online_game: return true if not mock_game_state: return true return mock_game_state.turn_manager.current_player_index == local_player_index # Helper function that mirrors Main.gd._can_perform_local_action() func _can_perform_local_action() -> bool: if not is_online_game: return true return _is_local_player_turn() # ======= _is_local_player_turn() Tests ======= func test_is_local_player_turn_returns_true_when_not_online(): is_online_game = false mock_game_state.turn_manager.current_player_index = 1 local_player_index = 0 assert_true(_is_local_player_turn(), "Should return true when not in online game") func test_is_local_player_turn_returns_true_when_no_game_state(): is_online_game = true mock_game_state = null assert_true(_is_local_player_turn(), "Should return true when game_state is null") func test_is_local_player_turn_returns_true_when_local_index_matches(): is_online_game = true local_player_index = 0 mock_game_state.turn_manager.current_player_index = 0 assert_true(_is_local_player_turn(), "Should return true when it's local player's turn") func test_is_local_player_turn_returns_false_when_opponent_turn(): is_online_game = true local_player_index = 0 mock_game_state.turn_manager.current_player_index = 1 assert_false(_is_local_player_turn(), "Should return false when it's opponent's turn") func test_is_local_player_turn_player_1_perspective(): is_online_game = true local_player_index = 1 mock_game_state.turn_manager.current_player_index = 1 assert_true(_is_local_player_turn(), "Player 1 should be able to act on their turn") func test_is_local_player_turn_player_1_opponent_turn(): is_online_game = true local_player_index = 1 mock_game_state.turn_manager.current_player_index = 0 assert_false(_is_local_player_turn(), "Player 1 should not act on opponent's turn") # ======= _can_perform_local_action() Tests ======= func test_can_perform_local_action_delegates_to_is_local_player_turn_online(): is_online_game = true local_player_index = 0 mock_game_state.turn_manager.current_player_index = 0 assert_true(_can_perform_local_action()) mock_game_state.turn_manager.current_player_index = 1 assert_false(_can_perform_local_action()) func test_can_perform_local_action_always_true_offline(): is_online_game = false local_player_index = 0 mock_game_state.turn_manager.current_player_index = 1 assert_true(_can_perform_local_action(), "Should always be able to act in offline game") # ======= Player Index Validation Tests ======= func test_valid_player_index_0(): var player_index = 0 assert_true(player_index >= 0 and player_index <= 1, "Player index 0 should be valid") func test_valid_player_index_1(): var player_index = 1 assert_true(player_index >= 0 and player_index <= 1, "Player index 1 should be valid") func test_invalid_player_index_negative(): var player_index = -1 assert_false(player_index >= 0 and player_index <= 1, "Negative player index should be invalid") func test_invalid_player_index_too_high(): var player_index = 2 assert_false(player_index >= 0 and player_index <= 1, "Player index > 1 should be invalid") # ======= Turn Timer Format Tests ======= func test_timer_format_full_minutes(): var seconds = 120 var minutes = seconds / 60 var secs = seconds % 60 var formatted = "%d:%02d" % [minutes, secs] assert_eq(formatted, "2:00") func test_timer_format_partial_minutes(): var seconds = 90 var minutes = seconds / 60 var secs = seconds % 60 var formatted = "%d:%02d" % [minutes, secs] assert_eq(formatted, "1:30") func test_timer_format_under_minute(): var seconds = 45 var minutes = seconds / 60 var secs = seconds % 60 var formatted = "%d:%02d" % [minutes, secs] assert_eq(formatted, "0:45") func test_timer_format_single_digit_seconds(): var seconds = 65 var minutes = seconds / 60 var secs = seconds % 60 var formatted = "%d:%02d" % [minutes, secs] assert_eq(formatted, "1:05") func test_timer_format_zero(): var seconds = 0 var minutes = seconds / 60 var secs = seconds % 60 var formatted = "%d:%02d" % [minutes, secs] assert_eq(formatted, "0:00") # ======= Timer Color Thresholds Tests ======= func test_timer_color_threshold_critical(): var seconds = 10 var is_critical = seconds <= 10 assert_true(is_critical, "10 seconds should be critical (red)") func test_timer_color_threshold_warning(): var seconds = 30 var is_warning = seconds > 10 and seconds <= 30 assert_true(is_warning, "30 seconds should be warning (yellow)") func test_timer_color_threshold_normal(): var seconds = 60 var is_normal = seconds > 30 assert_true(is_normal, "60 seconds should be normal (white)") func test_timer_color_threshold_boundary_10(): var seconds = 10 var is_critical = seconds <= 10 assert_true(is_critical, "Exactly 10 should be critical") func test_timer_color_threshold_boundary_11(): var seconds = 11 var is_warning = seconds > 10 and seconds <= 30 assert_true(is_warning, "11 should be warning, not critical") func test_timer_color_threshold_boundary_30(): var seconds = 30 var is_warning = seconds > 10 and seconds <= 30 assert_true(is_warning, "Exactly 30 should be warning") func test_timer_color_threshold_boundary_31(): var seconds = 31 var is_normal = seconds > 30 assert_true(is_normal, "31 should be normal, not warning") # ======= Online Game State Sync Tests ======= func test_game_state_sync_updates_current_player(): var state = { "current_player_index": 1, "current_phase": 2, "turn_number": 3 } mock_game_state.turn_manager.current_player_index = state.get("current_player_index", 0) assert_eq(mock_game_state.turn_manager.current_player_index, 1) func test_game_state_sync_updates_phase(): var state = { "current_player_index": 0, "current_phase": 3, "turn_number": 1 } mock_game_state.turn_manager.current_phase = state.get("current_phase", 0) assert_eq(mock_game_state.turn_manager.current_phase, 3) func test_game_state_sync_updates_turn_number(): var state = { "current_player_index": 0, "current_phase": 0, "turn_number": 5 } mock_game_state.turn_manager.turn_number = state.get("turn_number", 1) assert_eq(mock_game_state.turn_manager.turn_number, 5) func test_game_state_sync_timer_extraction(): var state = { "turn_timer_seconds": 90 } var timer_seconds = state.get("turn_timer_seconds", 120) assert_eq(timer_seconds, 90) func test_game_state_sync_timer_default(): var state = {} var timer_seconds = state.get("turn_timer_seconds", 120) assert_eq(timer_seconds, 120, "Should default to 120 seconds")