"""Prevent invisible-page work and unbounded UI event processing.""" import os,queue os.environ.setdefault('QT_QPA_PLATFORM','offscreen') from types import SimpleNamespace from unittest import TestCase,mock from wechat_gui_qt import MainWindow,SettingsPage def snapshot_host(view): text=lambda value:SimpleNamespace(text=lambda:value) host=SimpleNamespace(_running=False,_status_key='stopped',_console_view=view,runtime_settings={}, business_page=SimpleNamespace(archive_search=text(''),active_archive_filter='全部'), queue_page=SimpleNamespace(pending_states={},active_task_filter='全部'), log_page=SimpleNamespace(event_search=text(''),active_event_filter='全部'), _console_wecom_info=mock.Mock(return_value={'connected':False}), _console_dpi_label=mock.Mock(return_value='100%'), _console_idle_label=mock.Mock(return_value='5秒'), _console_runtime_label=mock.Mock(return_value='00:00:00'), _console_archive_filter_label=mock.Mock(return_value='全部会话')) defaults={'people':[{'key':'one'}],'logs':[],'activities':[],'metrics':{},'journey':[],'task':None, 'journey_total':'','chain':[],'window_stats':[],'archives':[{'key':'archive'}], 'chat':[],'memory':{},'settle':{},'ai_state':{'name':'客服'},'automation_state':{'poll':2}, 'system_state':{'scale':'自动','serverUrl':'http://example.invalid'},'log_detail':{}} for name,value in defaults.items():setattr(host,'_console_'+name,mock.Mock(return_value=value)) host._console_sort_people=mock.Mock(side_effect=lambda people:people) host._wechat_database_console_state=mock.Mock(return_value={'accounts':[]}) return host class SnapshotPerformanceTest(TestCase): def test_editing_pages_do_not_read_queues_archives_or_logs(self): for view,key in [('ai','ai'),('automation','automation'),('system','system'),('wechatdb','wechatDb')]: with self.subTest(view=view): host=snapshot_host(view);data=MainWindow._console_snapshot(host) self.assertIn(key,data) for name in ['people','task','archives','chat','memory','logs','metrics']: getattr(host,'_console_'+name).assert_not_called() if view!='system':host._console_system_state.assert_not_called() def test_each_page_receives_its_required_state(self): required={'auto':['people','task','journey','windowStats','metrics'], 'queue':['people','task','chain','metrics'], 'archive':['archives','chat','memory','settle'], 'logs':['logs','logDetail','exceptions','chain','metrics'], 'ai':['ai'],'automation':['automation'],'system':['system'],'wechatdb':['wechatDb']} for view,keys in required.items(): data=MainWindow._console_snapshot(snapshot_host(view)) for key in keys:self.assertIn(key,data,(view,key)) def test_system_cache_preserves_connection_fields_and_updates_scale(self): host=snapshot_host('system');MainWindow._console_snapshot(host) host._console_view='ai';host.runtime_settings={'scale_ratio':'200%'} result=MainWindow._console_snapshot(host) self.assertEqual(result['system']['serverUrl'],'http://example.invalid') self.assertEqual(result['system']['scale'],'200%') host._console_system_state.assert_called_once() def test_live_queue_does_not_build_archive_or_settings_views(self): host=snapshot_host('queue');data=MainWindow._console_snapshot(host) self.assertEqual(data['selectedKey'],'one');self.assertTrue(data['people'][0]['active']) for name in ['archives','chat','memory','ai_state','system_state','automation_state']: getattr(host,'_console_'+name).assert_not_called() host._wechat_database_console_state.assert_not_called() class EventLoopPerformanceTest(TestCase): def host(self,count): events=queue.Queue() for i in range(count):events.put(('log',str(i))) return SimpleNamespace(_queue=events,_start_time=None,_running=False, append_log=mock.Mock(),queue_timer=mock.Mock()) def test_large_event_burst_yields_after_64_and_keeps_order(self): host=self.host(200) with mock.patch('wechat_gui_qt.time.perf_counter',return_value=0): MainWindow._process_queue(host) self.assertEqual(host._queue.qsize(),136) host.queue_timer.setInterval.assert_called_with(16) for _ in range(3):MainWindow._process_queue(host) self.assertTrue(host._queue.empty()) self.assertEqual([c.args[0] for c in host.append_log.call_args_list],[str(i) for i in range(200)]) host.queue_timer.setInterval.assert_called_with(140) def test_time_budget_yields_even_when_message_limit_not_reached(self): host=self.host(20) with mock.patch('wechat_gui_qt.time.perf_counter',side_effect=[0,0.001,0.010]): MainWindow._process_queue(host) self.assertEqual(host.append_log.call_count,1) self.assertEqual(host._queue.qsize(),19) def test_manual_save_consumes_pending_native_autosave(self): host=SimpleNamespace(save_timer=mock.Mock(),_set_save_status=mock.Mock(),saved=mock.Mock(),values=lambda:{'poll_interval':7}) SettingsPage._emit_save(host) host.save_timer.stop.assert_called_once() host.saved.emit.assert_called_once_with({'poll_interval':7})