| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- """
- Tests for the Keyboard Shortcuts UI component (Story 7.13).
- """
- import pytest
- from pathlib import Path
- from PyQt6.QtWidgets import QApplication
- from PyQt6.QtGui import QKeySequence
- from src.ui.shortcuts import (
- StandardAction,
- DEFAULT_SHORTCUTS,
- ACTION_NAMES,
- ShortcutEntry,
- ShortcutsManager,
- ShortcutsModel,
- get_shortcuts_manager,
- )
- @pytest.fixture
- def app(qtbot):
- """Create QApplication for tests."""
- return QApplication.instance() or QApplication([])
- @pytest.fixture
- def clean_manager():
- """Create a fresh ShortcutsManager for testing."""
- import src.ui.shortcuts as sc
- sc._shortcuts_manager_instance = None
- manager = ShortcutsManager()
- return manager
- class TestStandardAction:
- """Tests for StandardAction enum."""
- def test_action_values(self):
- """Test StandardAction enum values."""
- assert StandardAction.OPEN_FILE.value == "open_file"
- assert StandardAction.SAVE_FILE.value == "save_file"
- assert StandardAction.START_TRANSLATION.value == "start_translation"
- class TestDefaultShortcuts:
- """Tests for default shortcuts."""
- def test_all_actions_have_defaults(self):
- """Test that all standard actions have default shortcuts."""
- for action in StandardAction:
- assert action in DEFAULT_SHORTCUTS
- assert DEFAULT_SHORTCUTS[action]
- def test_all_actions_have_names(self):
- """Test that all standard actions have display names."""
- for action in StandardAction:
- assert action in ACTION_NAMES
- assert ACTION_NAMES[action]
- def test_common_shortcuts(self):
- """Test common shortcut defaults."""
- assert DEFAULT_SHORTCUTS[StandardAction.OPEN_FILE] == "Ctrl+O"
- assert DEFAULT_SHORTCUTS[StandardAction.SAVE_FILE] == "Ctrl+S"
- assert DEFAULT_SHORTCUTS[StandardAction.START_TRANSLATION] == "F5"
- assert DEFAULT_SHORTCUTS[StandardAction.ABOUT] == "Ctrl+F1"
- class TestShortcutEntry:
- """Tests for ShortcutEntry dataclass."""
- def test_entry_creation(self):
- """Test creating a shortcut entry."""
- entry = ShortcutEntry(
- action=StandardAction.OPEN_FILE,
- key_sequence="Ctrl+O",
- default_key_sequence="Ctrl+O",
- name=ACTION_NAMES[StandardAction.OPEN_FILE],
- category="文件"
- )
- assert entry.action == StandardAction.OPEN_FILE
- assert entry.key_sequence == "Ctrl+O"
- assert entry.default_key_sequence == "Ctrl+O"
- def test_is_modified_false(self):
- """Test is_modified when not modified."""
- entry = ShortcutEntry(
- action=StandardAction.OPEN_FILE,
- key_sequence="Ctrl+O",
- default_key_sequence="Ctrl+O",
- name="Open File",
- category="File"
- )
- assert entry.is_modified is False
- def test_is_modified_true(self):
- """Test is_modified when modified."""
- entry = ShortcutEntry(
- action=StandardAction.OPEN_FILE,
- key_sequence="Ctrl+Shift+O",
- default_key_sequence="Ctrl+O",
- name="Open File",
- category="File"
- )
- assert entry.is_modified is True
- class TestShortcutsManager:
- """Tests for ShortcutsManager."""
- def test_initialization(self, clean_manager):
- """Test manager initialization."""
- assert isinstance(clean_manager, ShortcutsManager)
- def test_get_shortcut(self, clean_manager):
- """Test getting shortcut for an action."""
- shortcut = clean_manager.get_shortcut(StandardAction.OPEN_FILE)
- assert isinstance(shortcut, QKeySequence)
- assert shortcut.toString() == "Ctrl+O"
- def test_get_all_shortcuts(self, clean_manager):
- """Test all actions have shortcuts."""
- for action in StandardAction:
- shortcut = clean_manager.get_shortcut(action)
- assert isinstance(shortcut, QKeySequence)
- def test_set_shortcut(self, clean_manager):
- """Test setting a shortcut."""
- result = clean_manager.set_shortcut(StandardAction.OPEN_FILE, "Ctrl+Shift+O")
- assert result is True
- shortcut = clean_manager.get_shortcut(StandardAction.OPEN_FILE)
- assert shortcut.toString() == "Ctrl+Shift+O"
- def test_set_shortcut_conflict(self, clean_manager):
- """Test that conflicting shortcuts are rejected."""
- # Try to set OPEN_FILE to the same as SAVE_FILE
- result = clean_manager.set_shortcut(StandardAction.OPEN_FILE, "Ctrl+S")
- assert result is False
- def test_reset_action(self, clean_manager):
- """Test resetting a single action to default."""
- # First change it
- clean_manager.set_shortcut(StandardAction.OPEN_FILE, "Ctrl+Shift+O")
- # Reset to default
- clean_manager.reset_action(StandardAction.OPEN_FILE)
- shortcut = clean_manager.get_shortcut(StandardAction.OPEN_FILE)
- assert shortcut.toString() == DEFAULT_SHORTCUTS[StandardAction.OPEN_FILE]
- def test_reset_to_defaults(self, clean_manager):
- """Test resetting all shortcuts to defaults."""
- # Change some shortcuts
- clean_manager.set_shortcut(StandardAction.OPEN_FILE, "Ctrl+Shift+O")
- clean_manager.set_shortcut(StandardAction.SAVE_FILE, "Ctrl+Shift+S")
- # Reset all
- clean_manager.reset_to_defaults()
- assert clean_manager.get_shortcut(StandardAction.OPEN_FILE).toString() == "Ctrl+O"
- assert clean_manager.get_shortcut(StandardAction.SAVE_FILE).toString() == "Ctrl+S"
- def test_get_all_entries(self, clean_manager):
- """Test getting all shortcut entries."""
- entries = clean_manager.get_all_entries()
- assert len(entries) == len(StandardAction)
- for entry in entries:
- assert isinstance(entry, ShortcutEntry)
- assert isinstance(entry.action, StandardAction)
- assert entry.name
- assert entry.category
- assert entry.key_sequence
- assert entry.default_key_sequence
- def test_create_action(self, app, clean_manager):
- """Test creating a QAction with shortcut."""
- callback_called = []
- def callback():
- callback_called.append(True)
- action = clean_manager.create_action(
- StandardAction.OPEN_FILE,
- parent=None,
- callback=callback
- )
- assert action is not None
- assert action.text() == ACTION_NAMES[StandardAction.OPEN_FILE]
- assert action.shortcut() == clean_manager.get_shortcut(StandardAction.OPEN_FILE)
- def test_register_action(self, app, clean_manager):
- """Test registering an existing QAction."""
- from PyQt6.QtWidgets import QAction
- qaction = QAction("Test", None)
- clean_manager.register_action(StandardAction.OPEN_FILE, qaction)
- assert qaction.shortcut() == clean_manager.get_shortcut(StandardAction.OPEN_FILE)
- def test_register_then_change_shortcut(self, app, clean_manager):
- """Test that registered QAction updates when shortcut changes."""
- from PyQt6.QtWidgets import QAction
- qaction = QAction("Test", None)
- clean_manager.register_action(StandardAction.OPEN_FILE, qaction)
- # Change the shortcut
- clean_manager.set_shortcut(StandardAction.OPEN_FILE, "Ctrl+Shift+O")
- # QAction should be updated
- assert qaction.shortcut().toString() == "Ctrl+Shift+O"
- class TestShortcutsModel:
- """Tests for ShortcutsModel."""
- def test_model_initialization(self, app, clean_manager):
- """Test model initialization."""
- entries = clean_manager.get_all_entries()
- model = ShortcutsModel(entries)
- assert model.rowCount() == len(entries)
- assert model.columnCount() == 3
- def test_data_retrieval(self, app, clean_manager):
- """Test data retrieval from model."""
- entries = clean_manager.get_all_entries()
- model = ShortcutsModel(entries)
- index = model.index(0, 0) # First row, action column
- data = model.data(index)
- assert data # Should have a name
- index = model.index(0, 1) # First row, shortcut column
- data = model.data(index)
- assert isinstance(data, str)
- def test_header_data(self, app, clean_manager):
- """Test header data."""
- entries = clean_manager.get_all_entries()
- model = ShortcutsModel(entries)
- assert model.headerData(0, Qt.Orientation.Horizontal) == "操作"
- assert model.headerData(1, Qt.Orientation.Horizontal) == "快捷键"
- assert model.headerData(2, Qt.Orientation.Horizontal) == "默认"
- def test_get_entry_at_row(self, app, clean_manager):
- """Test getting entry at specific row."""
- entries = clean_manager.get_all_entries()
- model = ShortcutsModel(entries)
- entry = model.get_entry_at_row(0)
- assert entry is not None
- assert isinstance(entry, ShortcutEntry)
- entry = model.get_entry_at_row(999)
- assert entry is None
- class TestShortcutsSingleton:
- """Tests for the singleton pattern."""
- def test_get_singleton(self):
- """Test getting singleton instance."""
- manager = get_shortcuts_manager()
- assert manager is not None
- assert isinstance(manager, ShortcutsManager)
- def test_singleton_persistence(self):
- """Test that singleton returns same instance."""
- manager1 = get_shortcuts_manager()
- manager2 = get_shortcuts_manager()
- assert manager1 is manager2
|