"""计提参数管理端到端测试(需要容器、后端、前端都在运行)。 覆盖链路(M1 验收):目录分组展示 → 修改参数入「待提交」→ 批次提交(立即 生效)→ 目录反映新值 → 版本记录可见 → 计算预览金标准复现(27 天 / 9.7‰ / 145.5 元)→ 值改回种子值恢复现场。 运行:``E2E_ADMIN_PASSWORD=... python e2e/param_management.py`` """ import sys sys.path.insert(0, __import__("os").path.dirname(__file__)) from playwright.sync_api import sync_playwright from common import ( BASE_URL, E2EFailure, collect_console_errors, expect_toast, fail, login, wait_toast, ) if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8") PARAMS_URL = f"{BASE_URL}/system/params" console_errors: list[str] = [] def step(title: str) -> None: print(f"—— {title}") def main() -> int: failures: list[str] = [] with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page(viewport={"width": 1440, "height": 860}) errors = collect_console_errors(page, console_errors) try: admin_password = __import__("os").environ.get("E2E_ADMIN_PASSWORD") if not admin_password: print("✗ 缺少环境变量 E2E_ADMIN_PASSWORD(管理员密码不入库)") return 1 login(page, "admin", admin_password) page.goto(PARAMS_URL, wait_until="networkidle") step("1. 目录分组展示") if page.locator(".group-title", has_text="支付环节").count() == 0: fail("目录分组", "未找到「支付环节」分组") # 展开「支付环节」分组 page.locator(".el-collapse-item__header", has_text="支付环节").click() page.wait_for_timeout(300) step("2. 修改预付款比例 10 → 12(立即生效)") row = page.locator(".param-table tbody tr", has_text="预付款计提比例").first row.get_by_role("button", name="修改", exact=True).click() dialog = page.locator(".el-dialog") dialog.locator("input").fill("12") dialog.get_by_role("button", name="暂存修改").click() if "待改为 12" not in page.content(): fail("待提交", "参数行未出现「待改为 12」标记") step("3. 提交批次") page.get_by_role("button", name="提交变更").click() page.locator(".el-message-box").get_by_role("button", name="提交").click() expect_toast(page, "已提交", "提交批次") step("4. 目录反映新值") page.wait_for_timeout(500) row = page.locator(".param-table tbody tr", has_text="预付款计提比例").first if "12" not in row.text_content(): fail("目录生效", "提交后目录未显示新值 12") step("5. 版本记录可见") page.get_by_role("button", name="版本管理").click() page.wait_for_timeout(500) first_version = page.locator(".el-drawer .el-table tbody tr").first.text_content() if "P2026" not in first_version: fail("版本记录", f"最新记录异常:{first_version}") page.keyboard.press("Escape") page.wait_for_timeout(300) step("6. 恢复种子值 10") row = page.locator(".param-table tbody tr", has_text="预付款计提比例").first row.get_by_role("button", name="修改", exact=True).click() dialog = page.locator(".el-dialog") dialog.locator("input").fill("10") dialog.get_by_role("button", name="暂存修改").click() page.get_by_role("button", name="提交变更").click() page.locator(".el-message-box").get_by_role("button", name="提交").click() wait_toast(page, "已提交") page.wait_for_timeout(400) step("7. 计算预览金标准(27 天 / 9.7‰ / 145.5)") page.get_by_role("button", name="计算预览").click() page.wait_for_timeout(600) # 多个抽屉组件常驻 DOM(隐藏未销毁),按标题过滤出预览抽屉 drawer = page.locator(".el-drawer").filter(has_text="计算预览").last # 岗位下拉默认 salesperson(v-model 初始值),无需操作 drawer.locator(".el-form-item", has_text="发货日").locator("input").click() page.keyboard.type("2025-12-15") page.keyboard.press("Enter") drawer.locator(".el-form-item", has_text="回款到账日").locator("input").click() page.keyboard.type("2026-01-10") page.keyboard.press("Enter") drawer.locator(".el-form-item", has_text="销售额").locator("input").fill("100000") drawer.locator(".el-form-item", has_text="毛利润额").locator("input").fill("45000") drawer.locator(".el-form-item", has_text="本笔回款").locator("input").fill("60000") drawer.get_by_role("button", name="开始试算").click() page.wait_for_timeout(900) result_text = drawer.locator(".preview-result").text_content() for expected in ["27 天", "145.5", "97/10000"]: if expected not in result_text: fail("预览金标准", f"结果缺少 {expected}:{result_text[:200]}") except E2EFailure as exc: failures.append(str(exc)) page.screenshot(path="e2e/failure.png") except Exception as exc: # noqa: BLE001 import traceback traceback.print_exc() failures.append(f"未预期异常:{exc}") page.screenshot(path="e2e/failure.png") finally: browser.close() if failures: print(f"✗ {failures[0]}") if console_errors: print(f" 控制台错误(最近 3 条):{console_errors[-3:]}") return 1 print("✓ 计提参数管理端到端:7 步全部通过(目录/待提交/提交/生效/版本/恢复/预览金标准)") if console_errors: print(f" (控制台非致命消息 {len(console_errors)} 条,见上方日志)") return 0 if __name__ == "__main__": raise SystemExit(main())