#!/usr/bin/env python3 import unittest from pathlib import Path from engine import controls class DummyBindings(controls.KeyBindings): def spawn_rat(self): pass def toggle_audio(self): pass def toggle_full_screen(self): pass def start_scrolling(self, direction): pass def stop_scrolling(self): pass def spawn_new_bomb(self): pass def spawn_new_nuclear_bomb(self): pass def spawn_new_mine(self): pass def spawn_new_gas(self): pass def spawn_gas(self, parent_id=None): pass def toggle_pause(self): pass def reset_game(self): pass def quit_game(self): pass def menu_up(self): pass def menu_down(self): pass def menu_left(self): pass def menu_right(self): pass class KeybindingProfileTests(unittest.TestCase): def test_shipped_profiles_expose_all_weapon_actions(self): dummy = DummyBindings() conf_dir = Path(__file__).resolve().parent / "conf" weapon_actions = { "spawn_new_bomb", "spawn_new_nuclear_bomb", "spawn_new_mine", "spawn_new_gas", } for config_path in sorted(conf_dir.glob("keybindings*.json")) + sorted(conf_dir.glob("keybindings*.yaml")): bindings = controls._load_bindings_from_file(config_path) validated = dummy._validate_bindings(bindings, config_path) game_bindings = validated.get("keybinding_game", {}) self.assertTrue(game_bindings, f"missing keybinding_game in {config_path.name}") actions = set(game_bindings.values()) self.assertTrue( weapon_actions.issubset(actions), f"incomplete weapon bindings in {config_path.name}: {sorted(actions)}", ) def test_shipped_profiles_define_level_dialog_bindings(self): dummy = DummyBindings() conf_dir = Path(__file__).resolve().parent / "conf" required_sections = { "keybinding_level_intro", "keybinding_level_clear", "keybinding_defeat", "keybinding_run_complete", } for config_path in sorted(conf_dir.glob("keybindings*.json")) + sorted(conf_dir.glob("keybindings*.yaml")): bindings = controls._load_bindings_from_file(config_path) validated = dummy._validate_bindings(bindings, config_path) for section_name in required_sections: section = validated.get(section_name, {}) self.assertTrue(section, f"missing {section_name} in {config_path.name}") values = set(section.values()) self.assertIn("reset_game", values, f"missing confirm binding in {section_name} for {config_path.name}") self.assertIn("quit_game", values, f"missing quit binding in {section_name} for {config_path.name}") def test_trigger_uses_level_intro_context(self): dummy = DummyBindings() calls = [] dummy.reset_game = lambda: calls.append("reset") dummy.quit_game = lambda: calls.append("quit") dummy.bindings = { "keybinding_level_intro": {"keydown_Return": "reset_game"}, "keybinding_start_menu": {"keydown_Return": "quit_game"}, } dummy.game_status = "start_menu" dummy.menu_screen = "level_intro" dummy.game_end = (False, None) dummy.trigger("keydown_Return") self.assertEqual(calls, ["reset"]) def test_trigger_uses_level_clear_context(self): dummy = DummyBindings() calls = [] dummy.reset_game = lambda: calls.append("reset") dummy.quit_game = lambda: calls.append("quit") dummy.bindings = { "keybinding_level_clear": {"keydown_Return": "reset_game"}, "keybinding_paused": {"keydown_Return": "quit_game"}, } dummy.game_status = "paused" dummy.menu_screen = None dummy.game_end = (True, "level_clear") dummy.trigger("keydown_Return") self.assertEqual(calls, ["reset"]) if __name__ == "__main__": unittest.main()