PayrollManagementSystem/frontend/e2e/param_management.py
liuwenxin a2f9a58de5 feat(前端): 配套授权、监控与同步进度页面
- 角色授权:权限矩阵抽屉与角色创建,按模块分组勾选
- 系统监控:总览、趋势、接口与事件页,15 秒自动刷新,
  请求可中断、窗口切换暂停,详情抽屉支持导出
- T+ 同步:同步进度条组件与工作台状态拆分
- 工资:试用期面板、产品提取弹窗与无权限占位页
- 路由权限:按权限码控制菜单与页面可达性

影响范围:前端全部页面
验证:随本次后端联调本地人工核对,e2e 脚本入库待跑
2026-11-03 11:21:19 +08:00

146 lines
6.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""计提参数管理端到端测试(需要容器、后端、前端都在运行)。
覆盖链路(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())