""" UI 启动 smoke test: - 所有模块可正常 import - QApplication 能用 offscreen 平台创建 - MainWindow 能实例化、各 Tab 能构建 - AIConfigDialog 能弹出 """ import os import sys # offscreen 平台:允许在没有显示器的环境(CI/容器)跑 Qt os.environ["QT_QPA_PLATFORM"] = "offscreen" sys.path.insert(0, os.path.dirname(__file__)) from PyQt5.QtWidgets import QApplication from PyQt5.QtCore import QTimer from ui.main_window import MainWindow, APP_NAME from ui.host_dialog import HostDialog from ui.config_dialog import AIConfigDialog, PRESETS from ui.widgets import FileBrowser, MonitorPanel, AIChatPanel from core.ai_agent import AIAgent def main(): app = QApplication(sys.argv) app.setApplicationName(APP_NAME) print("[1/3] 验证 MainWindow 实例化") w = MainWindow() assert w.windowTitle().startswith(APP_NAME), w.windowTitle() assert w.tabs.count() == 4, f"应有 4 个 Tab,实际 {w.tabs.count()}" print(f" ✓ 主窗口创建,Tab 数量 = {w.tabs.count()}") print("[2/4] 验证子组件") assert isinstance(w.file_browser, FileBrowser) assert isinstance(w.monitor, MonitorPanel) assert isinstance(w.ai_panel, AIChatPanel) # 验证新增功能 assert hasattr(w.monitor, "_spark_cpu"), "MonitorPanel 应有 CPU 迷你图" assert hasattr(w.monitor, "_spark_mem"), "MonitorPanel 应有内存迷你图" assert hasattr(w.terminal_panel, "snippet_combo"), "TerminalPanel 应有片段下拉框" assert hasattr(w, "act_dark"), "MainWindow 应有暗色主题菜单项" menus = [a.text() for a in w.menuBar().actions()] assert "视图(&V)" in menus, f"应有视图菜单: {menus}" print(f" ✓ FileBrowser / MonitorPanel / AIChatPanel 全部就位") print(f" ✓ 暗色主题切换 / CPU·内存迷你图 / 命令片段下拉框") print("[3/4] 验证对话框") # 主机对话框 hd = HostDialog(current={"name": "test", "host": "1.2.3.4", "port": 22, "username": "u", "password": "p", "key_path": ""}) assert hd.name_edit.text() == "test" assert hd.host_edit.text() == "1.2.3.4" hd.close() print(" ✓ HostDialog 编辑模式可读字段") # AI 配置对话框 agent = AIAgent(api_key="test-key", base_url="http://localhost:1/v1", model="x") cd = AIConfigDialog(agent) assert cd.api_key_edit.text() == "test-key" assert len(PRESETS) >= 6 cd.close() print(f" ✓ AIConfigDialog + {len(PRESETS)} 个预设") print("[4/4] 验证主题切换") from ui.theme import get_theme, set_theme, get_qss # 切换到暗色 w.act_dark.setChecked(True) w._toggle_theme() assert get_theme() == "dark" qss = app.styleSheet() assert len(qss) > 100, "QSS 应该有内容" # 切回亮色 w.act_dark.setChecked(False) w._toggle_theme() assert get_theme() == "light" print(f" ✓ 暗/亮主题切换正常 (dark QSS={len(get_qss('dark'))} chars)") # 清理 w.close() print("\n所有 UI 组件加载正常 ✓") QTimer.singleShot(0, app.quit) app.exec_() if __name__ == "__main__": main()