"""自动验证「环境准备」窗口的检测 → 确认 → 放行 流程(不需要人工点按钮)。 验证点: 1. 所有项最终都能检测完(不会卡在「检测中…」) 2. 全部就绪时,「进入程序」按钮变为可用 3. 调用 _on_confirm 后 proceeded=True(main() 才会继续启动服务) 4. 关闭窗口(_on_close)时 proceeded=False(main() 应当退出) """ from __future__ import annotations import sys import time import traceback from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) import tkinter as tk # noqa: E402 from core.setup_window import SetupWindow # noqa: E402 FAILURES: list[str] = [] CALLBACK_ERRORS: list[str] = [] def check(name: str, ok: bool, detail: str = "") -> None: print(f" [{'PASS' if ok else 'FAIL'}] {name}" + (f" — {detail}" if detail else "")) if not ok: FAILURES.append(name) def pump(root: tk.Tk, seconds: float) -> None: """手动驱动 tkinter 事件循环(不进入 mainloop,便于断言)。""" deadline = time.monotonic() + seconds while time.monotonic() < deadline: try: root.update() except tk.TclError as exc: print(f" [pump] TclError 中断:{exc}") return time.sleep(0.02) def main() -> int: root = tk.Tk() def _on_cb_error(exc_type, exc_value, exc_tb) -> None: # Tk 回调里的异常 text = "".join(traceback.format_exception(exc_type, exc_value, exc_tb)) CALLBACK_ERRORS.append(text) print(f" [回调异常] {exc_value}") root.report_callback_exception = _on_cb_error win = SetupWindow(root, title="自检窗口") # Apple 驱动检测要做 27015 协议往返,留足时间 pump(root, 25.0) print(" 各项状态:") for item in win.items: st = win.state[item.key] print(f" {item.key:16s} required={item.required} ok={st.get('ok')} " f"busy={st.get('busy')} detail={str(st.get('detail'))[:46]}") try: exists = bool(root.winfo_exists()) except tk.TclError as exc: exists = False print(f" 窗口已不可用:{exc}") print(f" 窗口存在:{exists} proceeded={win.proceeded}") check("窗口在检测期间没有被意外销毁", exists) check("Tk 回调没有抛异常", not CALLBACK_ERRORS, f"{len(CALLBACK_ERRORS)} 个" if CALLBACK_ERRORS else "") stuck = [i.key for i in win.items if win.state[i.key].get("ok") is None and not win.state[i.key].get("busy")] check("没有卡在「检测中…」的项", not stuck, str(stuck)) required = [i for i in win.items if i.required] pending = [i.key for i in required if win.state[i.key].get("ok") is not True] check("必需项全部就绪(本机环境)", not pending, str(pending)) try: enabled = bool(win.confirm_button.instate(["!disabled"])) detail = f"state={win.confirm_button.state()}" except tk.TclError as exc: enabled, detail = False, f"控件已失效:{exc}" check("「进入程序」按钮可用", enabled, detail) # 模拟点击「进入程序」 win._on_confirm() check("点击后 proceeded=True", win.proceeded is True, f"proceeded={win.proceeded}") try: root.destroy() except Exception: pass # 再测「关闭窗口」分支 root2 = tk.Tk() win2 = SetupWindow(root2, title="自检窗口2") pump(root2, 1.0) win2._on_close() check("关闭窗口时 proceeded=False", win2.proceeded is False, f"proceeded={win2.proceeded}") try: root2.destroy() except Exception: pass print() if FAILURES: print(f"失败 {len(FAILURES)} 项:{FAILURES}") return 1 print("全部通过") return 0 if __name__ == "__main__": sys.exit(main())