"""Classic fallback uses the shared instance guard without starting any GUI.""" import unittest from unittest import mock import wechat_gui as gui class ClassicInstanceTests(unittest.TestCase): def setUp(self): self.guard = mock.Mock() self.guard.acquire.return_value = True self.patch = mock.patch('desktop_instance.DesktopInstanceGuard', return_value=self.guard) self.patch.start() self.addCleanup(self.patch.stop) def test_secondary_only_activates_existing_instance(self): self.guard.acquire.return_value = False with mock.patch.object(gui, '_run_classic_primary') as launch: gui.run_classic_ui() launch.assert_not_called() self.guard.request_activation.assert_called_once_with() self.guard.close.assert_called_once_with() def test_primary_holds_guard_until_session_returns(self): def session(guard): self.assertIs(guard, self.guard) guard.close.assert_not_called() with mock.patch.object(gui, '_run_classic_primary', side_effect=session): gui.run_classic_ui() self.guard.close.assert_called_once_with() self.guard.request_activation.assert_not_called() def test_startup_failure_still_releases_guard(self): with mock.patch.object(gui, '_run_classic_primary', side_effect=RuntimeError('synthetic startup failure')): with self.assertRaises(RuntimeError): gui.run_classic_ui() self.guard.close.assert_called_once_with() def test_rejected_update_does_not_create_main_window(self): with mock.patch('backend_client.startup_sync_config', return_value={'release': {}}), \ mock.patch.object(gui, 'handle_startup_update', return_value=False), \ mock.patch.object(gui, 'App') as app: gui.run_classic_ui() app.assert_not_called() self.guard.close.assert_called_once_with() def test_activation_is_polled_on_tk_ui_thread(self): app = mock.Mock() jobs = [] app.after.side_effect = lambda delay, callback: jobs.append((delay, callback)) self.guard.consume_activation.return_value = True def loop(): self.assertEqual(jobs[0][0], 200) jobs.pop(0)[1]() self.assertEqual(jobs[0][0], 200) app.mainloop.side_effect = loop with mock.patch('backend_client.startup_sync_config', return_value={'release': {}}), \ mock.patch.object(gui, 'handle_startup_update', return_value=True), \ mock.patch.object(gui, 'App', return_value=app), \ mock.patch('archive_auto_backup.start_auto_backup') as backup: gui.run_classic_ui() app._expand_console.assert_called_once_with() app.focus_force.assert_called_once_with() backup.assert_called_once_with() self.guard.close.assert_called_once_with() def test_guard_constructor_failure_is_visible_and_does_not_launch(self): with mock.patch('desktop_instance.DesktopInstanceGuard', side_effect=OSError('synthetic denied')), \ mock.patch.object(gui.messagebox, 'showerror') as error, \ mock.patch.object(gui, '_run_classic_primary') as launch: gui.run_classic_ui() launch.assert_not_called() error.assert_called_once() self.guard.close.assert_not_called() if __name__ == '__main__': unittest.main()