141 lines
6.2 KiB
Python
141 lines
6.2 KiB
Python
import os
|
|
from pathlib import Path
|
|
from urllib.parse import urlparse
|
|
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
|
|
FRONTEND_URL = "http://localhost"
|
|
BACKEND_URL = os.environ.get("DENSE_PLAN_BACKEND_URL", "http://127.0.0.1:8080")
|
|
TEST_USERNAME = os.environ.get("DENSE_PLAN_USERNAME")
|
|
TEST_PASSWORD = os.environ.get("DENSE_PLAN_PASSWORD")
|
|
SCREENSHOT_PATH = Path(
|
|
os.environ.get(
|
|
"DENSE_PLAN_SCREENSHOT",
|
|
r"C:\Users\13623\.codex\visualizations\2026\07\14\019f5e36-a2f0-7751-86cc-3d8ac317f956\dense-cargo-space-plan.png",
|
|
)
|
|
)
|
|
|
|
if not TEST_USERNAME or not TEST_PASSWORD:
|
|
raise RuntimeError("请通过 DENSE_PLAN_USERNAME 和 DENSE_PLAN_PASSWORD 提供测试账号")
|
|
|
|
|
|
def choose_warehouse(page, warehouse_name):
|
|
warehouse_field = page.locator(".el-form-item").filter(has_text="仓库").first
|
|
warehouse_field.locator(".el-select").click()
|
|
page.locator(".el-select-dropdown:visible .el-select-dropdown__item").filter(
|
|
has_text=warehouse_name
|
|
).click()
|
|
|
|
|
|
def assert_no_internal_overflow(page):
|
|
for selector in (".dense-map__viewport", ".dense-grid"):
|
|
metrics = page.locator(selector).evaluate(
|
|
"node => ({ scrollWidth: node.scrollWidth, clientWidth: node.clientWidth, "
|
|
"scrollHeight: node.scrollHeight, clientHeight: node.clientHeight })"
|
|
)
|
|
assert metrics["scrollWidth"] <= metrics["clientWidth"] + 1, (selector, metrics)
|
|
assert metrics["scrollHeight"] <= metrics["clientHeight"] + 1, (selector, metrics)
|
|
|
|
|
|
with sync_playwright() as playwright:
|
|
browser = playwright.chromium.launch(
|
|
headless=True,
|
|
executable_path=r"C:\Program Files\Google\Chrome\Application\chrome.exe",
|
|
)
|
|
context = browser.new_context(viewport={"width": 1500, "height": 1050})
|
|
page = context.new_page()
|
|
console_errors = []
|
|
page.on("console", lambda message: console_errors.append(message.text) if message.type == "error" else None)
|
|
|
|
login_response = page.request.post(
|
|
f"{BACKEND_URL}/login",
|
|
data={"username": TEST_USERNAME, "password": TEST_PASSWORD, "code": "", "uuid": ""},
|
|
)
|
|
login_data = login_response.json()
|
|
assert login_data.get("code") == 200, login_data
|
|
token = login_data["token"]
|
|
context.add_cookies(
|
|
[{"name": "Admin-Token", "value": token, "url": FRONTEND_URL}]
|
|
)
|
|
|
|
def route_backend(route):
|
|
request = route.request
|
|
parsed = urlparse(request.url)
|
|
backend_path = parsed.path.removeprefix("/dev-api")
|
|
target_url = f"{BACKEND_URL}{backend_path}"
|
|
if parsed.query:
|
|
target_url += f"?{parsed.query}"
|
|
response = page.request.fetch(
|
|
target_url,
|
|
method=request.method,
|
|
headers=request.headers,
|
|
data=request.post_data,
|
|
)
|
|
route.fulfill(response=response)
|
|
|
|
page.route("**/dev-api/**", route_backend)
|
|
page.goto(f"{FRONTEND_URL}/kpi/planKpi")
|
|
page.wait_for_load_state("networkidle")
|
|
|
|
choose_warehouse(page, "密集库")
|
|
dense_map = page.get_by_test_id("dense-cargo-space-map")
|
|
dense_map.wait_for(state="visible")
|
|
page.wait_for_function(
|
|
"document.querySelectorAll('[data-testid=dense-location]').length === 259"
|
|
)
|
|
|
|
floor_one_count = page.get_by_test_id("dense-location").count()
|
|
mother_count = page.locator('[data-testid="dense-location"][data-status="9"]').count()
|
|
lift_count = page.locator('[data-testid="dense-location"][data-status="7"]').count()
|
|
conveyor_count = page.locator('[data-testid="dense-location"][data-status="8"]').count()
|
|
charging_count = page.locator('[data-testid="dense-location"][data-status="10"]').count()
|
|
assert (floor_one_count, mother_count, lift_count, conveyor_count, charging_count) == (259, 49, 2, 2, 1)
|
|
assert page.get_by_text("充电桩", exact=True).count() >= 1
|
|
assert page.locator(".axis-label--column").count() == 24
|
|
assert page.locator(".axis-label--column", has_text="25").count() == 0
|
|
assert page.locator(".search-box").get_by_test_id("floor-switch").count() == 1
|
|
assert page.locator(".search-box").get_by_test_id("dense-refresh").count() == 1
|
|
assert page.get_by_text("密集库模式:按层展示完整平面坐标", exact=True).count() == 0
|
|
assert page.get_by_text("密集库货位平面图", exact=True).count() == 0
|
|
assert_no_internal_overflow(page)
|
|
assert page.locator('[data-testid="dense-location"][data-platoon="7"][data-column="13"]').count() == 1
|
|
assert page.locator('[data-testid="dense-location"][data-platoon="1"][data-column="13"]').count() == 1
|
|
assert page.locator('[data-testid="dense-location"][data-platoon="13"][data-column="13"]').count() == 1
|
|
page.locator('[data-testid="dense-location"][data-platoon="1"][data-column="1"]').click()
|
|
assert page.get_by_text("货区 A", exact=True).count() == 1
|
|
assert page.get_by_text("区域 Z01", exact=True).count() == 0
|
|
|
|
page.get_by_test_id("floor-switch").get_by_text("2层", exact=True).click()
|
|
page.wait_for_function(
|
|
"Array.from(document.querySelectorAll('[data-testid=dense-location]')).every(node => node.textContent.trim().endsWith('02'))"
|
|
)
|
|
floor_two_count = page.get_by_test_id("dense-location").count()
|
|
assert floor_two_count == 259
|
|
assert page.locator('[data-testid="dense-location"][data-status="10"]').count() == 1
|
|
|
|
page.set_viewport_size({"width": 1280, "height": 800})
|
|
page.wait_for_timeout(300)
|
|
assert_no_internal_overflow(page)
|
|
|
|
SCREENSHOT_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
dense_map.screenshot(path=str(SCREENSHOT_PATH))
|
|
|
|
choose_warehouse(page, "托盘库1")
|
|
page.locator(".chart-container--normal").wait_for(state="visible")
|
|
page.locator(".chart-container--normal canvas").first.wait_for(state="visible")
|
|
assert page.get_by_test_id("dense-cargo-space-map").count() == 0
|
|
|
|
relevant_errors = [
|
|
error for error in console_errors
|
|
if "favicon" not in error.lower() and "sockjs" not in error.lower()
|
|
]
|
|
assert not relevant_errors, relevant_errors
|
|
print(
|
|
"dense-plan-ok "
|
|
f"floor1={floor_one_count} floor2={floor_two_count} "
|
|
f"mother={mother_count} lift={lift_count} conveyor={conveyor_count} charging={charging_count} "
|
|
"legacy-chart=visible console-errors=0"
|
|
)
|
|
browser.close()
|