From 9e510714186ec76442a3482e10db923c218e05cb Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 11 Mar 2026 20:30:09 -0400 Subject: [PATCH] test: Added layout and scaling tests for Preset windows and AI Settings --- tests/test_ai_settings_layout.py | 58 ++++++++++++++++++++++++++++ tests/test_preset_windows_layout.py | 46 ++++++++++++++++++++++ tests/test_tool_management_layout.py | 47 ++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 tests/test_ai_settings_layout.py create mode 100644 tests/test_preset_windows_layout.py create mode 100644 tests/test_tool_management_layout.py diff --git a/tests/test_ai_settings_layout.py b/tests/test_ai_settings_layout.py new file mode 100644 index 0000000..83e1a7e --- /dev/null +++ b/tests/test_ai_settings_layout.py @@ -0,0 +1,58 @@ +import pytest +import time +from src.api_hook_client import ApiHookClient + +@pytest.mark.timeout(30) +def test_change_provider_via_hook(live_gui) -> None: + """Verify that we can change the current provider via the API hook.""" + client = ApiHookClient() + if not client.wait_for_server(): + pytest.fail("Server did not become ready") + + # Change provider to 'anthropic' + client.set_value('current_provider', 'anthropic') + + # Wait for state to reflect change + success = False + state = {} + for _ in range(20): + state = client.get_gui_state() + if state.get('current_provider') == 'anthropic': + success = True + break + time.sleep(0.5) + + assert success, f"Provider did not update. Current state: {state}" + +@pytest.mark.timeout(30) +def test_set_params_via_custom_callback(live_gui) -> None: + """Verify we can use custom_callback to set temperature and max_tokens.""" + client = ApiHookClient() + if not client.wait_for_server(): + pytest.fail("Server did not become ready") + + # Set temperature via custom_callback using _set_attr + client.post_gui({ + "action": "custom_callback", + "callback": "_set_attr", + "args": ["temperature", 0.85] + }) + + # Set max_tokens via custom_callback using _set_attr + client.post_gui({ + "action": "custom_callback", + "callback": "_set_attr", + "args": ["max_tokens", 1024] + }) + + # Verify via get_gui_state + success = False + state = {} + for _ in range(20): + state = client.get_gui_state() + if state.get('temperature') == 0.85 and state.get('max_tokens') == 1024: + success = True + break + time.sleep(0.5) + + assert success, f"Params did not update via custom_callback. Got: {state}" diff --git a/tests/test_preset_windows_layout.py b/tests/test_preset_windows_layout.py new file mode 100644 index 0000000..f138584 --- /dev/null +++ b/tests/test_preset_windows_layout.py @@ -0,0 +1,46 @@ +import pytest +import time +from concurrent.futures import ThreadPoolExecutor +from src.api_hook_client import ApiHookClient + +def test_preset_windows_opening(live_gui): + """Test opening Preset Manager, Tool Preset Manager, and Persona Editor via custom_callback.""" + client = ApiHookClient() + assert client.wait_for_server(timeout=15) + + # Push custom_callback events to set window visibility flags + # These rely on the _set_attr predefined callback in AppController + windows = [ + "show_preset_manager_window", + "show_tool_preset_manager_window", + "show_persona_editor_window" + ] + + for window in windows: + client.push_event("custom_callback", { + "callback": "_set_attr", + "args": [window, True] + }) + + # Wait 1 second as requested + time.sleep(1.0) + + # Verify the app is still responsive + status = client.get_status() + assert status.get("status") == "ok" + +def test_api_hook_under_load(live_gui): + """Verify the API Hook can still respond under load.""" + client = ApiHookClient() + assert client.wait_for_server(timeout=15) + + def make_request(_): + return client.get_status() + + # Send 20 parallel requests using a thread pool + with ThreadPoolExecutor(max_workers=10) as executor: + results = list(executor.map(make_request, range(20))) + + for res in results: + assert res is not None + assert res.get("status") == "ok" diff --git a/tests/test_tool_management_layout.py b/tests/test_tool_management_layout.py new file mode 100644 index 0000000..ffbb3c3 --- /dev/null +++ b/tests/test_tool_management_layout.py @@ -0,0 +1,47 @@ +import sys +import os +import time +from typing import Any + +# Ensure project root is in path for imports +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from src.api_hook_client import ApiHookClient + +def test_tool_management_state_updates(live_gui: Any) -> None: + client = ApiHookClient() + # Wait for hook server to be ready + assert client.wait_for_server(timeout=30), "Hook server did not respond within 30s" + + # Test setting ui_active_tool_preset via custom_callback + # callback '_set_attr' is defined in AppController._predefined_callbacks + preset_name = "TestToolPreset" + client.push_event("custom_callback", { + "callback": "_set_attr", + "args": ["ui_active_tool_preset", preset_name] + }) + + # Test setting ui_active_bias_profile via custom_callback + bias_profile = "TestBiasProfile" + client.push_event("custom_callback", { + "callback": "_set_attr", + "args": ["ui_active_bias_profile", bias_profile] + }) + + # Give some time for the GUI task to process (it's async via _pending_gui_tasks) + time.sleep(2.0) + + # Verify via get_gui_state + state = client.get_gui_state() + + assert state.get("ui_active_tool_preset") == preset_name, f"Expected {preset_name}, got {state.get('ui_active_tool_preset')}" + assert state.get("ui_active_bias_profile") == bias_profile, f"Expected {bias_profile}, got {state.get('ui_active_bias_profile')}" + +def test_tool_management_gettable_fields(live_gui: Any) -> None: + client = ApiHookClient() + assert client.wait_for_server(timeout=30) + + # Ensure they are at least present in the state (even if None/empty) + state = client.get_gui_state() + assert "ui_active_tool_preset" in state + assert "ui_active_bias_profile" in state