"""Tests for game logic.""" import pytest from src.server.game_logic import GameLogic from src.shared.models import Position, Snake from src.shared.constants import GRID_WIDTH, GRID_HEIGHT, RIGHT, LEFT, UP, DOWN class TestGameLogic: """Test suite for GameLogic class.""" def test_create_snake(self) -> None: """Test snake creation.""" logic = GameLogic() snake = logic.create_snake("player1") assert snake.player_id == "player1" assert len(snake.body) == 3 assert snake.alive is True assert snake.score == 0 assert snake.direction == RIGHT def test_spawn_food(self) -> None: """Test food spawning.""" logic = GameLogic() food = logic.spawn_food() assert 0 <= food.position.x < GRID_WIDTH assert 0 <= food.position.y < GRID_HEIGHT def test_update_snake_direction(self) -> None: """Test updating snake direction.""" logic = GameLogic() snake = logic.create_snake("player1") logic.state.snakes.append(snake) # Valid direction change logic.update_snake_direction("player1", UP) assert snake.direction == UP # Invalid 180-degree turn (should be ignored) logic.update_snake_direction("player1", DOWN) assert snake.direction == UP # Should remain UP def test_move_snakes(self) -> None: """Test snake movement.""" logic = GameLogic() snake = Snake(player_id="player1", body=[ Position(5, 5), Position(4, 5), Position(3, 5), ], direction=RIGHT) logic.state.snakes.append(snake) initial_length = len(snake.body) logic.move_snakes() # Snake should have moved one cell to the right assert snake.get_head().x == 6 assert snake.get_head().y == 5 assert len(snake.body) == initial_length def test_collision_with_wall(self) -> None: """Test collision detection with walls.""" logic = GameLogic() # Snake at left wall snake = Snake(player_id="player1", body=[ Position(0, 5), Position(1, 5), Position(2, 5), ], direction=LEFT) logic.state.snakes.append(snake) logic.move_snakes() logic.check_collisions() assert snake.alive is False def test_collision_with_self(self) -> None: """Test collision detection with self.""" logic = GameLogic() # Create a snake that will hit itself snake = Snake(player_id="player1", body=[ Position(5, 5), Position(5, 6), Position(6, 6), Position(6, 5), ], direction=DOWN) logic.state.snakes.append(snake) logic.move_snakes() logic.check_collisions() assert snake.alive is False def test_food_eating(self) -> None: """Test snake eating food and growing.""" logic = GameLogic() snake = Snake(player_id="player1", body=[ Position(5, 5), Position(4, 5), Position(3, 5), ], direction=RIGHT) logic.state.snakes.append(snake) # Place food in front of snake from src.shared.models import Food food = Food(position=Position(6, 5)) logic.state.food.append(food) initial_length = len(snake.body) initial_score = snake.score logic.move_snakes() # Snake should have grown and scored assert len(snake.body) == initial_length + 1 assert snake.score == initial_score + 10 assert food not in logic.state.food def test_is_game_over(self) -> None: """Test game over detection.""" logic = GameLogic() # No game over with multiple alive snakes snake1 = Snake(player_id="player1", alive=True) snake2 = Snake(player_id="player2", alive=True) logic.state.snakes = [snake1, snake2] assert logic.is_game_over() is False # Game over when only one snake alive snake2.alive = False assert logic.is_game_over() is True def test_get_winner(self) -> None: """Test winner determination.""" logic = GameLogic() snake1 = Snake(player_id="player1", alive=True) snake2 = Snake(player_id="player2", alive=False) logic.state.snakes = [snake1, snake2] winner = logic.get_winner() assert winner == "player1"