""" 侧栏折叠测试: - 默认状态可见 - _toggle_sidebar 后隐藏 + 浮动按钮显示 - 再 toggle 恢复,splitter 宽度还原 - 菜单 act_toggle_sidebar 同步状态 - Ctrl+B 快捷键一次按键只触发一次(回归:曾经双绑定 toggle 两次=没反应) - 浮动按钮用父级局部坐标,贴主窗口左边缘 - 折叠状态持久化到 settings,新窗口恢复 """ import os import sys import tempfile from pathlib import Path os.environ["QT_QPA_PLATFORM"] = "offscreen" sys.path.insert(0, os.path.dirname(__file__)) # 隔离配置:不污染真实 ~/.sshclient/settings.json import ui.theme as theme _tmpdir = tempfile.mkdtemp(prefix="sshclient_sidebar_test_") theme.CONFIG_DIR = Path(_tmpdir) theme.SETTINGS_FILE = Path(_tmpdir) / "settings.json" from PyQt5.QtCore import Qt from PyQt5.QtTest import QTest from PyQt5.QtWidgets import QApplication from ui.main_window import MainWindow def main(): app = QApplication(sys.argv) print("[1/7] 默认状态:侧栏可见") w = MainWindow() w.show() w.activateWindow() app.processEvents() assert w._sidebar_collapsed is False assert w.left_panel.isVisible() assert w.btn_collapse_sidebar.text() == "◀" assert w.btn_show_sidebar.isHidden() print(" ✓ left_panel 可见, btn_collapse_sidebar='◀', btn_show_sidebar 隐藏") print("[2/7] 折叠:侧栏隐藏 + 浮动按钮显示") w._toggle_sidebar() app.processEvents() assert w._sidebar_collapsed is True assert not w.left_panel.isVisible() assert w.btn_collapse_sidebar.text() == "▶" assert w.btn_show_sidebar.isVisible() # 菜单项同步 assert w.act_toggle_sidebar.isChecked() assert "展开" in w.act_toggle_sidebar.text() print(" ✓ left_panel 隐藏, btn_collapse_sidebar='▶', btn_show_sidebar 可见, 菜单项 checked+text 已同步") print("[3/7] 展开:恢复 + splitter 宽度还原") w._toggle_sidebar() app.processEvents() assert w._sidebar_collapsed is False assert w.left_panel.isVisible() assert w.btn_collapse_sidebar.text() == "◀" assert w.btn_show_sidebar.isHidden() assert not w.act_toggle_sidebar.isChecked() assert "隐藏" in w.act_toggle_sidebar.text() left_w = w.splitter.sizes()[0] assert left_w > 0, f"展开后侧栏宽度应 >0, 实际 {left_w}" print(f" ✓ 恢复原状, splitter 侧栏宽度={left_w}px") print("[4/7] 连续折叠/展开多次") # 当前 collapsed=False;第 k 次 toggle 后 collapsed = (k 为奇数) for i in range(5): w._toggle_sidebar() app.processEvents() expected = (i % 2 == 0) # i=0 → 第1次 → True assert w._sidebar_collapsed == expected, \ f"第 {i+1} 次切换后应为 {expected}, 实际 {w._sidebar_collapsed}" assert w.left_panel.isVisible() == (not expected) # 5 次后 collapsed=True,再 toggle 一次回到 False w._toggle_sidebar() app.processEvents() assert w._sidebar_collapsed is False print(" ✓ 6 次切换状态全部正确") print("[5/7] Ctrl+B 快捷键:一次按键只触发一次") before = w._sidebar_collapsed QTest.keyClick(w, Qt.Key_B, Qt.ControlModifier) app.processEvents() assert w._sidebar_collapsed == (not before), \ f"Ctrl+B 未生效(或双绑定触发了两次): before={before}, after={w._sidebar_collapsed}" QTest.keyClick(w, Qt.Key_B, Qt.ControlModifier) app.processEvents() assert w._sidebar_collapsed == before print(f" ✓ 按两次 Ctrl+B: {before} → {not before} → {before}") print("[6/7] 浮动按钮位置:父级局部坐标 (4, 100)") if not w._sidebar_collapsed: w._toggle_sidebar() app.processEvents() pos = w.btn_show_sidebar.pos() assert (pos.x(), pos.y()) == (4, 100), \ f"浮动按钮位置 ({pos.x()}, {pos.y()}) != (4, 100)" print(f" ✓ 浮动按钮局部坐标 ({pos.x()}, {pos.y()}),窗口移动/缩放都不会飘走") w._toggle_sidebar() app.processEvents() print("[7/7] 状态持久化:重启后恢复折叠状态") # 折叠 → 新窗口应恢复为折叠 if not w._sidebar_collapsed: w._toggle_sidebar() app.processEvents() assert theme.load_settings()["sidebar_collapsed"] is True w2 = MainWindow() w2.show() app.processEvents() assert w2._sidebar_collapsed is True assert not w2.left_panel.isVisible() assert w2.btn_show_sidebar.isVisible() assert w2.act_toggle_sidebar.isChecked() # 展开 → 再开新窗口应恢复为展开 w2._toggle_sidebar() app.processEvents() w3 = MainWindow() w3.show() app.processEvents() assert w3._sidebar_collapsed is False assert w3.left_panel.isVisible() assert w3.btn_show_sidebar.isHidden() print(" ✓ 折叠/展开状态均能跨启动恢复(含菜单项勾选同步)") print("\n侧栏折叠测试全部通过 ✓") if __name__ == "__main__": main()