# -*- coding: utf-8 -*- """验证首次设置窗口(界面重做之后:整个程序只有这一个窗口)。 1. 全新安装 → 出现设置窗口:配对码输入框 + 自启/防火墙勾选框 + 按钮 2. 输入 6 位数字点确定 → 返回结果里带着码 3. 输入太短的码 → 被拒绝,窗口不关 """ from __future__ import annotations import shutil import sys import tempfile import time import tkinter as tk from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "windows")) PASSED = 0 FAILED = 0 def check(name, ok, detail=""): global PASSED, FAILED if ok: PASSED += 1 print(f" [PASS] {name}") else: FAILED += 1 print(f" [FAIL] {name} {detail}") def walk(widget): yield widget try: for child in widget.winfo_children(): yield from walk(child) except tk.TclError: return def inspect(window) -> dict: """看看窗口上有什么控件。""" root = window.root return { "entries": [w for w in walk(root) if isinstance(w, tk.Entry)], "checks": [w for w in walk(root) if isinstance(w, tk.Checkbutton)], "buttons": [w for w in walk(root) if isinstance(w, tk.Button)], "labels": [str(w.cget("text")) for w in walk(root) if isinstance(w, tk.Label)], } def fill_and_confirm(window, code: str) -> bool: parts = inspect(window) if parts["entries"]: entry = parts["entries"][0] entry.delete(0, "end") entry.insert(0, code) for button in parts["buttons"]: try: if "确定" in str(button.cget("text")): button.invoke() return True except tk.TclError: continue return False def main() -> int: from lanremote.config import Store from lanremote.ui import SetupWindow work = Path(tempfile.mkdtemp(prefix="lr_setup2_")) print("一、全新安装:应该弹出设置窗口") store = Store(work) window = SetupWindow(store) found: dict = {} def ready(win): root = win.root # 多刷几轮,等布局稳定(刚建好时 winfo_width 还可能是初始值) for _ in range(6): root.update_idletasks() root.update() time.sleep(0.2) parts = inspect(win) found["entries"] = len(parts["entries"]) found["checks"] = len(parts["checks"]) found["buttons"] = len(parts["buttons"]) found["labels"] = parts["labels"] children = root.winfo_children() found["metrics"] = { "width": root.winfo_width(), "height": root.winfo_height(), "children": len(children), "mapped": sum(1 for c in children if c.winfo_ismapped()), "reqheight": root.winfo_reqheight(), "entry_mapped": any(e.winfo_ismapped() for e in parts["entries"]), } found["confirmed"] = fill_and_confirm(win, "789113") result = window.show(on_ready=ready) print(f" 输入框 {found.get('entries')} 个," f"勾选框 {found.get('checks')} 个,按钮 {found.get('buttons')} 个") for text in found.get("labels", []): if text.strip(): print(f" 文案: {text[:40]!r}") # ---- 界面必须真的显示出来 ---- # 踩过的坑:_card() 返回了内层 frame,内层挂在从未 pack 的外层里, # 于是两张卡片完全不显示,窗口只有 199px 高 —— 但控件都在, # 光数控件个数查不出来。所以这里断言"够高 + 子控件是 mapped 的"。 metrics = found.get("metrics", {}) print(f" 窗口 {metrics.get('width')}x{metrics.get('height')}," f"mapped 子控件 {metrics.get('mapped')}/{metrics.get('children')}") check("设置窗口够高(卡片真的画出来了)", (metrics.get("height") or 0) >= 400, f"高度只有 {metrics.get('height')}(<400 说明卡片没显示)") check("有多个子控件被真正映射(mapped)", (metrics.get("mapped") or 0) >= 2, metrics) check("配对码输入框是可见的", metrics.get("entry_mapped") is True, metrics) check("设置窗口有输入框", found.get("entries", 0) >= 1, str(found)) check("窗口上有勾选框(自启 / 防火墙)", found.get("checks", 0) >= 1, f"{found.get('checks')} 个") check("窗口上有按钮", found.get("buttons", 0) >= 2, f"{found.get('buttons')} 个") check("点了确定", found.get("confirmed") is True) check("返回了结果", isinstance(result, dict), str(result)) if isinstance(result, dict): check("配对码是 789113", result.get("code") == "789113", str(result)) check("带上了自启选项", "autostart" in result, str(result)) check("带上了防火墙选项", "firewall" in result, str(result)) print() print("二、太短的码要被拒绝") bad_store = Store(Path(tempfile.mkdtemp(prefix="lr_bad_"))) bad = SetupWindow(bad_store) state = {"tried_short": False} def ready_bad(win): state["tried_short"] = fill_and_confirm(win, "123") def later(): try: if win.root.winfo_exists(): fill_and_confirm(win, "123456") except tk.TclError: pass win.root.after(400, later) result_bad = bad.show(on_ready=ready_bad) check("太短的码没有让窗口关闭(后来又输了对的)", isinstance(result_bad, dict) and result_bad.get("code") == "123456", str(result_bad)) print() print("三、随机码建议是 6 位") fresh = Store(Path(tempfile.mkdtemp(prefix="lr_fresh_"))) suggestion = fresh.new_pairing_code() check("默认建议 6 位", len(suggestion) == 6, suggestion) check("建议是纯数字", suggestion.isdigit(), suggestion) shutil.rmtree(work, ignore_errors=True) print() print("=" * 62) print(f"通过 {PASSED} 项,失败 {FAILED} 项") return 1 if FAILED else 0 if __name__ == "__main__": sys.exit(main())