PayrollManagementSystem/frontend/e2e/param_management.py

146 lines
6.3 KiB
Python
Raw Normal View History

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