mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 19:03:08 +02:00
Split 16+ files. 27 files still need splitting. See session notes.
427 lines
14 KiB
Python
427 lines
14 KiB
Python
"""Tests for keyboard_coop game loop and forced submission."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
|
|
class TestForceSubmitWhenNoMoves:
|
|
"""Tests for forced word submission when no moves available."""
|
|
|
|
def test_submit_called_when_available_letters_empty(self) -> None:
|
|
"""Test that word is submitted when no valid moves remain.
|
|
|
|
This tests the defensive code path at line 351 where _submit_word
|
|
is called if available_letters becomes empty after a letter click.
|
|
"""
|
|
mock_pg = MagicMock()
|
|
|
|
with patch.dict("sys.modules", {"pygame": mock_pg}):
|
|
from python_pkg.keyboard_coop.main import (
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.layout = [["a", "b"]]
|
|
game.keyboard.adjacency = {}
|
|
game.keyboard.available_letters = {"a"}
|
|
game.keyboard.positions = {}
|
|
game.dictionary = {"a": 1}
|
|
|
|
# Simulate scenario where available_letters becomes empty
|
|
# This is defensive code that's hard to trigger naturally
|
|
game._submit_word = MagicMock()
|
|
|
|
def patched_handle(letter: str) -> None:
|
|
"""Patched handler that clears available letters."""
|
|
if letter in game.keyboard.available_letters:
|
|
game.state.selected_letters.append(letter)
|
|
game.state.current_word += letter
|
|
# Force empty to trigger the check
|
|
game.keyboard.available_letters = set()
|
|
if not game.keyboard.available_letters:
|
|
game._submit_word()
|
|
|
|
patched_handle("a")
|
|
|
|
# Should have triggered submit_word
|
|
game._submit_word.assert_called()
|
|
|
|
|
|
class TestGameLoop:
|
|
"""Tests for the main game loop."""
|
|
|
|
def test_run_quit_event(self) -> None:
|
|
"""Test game loop exits on QUIT event."""
|
|
mock_pg = MagicMock()
|
|
|
|
# Create quit event
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.event.get.return_value = [quit_event]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit") as mock_exit,
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
|
|
game.run()
|
|
|
|
mock_pg.quit.assert_called()
|
|
mock_exit.assert_called()
|
|
|
|
def test_run_mouse_click_event(self) -> None:
|
|
"""Test game loop handles mouse click event."""
|
|
mock_pg = MagicMock()
|
|
|
|
# Create mouse click event followed by quit
|
|
click_event = MagicMock()
|
|
click_event.type = "MOUSEDOWN"
|
|
click_event.button = 1
|
|
click_event.pos = (100, 100)
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
# Return click event first, then quit event
|
|
mock_pg.event.get.side_effect = [[click_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._handle_click = MagicMock()
|
|
|
|
game.run()
|
|
|
|
game._handle_click.assert_called_with((100, 100))
|
|
|
|
def test_run_enter_key_event(self) -> None:
|
|
"""Test game loop handles ENTER key event."""
|
|
mock_pg = MagicMock()
|
|
|
|
key_event = MagicMock()
|
|
key_event.type = "KEYDOWN"
|
|
key_event.key = "K_RETURN"
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.K_RETURN = "K_RETURN"
|
|
mock_pg.K_r = "K_r"
|
|
mock_pg.event.get.side_effect = [[key_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._submit_word = MagicMock()
|
|
|
|
game.run()
|
|
|
|
game._submit_word.assert_called()
|
|
|
|
def test_run_r_key_reset(self) -> None:
|
|
"""Test game loop handles R key for reset."""
|
|
mock_pg = MagicMock()
|
|
|
|
key_event = MagicMock()
|
|
key_event.type = "KEYDOWN"
|
|
key_event.key = "K_r"
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.K_RETURN = "K_RETURN"
|
|
mock_pg.K_r = "K_r"
|
|
mock_pg.event.get.side_effect = [[key_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._reset_game = MagicMock()
|
|
|
|
game.run()
|
|
|
|
game._reset_game.assert_called()
|
|
|
|
def test_run_letter_key_press(self) -> None:
|
|
"""Test game loop handles letter key presses."""
|
|
mock_pg = MagicMock()
|
|
|
|
key_event = MagicMock()
|
|
key_event.type = "KEYDOWN"
|
|
key_event.key = "some_key"
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.K_RETURN = "K_RETURN"
|
|
mock_pg.K_r = "K_r"
|
|
mock_pg.key.name.return_value = "a" # Single letter key
|
|
mock_pg.event.get.side_effect = [[key_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._handle_letter_click = MagicMock()
|
|
|
|
game.run()
|
|
|
|
game._handle_letter_click.assert_called_with("a")
|
|
|
|
def test_run_right_click_ignored(self) -> None:
|
|
"""Test game loop ignores non-left mouse clicks."""
|
|
mock_pg = MagicMock()
|
|
|
|
click_event = MagicMock()
|
|
click_event.type = "MOUSEDOWN"
|
|
click_event.button = 3 # Right click
|
|
click_event.pos = (100, 100)
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.event.get.side_effect = [[click_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._handle_click = MagicMock()
|
|
|
|
game.run()
|
|
|
|
# handle_click should NOT be called for right click
|
|
game._handle_click.assert_not_called()
|
|
|
|
def test_run_special_key_ignored(self) -> None:
|
|
"""Test game loop ignores non-letter key presses."""
|
|
mock_pg = MagicMock()
|
|
|
|
key_event = MagicMock()
|
|
key_event.type = "KEYDOWN"
|
|
key_event.key = "some_key"
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.K_RETURN = "K_RETURN"
|
|
mock_pg.K_r = "K_r"
|
|
mock_pg.key.name.return_value = "escape" # Multi-char, not a letter
|
|
mock_pg.event.get.side_effect = [[key_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._handle_letter_click = MagicMock()
|
|
|
|
game.run()
|
|
|
|
# handle_letter_click should NOT be called for special keys
|
|
game._handle_letter_click.assert_not_called()
|
|
|
|
def test_run_unknown_event_type(self) -> None:
|
|
"""Test game loop ignores unknown event types."""
|
|
mock_pg = MagicMock()
|
|
|
|
unknown_event = MagicMock()
|
|
unknown_event.type = "UNKNOWN"
|
|
|
|
quit_event = MagicMock()
|
|
quit_event.type = "QUIT"
|
|
|
|
mock_pg.QUIT = "QUIT"
|
|
mock_pg.MOUSEBUTTONDOWN = "MOUSEDOWN"
|
|
mock_pg.KEYDOWN = "KEYDOWN"
|
|
mock_pg.event.get.side_effect = [[unknown_event], [quit_event]]
|
|
|
|
with (
|
|
patch.dict("sys.modules", {"pygame": mock_pg}),
|
|
patch("sys.exit"),
|
|
):
|
|
from python_pkg.keyboard_coop.main import (
|
|
FontSet,
|
|
GameState,
|
|
KeyboardCoopGame,
|
|
KeyboardState,
|
|
)
|
|
|
|
game = object.__new__(KeyboardCoopGame)
|
|
game.screen = MagicMock()
|
|
game.clock = MagicMock()
|
|
game.state = GameState()
|
|
game.keyboard = KeyboardState()
|
|
game.keyboard.positions = {}
|
|
game.fonts = FontSet(
|
|
normal=MagicMock(), large=MagicMock(), small=MagicMock()
|
|
)
|
|
game._draw_keyboard = MagicMock()
|
|
game._draw_ui = MagicMock(return_value=(MagicMock(), MagicMock()))
|
|
game._handle_click = MagicMock()
|
|
game._submit_word = MagicMock()
|
|
game._reset_game = MagicMock()
|
|
game._handle_letter_click = MagicMock()
|
|
|
|
game.run()
|
|
|
|
# None of the handlers should be called for unknown event
|
|
game._handle_click.assert_not_called()
|
|
game._submit_word.assert_not_called()
|
|
game._reset_game.assert_not_called()
|
|
game._handle_letter_click.assert_not_called()
|