Initial commit: add AutoDeploy project
This commit is contained in:
163
tests/test_gui_navigation.py
Normal file
163
tests/test_gui_navigation.py
Normal file
@@ -0,0 +1,163 @@
|
||||
import unittest
|
||||
import queue
|
||||
from unittest.mock import patch
|
||||
|
||||
from deploy_tool.gui import DeployWorkbench, database_name_from_sql_files
|
||||
import deploy_tool.gui as gui_module
|
||||
|
||||
|
||||
class FakeWidget:
|
||||
def __init__(self):
|
||||
self.focused = False
|
||||
self.seen = False
|
||||
|
||||
def focus_set(self):
|
||||
self.focused = True
|
||||
|
||||
def see(self, index):
|
||||
self.seen = index
|
||||
|
||||
|
||||
class FakeButton:
|
||||
def __init__(self):
|
||||
self.state = None
|
||||
|
||||
def configure(self, **options):
|
||||
self.state = options.get("state")
|
||||
|
||||
|
||||
class GuiNavigationTests(unittest.TestCase):
|
||||
def test_database_name_comes_from_first_sql_filename(self):
|
||||
from pathlib import Path
|
||||
|
||||
self.assertEqual(database_name_from_sql_files([Path("db/movie.sql")]), "movie")
|
||||
self.assertEqual(database_name_from_sql_files([]), "")
|
||||
|
||||
def test_deployment_running_state_updates_deploy_button(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.deployment_running = False
|
||||
app.deploy_buttons = [FakeButton()]
|
||||
set_running = getattr(DeployWorkbench, "_set_deployment_running", lambda self, running: None)
|
||||
|
||||
set_running(app, True)
|
||||
|
||||
self.assertTrue(app.deployment_running)
|
||||
self.assertEqual([button.state for button in app.deploy_buttons], ["disabled"])
|
||||
|
||||
set_running(app, False)
|
||||
|
||||
self.assertFalse(app.deployment_running)
|
||||
self.assertEqual([button.state for button in app.deploy_buttons], ["normal"])
|
||||
|
||||
def test_running_deployment_ignores_another_deploy_request(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.deployment_running = True
|
||||
plan_calls = []
|
||||
logs = []
|
||||
app._current_plan = lambda: plan_calls.append("planned") or []
|
||||
app._append_log = logs.append
|
||||
|
||||
DeployWorkbench.run_deploy_plan_async(app)
|
||||
|
||||
self.assertEqual(plan_calls, [])
|
||||
self.assertTrue(any("正在执行" in line for line in logs))
|
||||
|
||||
def test_confirmed_deployment_locks_buttons_before_worker_starts(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.deployment_running = False
|
||||
app.deploy_buttons = [FakeButton()]
|
||||
app._current_plan = lambda: [object()]
|
||||
app.ui_queue = object()
|
||||
app._thread_log = lambda value: None
|
||||
|
||||
with patch.object(gui_module.messagebox, "askyesno", return_value=True), patch.object(gui_module.threading, "Thread") as thread_class:
|
||||
DeployWorkbench.run_deploy_plan_async(app)
|
||||
|
||||
self.assertTrue(app.deployment_running)
|
||||
self.assertEqual([button.state for button in app.deploy_buttons], ["disabled"])
|
||||
thread_class.return_value.start.assert_called_once_with()
|
||||
|
||||
def test_thread_start_failure_restores_deploy_buttons(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.deployment_running = False
|
||||
app.deploy_buttons = [FakeButton()]
|
||||
app._current_plan = lambda: [object()]
|
||||
logs = []
|
||||
app._append_log = logs.append
|
||||
|
||||
with patch.object(gui_module.messagebox, "askyesno", return_value=True), patch.object(gui_module.threading, "Thread") as thread_class:
|
||||
thread_class.return_value.start.side_effect = RuntimeError("thread unavailable")
|
||||
try:
|
||||
DeployWorkbench.run_deploy_plan_async(app)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
self.assertFalse(app.deployment_running)
|
||||
self.assertEqual([button.state for button in app.deploy_buttons], ["normal"])
|
||||
self.assertTrue(any("thread unavailable" in line for line in logs))
|
||||
|
||||
def test_worker_exception_always_queues_deploy_done(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.ui_queue = queue.Queue()
|
||||
run_worker = getattr(DeployWorkbench, "_run_deployment_worker", lambda self, plan: None)
|
||||
|
||||
with patch.object(gui_module, "run_steps", side_effect=RuntimeError("unexpected failure")):
|
||||
run_worker(app, [object()])
|
||||
|
||||
events = []
|
||||
while not app.ui_queue.empty():
|
||||
events.append(app.ui_queue.get_nowait())
|
||||
|
||||
self.assertIn(("deploy_done", 1), events)
|
||||
self.assertTrue(any(event == "log" and "unexpected failure" in str(payload) for event, payload in events))
|
||||
|
||||
def test_deploy_done_event_restores_deploy_buttons(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.deployment_running = True
|
||||
app.deploy_buttons = [FakeButton()]
|
||||
app.ui_queue = queue.Queue()
|
||||
app.ui_queue.put(("deploy_done", 1))
|
||||
logs = []
|
||||
app._append_log = logs.append
|
||||
app.after = lambda *args, **kwargs: None
|
||||
|
||||
DeployWorkbench._drain_queue(app)
|
||||
|
||||
self.assertFalse(app.deployment_running)
|
||||
self.assertEqual([button.state for button in app.deploy_buttons], ["normal"])
|
||||
self.assertTrue(any("退出码: 1" in line for line in logs))
|
||||
|
||||
def test_top_action_only_exposes_execution(self):
|
||||
self.assertNotIn("plan", gui_module.TEXT)
|
||||
self.assertEqual(gui_module.TEXT["deploy"], "执行部署")
|
||||
|
||||
def test_sidebar_navigation_focuses_logs(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.log_text = FakeWidget()
|
||||
app.result_text = FakeWidget()
|
||||
|
||||
app.activate_sidebar_item("运行日志")
|
||||
|
||||
self.assertTrue(app.log_text.focused)
|
||||
self.assertEqual(app.log_text.seen, "end")
|
||||
|
||||
def test_sidebar_navigation_focuses_database_config(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
app.database_widget = FakeWidget()
|
||||
|
||||
app.activate_sidebar_item("数据库")
|
||||
|
||||
self.assertTrue(app.database_widget.focused)
|
||||
|
||||
def test_sidebar_navigation_can_trigger_environment_check(self):
|
||||
app = DeployWorkbench.__new__(DeployWorkbench)
|
||||
calls = []
|
||||
app.check_environment_async = lambda: calls.append("checked")
|
||||
|
||||
app.activate_sidebar_item("环境检测")
|
||||
|
||||
self.assertEqual(calls, ["checked"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user