226 lines
5.9 KiB
Python
226 lines
5.9 KiB
Python
"""
|
|
Shared pytest fixtures for Fenrir tests.
|
|
|
|
This file contains fixtures and configuration used across all test modules.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, Mock
|
|
|
|
import pytest
|
|
|
|
# Add src directory to Python path for imports
|
|
fenrir_root = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(fenrir_root / "src"))
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_environment():
|
|
"""Create a minimal mock environment for testing.
|
|
|
|
Returns a mock environment dict with required runtime managers mocked.
|
|
This allows testing components without initializing the full Fenrir stack.
|
|
"""
|
|
env = {
|
|
"runtime": {
|
|
"DebugManager": Mock(write_debug_out=Mock()),
|
|
"OutputManager": Mock(
|
|
present_text=Mock(),
|
|
speak_text=Mock(),
|
|
interrupt_output=Mock(),
|
|
),
|
|
"SettingsManager": Mock(
|
|
get_setting=Mock(return_value="default"),
|
|
get_setting_as_int=Mock(return_value=0),
|
|
get_setting_as_float=Mock(return_value=0.0),
|
|
get_setting_as_bool=Mock(return_value=True),
|
|
),
|
|
"InputManager": Mock(
|
|
sendKeys=Mock(),
|
|
handle_device_grab=Mock(),
|
|
),
|
|
"ScreenManager": Mock(update_screen_ignored=Mock()),
|
|
"EventManager": Mock(stop_main_event_loop=Mock()),
|
|
"MemoryManager": Mock(
|
|
add_value_to_first_index=Mock(),
|
|
get_index_list_element=Mock(return_value="test clipboard"),
|
|
is_index_list_empty=Mock(return_value=False),
|
|
),
|
|
"VmenuManager": Mock(
|
|
set_curr_menu=Mock(),
|
|
),
|
|
"CursorManager": Mock(
|
|
set_window_for_application=Mock(),
|
|
clear_window_for_application=Mock(),
|
|
),
|
|
},
|
|
"settings": Mock(),
|
|
"general": {
|
|
"curr_user": "testuser",
|
|
},
|
|
}
|
|
return env
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_config_file(tmp_path):
|
|
"""Create a temporary configuration file for testing.
|
|
|
|
Returns path to a valid test configuration file.
|
|
"""
|
|
config_path = tmp_path / "test_settings.conf"
|
|
config_content = """[sound]
|
|
enabled=True
|
|
driver=gstreamerDriver
|
|
theme=default
|
|
volume=0.7
|
|
|
|
[speech]
|
|
enabled=True
|
|
driver=speechdDriver
|
|
rate=0.5
|
|
pitch=0.5
|
|
volume=1.0
|
|
autoReadIncoming=True
|
|
|
|
[screen]
|
|
driver=vcsaDriver
|
|
encoding=auto
|
|
screenUpdateDelay=0.05
|
|
|
|
[keyboard]
|
|
driver=evdevDriver
|
|
device=ALL
|
|
grabDevices=True
|
|
keyboardLayout=desktop
|
|
|
|
[general]
|
|
debugLevel=2
|
|
debugMode=File
|
|
|
|
[remote]
|
|
enable=True
|
|
driver=unixDriver
|
|
port=22447
|
|
enableSettingsRemote=True
|
|
enableCommandRemote=True
|
|
"""
|
|
config_path.write_text(config_content)
|
|
return config_path
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_socket_path(tmp_path):
|
|
"""Create a temporary Unix socket path for testing.
|
|
|
|
Returns path that can be used for Unix socket testing.
|
|
"""
|
|
return tmp_path / "test_fenrir.sock"
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_clipboard_file(tmp_path):
|
|
"""Create a temporary clipboard file for testing.
|
|
|
|
Returns path to a temporary file for clipboard operations.
|
|
"""
|
|
clipboard_path = tmp_path / "fenrirClipboard"
|
|
clipboard_path.write_text("")
|
|
return clipboard_path
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_screen_data():
|
|
"""Return sample screen data for testing screen-related functionality.
|
|
|
|
Returns dict with screen dimensions and content.
|
|
"""
|
|
return {
|
|
"columns": 80,
|
|
"lines": 24,
|
|
"delta": "Hello World",
|
|
"cursor": {"x": 0, "y": 0},
|
|
"content": "Sample screen content\nSecond line\nThird line",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_remote_commands():
|
|
"""Return sample remote control commands for testing.
|
|
|
|
Returns list of valid remote commands.
|
|
"""
|
|
return [
|
|
"command say Hello World",
|
|
"command interrupt",
|
|
"setting set speech#rate=0.8",
|
|
"setting set speech#pitch=0.6",
|
|
"setting set sound#volume=0.5",
|
|
"setting reset",
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def invalid_remote_commands():
|
|
"""Return invalid remote control commands for testing validation.
|
|
|
|
Returns list of commands that should be rejected.
|
|
"""
|
|
return [
|
|
"setting set speech#rate=999", # Out of range
|
|
"setting set speech#rate=-1", # Negative value
|
|
"setting set speech#pitch=10", # Out of range
|
|
"setting set speech#volume=-0.5", # Negative volume
|
|
"setting set invalid#setting=value", # Invalid section
|
|
"command unknown_command", # Unknown command
|
|
]
|
|
|
|
|
|
# Pytest hooks for test session customization
|
|
|
|
|
|
def pytest_configure(config):
|
|
"""Configure pytest with custom settings."""
|
|
# Add custom markers
|
|
config.addinivalue_line(
|
|
"markers", "unit: Unit tests (fast, no mocking required)"
|
|
)
|
|
config.addinivalue_line(
|
|
"markers", "integration: Integration tests (require mocking)"
|
|
)
|
|
config.addinivalue_line(
|
|
"markers", "driver: Driver tests (require root access)"
|
|
)
|
|
config.addinivalue_line(
|
|
"markers", "slow: Tests that take more than 1 second"
|
|
)
|
|
|
|
|
|
def pytest_collection_modifyitems(config, items):
|
|
"""Modify test collection to skip driver tests unless explicitly run.
|
|
|
|
Driver tests require root access and hardware, so skip by default.
|
|
Run with: pytest --run-driver-tests
|
|
"""
|
|
skip_driver = pytest.mark.skip(
|
|
reason="Driver tests require root access (use --run-driver-tests)"
|
|
)
|
|
run_driver_tests = config.getoption("--run-driver-tests", default=False)
|
|
|
|
for item in items:
|
|
if "driver" in item.keywords and not run_driver_tests:
|
|
item.add_marker(skip_driver)
|
|
|
|
|
|
def pytest_addoption(parser):
|
|
"""Add custom command line options."""
|
|
parser.addoption(
|
|
"--run-driver-tests",
|
|
action="store_true",
|
|
default=False,
|
|
help="Run driver tests that require root access",
|
|
)
|