feat(javaTest): visualize source-aligned task phases
This commit is contained in:
@@ -91,17 +91,71 @@ def verify_map_interactions(page):
|
||||
page.locator("#show-move-trace").check()
|
||||
|
||||
|
||||
def verify_historical_mode(page):
|
||||
"""Run 240 tasks and inspect one real cross-floor dispatch without drawing a fake edge."""
|
||||
def select_task_with_phase(page, phase_name):
|
||||
"""Select the first visible business task that exposes the requested backend phase."""
|
||||
rows = page.locator("#history-task-body tr")
|
||||
for index in range(rows.count()):
|
||||
rows.nth(index).click()
|
||||
if page.locator("#phase-list [data-phase='%s']" % phase_name).count():
|
||||
return
|
||||
raise AssertionError("no task exposed business phase " + phase_name)
|
||||
|
||||
|
||||
def assert_no_cross_floor_route_segments(page):
|
||||
"""Verify that transfer jobs use port markers rather than fake map edges."""
|
||||
cross_floor_segments = page.evaluate("""
|
||||
async () => {
|
||||
const bootstrap = await fetch('/api/bootstrap').then(response => response.json());
|
||||
const floors = Object.fromEntries(
|
||||
bootstrap.sites.map(site => [site.siteId, Number(site.floor)]));
|
||||
return Array.from(document.querySelectorAll(
|
||||
'#dynamic-route-layer .route-segment title'))
|
||||
.map(title => title.textContent.split(' → '))
|
||||
.filter(parts => parts.length === 2
|
||||
&& floors[parts[0]] !== undefined
|
||||
&& floors[parts[1]] !== undefined
|
||||
&& floors[parts[0]] !== floors[parts[1]]);
|
||||
}
|
||||
""")
|
||||
require(not cross_floor_segments,
|
||||
"normal route layer drew cross-floor edges: " + str(cross_floor_segments))
|
||||
|
||||
|
||||
def verify_historical_mode(page, switch_raw=True):
|
||||
"""Run business replay, inspect phase/transfer paths, then verify RAW compatibility."""
|
||||
page.locator(".mode-tab[data-mode='history']").click()
|
||||
require(page.locator("#simulation-mode-business").is_checked(),
|
||||
"business replay must be the default historical mode")
|
||||
page.locator("#run-history").click()
|
||||
expect(page.locator("#history-run-state")).to_have_text(
|
||||
re.compile(r"^最近运行"), timeout=180_000
|
||||
)
|
||||
require("240" in page.locator("#task-filter-count").inner_text(),
|
||||
"historical result did not expose all 240 tasks")
|
||||
require(page.locator("#history-task-body tr").count() == 240,
|
||||
"historical task table row count is not 240")
|
||||
require(page.locator("#raw-snapshot-count").inner_text() == "240",
|
||||
"input audit did not expose 240 raw snapshots")
|
||||
require(page.locator("#business-task-count").inner_text() == "76",
|
||||
"input audit did not expose 76 business parent tasks")
|
||||
require("76" in page.locator("#task-filter-count").inner_text(),
|
||||
"business replay did not expose 76 parent tasks")
|
||||
require(page.locator("#history-task-body tr").count() == 76,
|
||||
"business replay table row count is not 76")
|
||||
|
||||
select_task_with_phase(page, "EMPTY_RETURN_TO_TARGET_FRONT")
|
||||
require(page.locator("#phase-list [data-phase]").count() >= 2,
|
||||
"business task did not expose its multi-stage route evidence")
|
||||
require(page.locator("#business-completed-at").inner_text() != "--",
|
||||
"business completion time is missing")
|
||||
require("车辆已释放" in page.locator("#vehicle-released-at").inner_text(),
|
||||
"vehicle release evidence is incomplete")
|
||||
selected_phase = page.locator(
|
||||
"#phase-list [data-phase='EMPTY_RETURN_TO_TARGET_FRONT']"
|
||||
)
|
||||
selected_phase.click()
|
||||
require(page.locator("#dynamic-route-layer .business-phase").count() > 0,
|
||||
"selected business phase did not render a same-floor route")
|
||||
require(page.locator(".map-floor-layer:not([hidden]) .map-edge").count() > 20,
|
||||
"phase selection replaced the authoritative full map")
|
||||
assert_no_cross_floor_route_segments(page)
|
||||
|
||||
transfer_rows = page.locator(
|
||||
"#history-task-body tr[data-assignment-mode='FLOOR_TRANSFER']"
|
||||
)
|
||||
@@ -132,22 +186,21 @@ def verify_historical_mode(page):
|
||||
).inner_text() == "换层完成",
|
||||
"transfer completion event did not receive a business label")
|
||||
|
||||
cross_floor_segments = page.evaluate("""
|
||||
async () => {
|
||||
const bootstrap = await fetch('/api/bootstrap').then(response => response.json());
|
||||
const floors = Object.fromEntries(
|
||||
bootstrap.sites.map(site => [site.siteId, Number(site.floor)]));
|
||||
return Array.from(document.querySelectorAll(
|
||||
'#dynamic-route-layer .route-segment title'))
|
||||
.map(title => title.textContent.split(' → '))
|
||||
.filter(parts => parts.length === 2
|
||||
&& floors[parts[0]] !== undefined
|
||||
&& floors[parts[1]] !== undefined
|
||||
&& floors[parts[0]] !== floors[parts[1]]);
|
||||
}
|
||||
""")
|
||||
require(not cross_floor_segments,
|
||||
"normal route layer drew cross-floor edges: " + str(cross_floor_segments))
|
||||
assert_no_cross_floor_route_segments(page)
|
||||
|
||||
if not switch_raw:
|
||||
return
|
||||
page.locator("label[for='simulation-mode-raw']").click()
|
||||
expect(page.locator("#task-filter-count")).to_have_text("240 条", timeout=180_000)
|
||||
require(page.locator("#history-task-body tr").count() == 240,
|
||||
"RAW compatibility replay did not expose all 240 snapshots")
|
||||
require(page.locator("#replay-mode-readout").inner_text() == "RAW 快照",
|
||||
"replay mode readout did not switch to RAW")
|
||||
require(not page.locator("#show-historical").is_disabled(),
|
||||
"RAW mode did not restore the historical path layer")
|
||||
page.locator("#history-task-body tr").first.click()
|
||||
require(page.locator("#route-difference").inner_text() != "共同 -- / 新增 -- / 历史 --",
|
||||
"RAW task did not render historical/new path difference evidence")
|
||||
|
||||
|
||||
def verify_viewport(browser, viewport, filename, run_history):
|
||||
@@ -166,7 +219,7 @@ def verify_viewport(browser, viewport, filename, run_history):
|
||||
run_point_to_point(page)
|
||||
verify_map_interactions(page)
|
||||
if run_history:
|
||||
verify_historical_mode(page)
|
||||
verify_historical_mode(page, switch_raw=viewport["width"] > 580)
|
||||
require(not horizontal_overflow(page), "page has horizontal overflow after simulation")
|
||||
page.screenshot(path=os.path.join(OUTPUT_DIR, filename), full_page=True)
|
||||
require(not errors, "browser console/page errors: " + " | ".join(errors))
|
||||
@@ -186,7 +239,7 @@ def main():
|
||||
launch_options["executable_path"] = cached_candidates[0]
|
||||
browser = playwright.chromium.launch(**launch_options)
|
||||
verify_viewport(browser, {"width": 1440, "height": 1000}, "desktop.png", True)
|
||||
verify_viewport(browser, {"width": 390, "height": 844}, "mobile.png", False)
|
||||
verify_viewport(browser, {"width": 390, "height": 844}, "mobile.png", True)
|
||||
browser.close()
|
||||
print("visualizer browser QA passed: desktop=1440x1000 mobile=390x844")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user