import pytest from unittest.mock import patch, MagicMock import importlib.util import sys import os import dearpygui.dearpygui as dpg # Ensure project root is in path for imports sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) # Load gui.py as a module for testing spec = importlib.util.spec_from_file_location("gui", "gui.py") gui = importlib.util.module_from_spec(spec) sys.modules["gui"] = gui spec.loader.exec_module(gui) from gui import App @pytest.fixture def app_instance(): """ Fixture to create an instance of the App class for testing. It creates a real DPG context but mocks functions that would render a window or block execution. """ dpg.create_context() # Patch only the functions that would show a window or block, # and the App methods that rebuild UI on init. with patch('dearpygui.dearpygui.create_viewport'), \ patch('dearpygui.dearpygui.setup_dearpygui'), \ patch('dearpygui.dearpygui.show_viewport'), \ patch('dearpygui.dearpygui.start_dearpygui'), \ patch('gui.load_config', return_value={}), \ patch.object(App, '_rebuild_files_list'), \ patch.object(App, '_rebuild_shots_list'), \ patch.object(App, '_rebuild_disc_list'), \ patch.object(App, '_rebuild_disc_roles_list'), \ patch.object(App, '_rebuild_discussion_selector'), \ patch.object(App, '_refresh_project_widgets'): app = App() yield app dpg.destroy_context() def test_telemetry_panel_updates_correctly(app_instance): """ Tests that the _update_performance_diagnostics method correctly updates DPG widgets based on the stats from ai_client. """ # 1. Set the provider to anthropic app_instance.current_provider = "anthropic" # 2. Define the mock stats mock_stats = { "provider": "anthropic", "limit": 180000, "current": 135000, "percentage": 75.0, } # 3. Patch the dependencies app_instance._last_bleed_update_time = 0 # Force update with patch('ai_client.get_history_bleed_stats', return_value=mock_stats) as mock_get_stats, \ patch('dearpygui.dearpygui.set_value') as mock_set_value, \ patch('dearpygui.dearpygui.configure_item') as mock_configure_item, \ patch('dearpygui.dearpygui.is_item_shown', return_value=False), \ patch('dearpygui.dearpygui.does_item_exist', return_value=True) as mock_does_item_exist: # 4. Call the method under test app_instance._refresh_api_metrics() # 5. Assert the results mock_get_stats.assert_called_once() # Assert history bleed widgets were updated mock_set_value.assert_any_call("token_budget_bar", 0.75) mock_set_value.assert_any_call("token_budget_label", "135,000 / 180,000") # Assert Gemini-specific widget was hidden mock_configure_item.assert_any_call("gemini_cache_label", show=False) def test_cache_data_display_updates_correctly(app_instance): """ Tests that the _update_performance_diagnostics method correctly updates the GUI with Gemini cache statistics when the provider is set to Gemini. """ # 1. Set the provider to Gemini app_instance.current_provider = "gemini" # 2. Define mock cache stats mock_cache_stats = { 'cache_count': 5, 'total_size_bytes': 12345 } # Expected formatted string expected_text = "Gemini Caches: 5 (12.1 KB)" # 3. Patch dependencies app_instance._last_bleed_update_time = 0 # Force update with patch('ai_client.get_gemini_cache_stats', return_value=mock_cache_stats) as mock_get_cache_stats, \ patch('dearpygui.dearpygui.set_value') as mock_set_value, \ patch('dearpygui.dearpygui.configure_item') as mock_configure_item, \ patch('dearpygui.dearpygui.is_item_shown', return_value=False), \ patch('dearpygui.dearpygui.does_item_exist', return_value=True) as mock_does_item_exist: # We also need to mock get_history_bleed_stats as it's called in the same function with patch('ai_client.get_history_bleed_stats', return_value={}): # 4. Call the method under test with payload app_instance._refresh_api_metrics(payload={'cache_stats': mock_cache_stats}) # 5. Assert the results # mock_get_cache_stats.assert_called_once() # No longer called synchronously # Check that the UI item was shown and its value was set mock_configure_item.assert_any_call("gemini_cache_label", show=True) mock_set_value.assert_any_call("gemini_cache_label", expected_text)