fix: save_auth 改为纯手动模式,不再尝试自动填表

用户自己在浏览器中完成验证码登录后按 Enter,脚本仅负责检测并保存 storage_state
This commit is contained in:
xst
2026-07-15 10:59:24 +08:00
parent 49eb9bcd2b
commit 4b4b83a2c0
+25 -63
View File
@@ -5,41 +5,27 @@
cookies + localStorage 序列化到 JSON 文件,后续用例自动复用。 cookies + localStorage 序列化到 JSON 文件,后续用例自动复用。
用法: 用法:
# 保存超级管理员的登录态(最常用)
python tests/web/save_auth.py python tests/web/save_auth.py
# 保存指定角色的登录态 流程:
python tests/web/save_auth.py --role team_leader 1. 脚本打开浏览器到登录页
2. 你在浏览器中手动输入账号、密码、完成验证码并点击登录
# 指定浏览器 3. 登录成功后按 Enter 键,脚本自动保存登录态
python tests/web/save_auth.py --browser firefox 4. 后续 pytest 用例自动复用
# 查看帮助
python tests/web/save_auth.py --help
生成的 auth 文件: 生成的 auth 文件:
tests/web/auth/super_admin_chromium.json tests/web/auth/super_admin_chromium.json
tests/web/auth/team_leader_firefox.json
...
""" """
import argparse import argparse
import sys import sys
from pathlib import Path from pathlib import Path
# 确保 tests/ 在 Python path 中
sys.path.insert(0, str(Path(__file__).parent.parent.parent)) sys.path.insert(0, str(Path(__file__).parent.parent.parent))
from tests.config.test_config import load_config from tests.config.test_config import load_config
# 登录页的 URL 后缀
LOGIN_PATH = "/login"
# 登录后验证成功的 URL 关键字
SUCCESS_URL_KEYWORD = "/admin"
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="手动登录并保存浏览器登录态(绕过图形验证码)" description="手动登录并保存浏览器登录态(绕过图形验证码)"
@@ -47,8 +33,7 @@ def main():
parser.add_argument( parser.add_argument(
"--role", "--role",
default="super_admin", default="super_admin",
choices=["super_admin", "team_leader", "driver"], help="登录角色(默认: super_admin),会体现在文件名中",
help="登录角色(默认: super_admin",
) )
parser.add_argument( parser.add_argument(
"--browser", "--browser",
@@ -56,68 +41,48 @@ def main():
choices=["chromium", "firefox", "webkit"], choices=["chromium", "firefox", "webkit"],
help="浏览器类型(默认: chromium", help="浏览器类型(默认: chromium",
) )
parser.add_argument(
"--headless",
action="store_true",
help="无头模式(开启后将无法手动输入验证码,仅用于测试已保存的登录态)",
)
args = parser.parse_args() args = parser.parse_args()
config = load_config() config = load_config()
web_config = config["web"] web_config = config["web"]
account = config["accounts"].get(args.role)
if not account:
print(f"❌ 未知角色 '{args.role}',可用: {list(config['accounts'].keys())}")
sys.exit(1)
base_url = web_config["base_url"] base_url = web_config["base_url"]
login_url = f"{base_url}/#/login" login_url = f"{base_url}/#/login"
# ── 打开浏览器 ──
from playwright.sync_api import sync_playwright from playwright.sync_api import sync_playwright
with sync_playwright() as p: with sync_playwright() as p:
browser_launcher = getattr(p, args.browser) browser_launcher = getattr(p, args.browser)
browser = browser_launcher.launch(headless=args.headless) browser = browser_launcher.launch(headless=False)
context = browser.new_context( context = browser.new_context(
viewport={"width": 1920, "height": 1080}, viewport={"width": 1920, "height": 1080},
locale="zh-CN", locale="zh-CN",
) )
page = context.new_page() page = context.new_page()
# ── 导航到登录页 ──
print(f"\n🔗 打开登录页: {login_url}") print(f"\n🔗 打开登录页: {login_url}")
page.goto(login_url) page.goto(login_url)
# ── 填入账号密码 ── print(f"\n{'='*60}")
page.get_by_placeholder("请输入用户名").fill(account["phone"]) print(f"👤 角色: {args.role}")
page.get_by_placeholder("请输入密码").fill(account["password"]) print(f" 请在浏览器中手动完成登录(输入账号密码 + 验证码)")
print(f"👤 已填入账号: {account['phone']}(角色: {args.role}") print(f" 登录成功后回到此处按 Enter 键保存登录态...")
print("📝 请在浏览器中手动完成验证码并点击登录...") print(f"{'='*60}\n")
print(" (登录成功后脚本会自动检测并保存)\n")
# ── 等待用户手动完成验证码 + 登录 ── input(">>> 按 Enter 保存登录态...")
try:
# Hash 路由模式,用元素可见判断登录成功而不是 URL 变化 # 检查是否真的登录成功了
page.wait_for_selector(".ant-layout-sider, .sidebar, [class*='sider']", timeout=300_000) current = page.url
except Exception: if "/login" in current or "/#/login" in current:
print("\n⚠️ 等待超时(5 分钟)。可能原因:") print(f"\n⚠️ 当前仍在登录页: {current}")
print(" 1. 未在浏览器中完成验证码登录") print(" 要保存吗?(y/n): ", end="")
print(" 2. 账号密码错误") choice = input().strip().lower()
print(" 3. 网络不可达") if choice != "y":
print(" 请检查后重试") print("已取消")
browser.close() browser.close()
sys.exit(1) sys.exit(0)
# ── 验证登录成功 ── print(f"\n✅ 当前页面: {current}")
if "/login" in page.url or "/#/login" in page.url:
print("\n❌ 登录失败,仍然停留在登录页。请检查账号密码。")
browser.close()
sys.exit(1)
print(f"✅ 登录成功!当前页面: {page.url}")
# ── 保存登录态 ──
auth_dir = Path(web_config.get("storage_state_dir", "tests/web/auth")) auth_dir = Path(web_config.get("storage_state_dir", "tests/web/auth"))
auth_dir.mkdir(parents=True, exist_ok=True) auth_dir.mkdir(parents=True, exist_ok=True)
auth_file = auth_dir / f"{args.role}_{args.browser}.json" auth_file = auth_dir / f"{args.role}_{args.browser}.json"
@@ -127,10 +92,7 @@ def main():
browser.close() browser.close()
print("\n🎉 完成!现在可以运行用例了:") print(f"\n🎉 现在可以跑了: pytest tests/web/ -m p0")
print(f" pytest tests/web/ -m p0")
print(f"\n登录态过期后重新运行即可:")
print(f" python tests/web/save_auth.py --role {args.role}")
if __name__ == "__main__": if __name__ == "__main__":