fix(topology): repair controls navigation and details

This commit is contained in:
2026-07-09 22:08:42 +08:00
parent 6ff18623e0
commit 5a8a04c440
5 changed files with 225 additions and 28 deletions
+8
View File
@@ -40,6 +40,14 @@ class GuanghanTopologySourceTests(unittest.TestCase):
self.assertIn("const API_BASE = ''", self.html)
self.assertNotIn("http://localhost:5000", self.html)
def test_controls_use_api_navigation_and_safe_text(self) -> None:
self.assertIn("/api/v1/bases/guanghan/missions", self.html)
self.assertNotIn("return ['BL-01'", self.html)
self.assertIn("popstate", self.html)
self.assertIn("Asia/Shanghai", self.html)
self.assertNotIn(".innerHTML =", self.html)
self.assertIn("replaceChildren", self.html)
if __name__ == "__main__":
unittest.main()
+104
View File
@@ -115,6 +115,110 @@ class GuanghanTopologyE2ETests(unittest.TestCase):
with topology_server() as base_url:
asyncio.run(scenario(base_url))
def test_controls_navigation_and_modal_semantics(self) -> None:
async def scenario(base_url: str) -> None:
async with async_playwright() as pw:
browser = await pw.chromium.launch(headless=True)
page = await browser.new_page(
viewport={"width": 1440, "height": 1000}
)
await page.goto(
f"{base_url}/guanghan_topology_demo.html"
"?mission=GHC-05",
wait_until="networkidle",
)
await page.wait_for_function(
"""() => document.querySelectorAll(
'.topology-node'
).length === 14"""
)
options = await page.locator(
"#mission-select option"
).evaluate_all("(items) => items.map(item => item.value)")
self.assertEqual(
options,
[
"",
"BL-01",
"GHC-01",
"JC-01",
"BL-02",
"GHC-02",
"GHC-03",
"BL-03",
"GHC-04",
"GHC-05",
],
)
core = page.locator(
'.topology-node[data-node-key="core_cabin"]'
)
await core.click()
self.assertIn(
"GHC-01",
await page.locator("#detail-mission").inner_text(),
)
await page.locator(".modal-close").click()
self.assertEqual(
await page.evaluate(
"() => document.activeElement?.dataset.nodeKey"
),
"core_cabin",
)
await page.select_option("#mission-select", "GHC-01")
await page.fill(
"#time-input",
"2025-01-02T08:00:00+08:00",
)
await page.locator("#go-btn").click()
await page.wait_for_function(
"""() => document.querySelector('#snapshot-info')
?.textContent.includes('明确时间')"""
)
self.assertTrue(
(await page.locator("#page-subtitle").inner_text())
.startswith("GHC-01 ·")
)
self.assertIn("mission=GHC-01", page.url)
self.assertIn("at=", page.url)
await page.fill("#time-input", "not-a-time")
await page.locator("#go-btn").click()
self.assertIn(
"请输入带时区的 ISO 8601 时间",
await page.locator("#error-msg").inner_text(),
)
await page.fill("#time-input", "")
await page.select_option("#mission-select", "GHC-01")
await page.locator("#go-btn").click()
await page.wait_for_function(
"""() => document.querySelector('#page-subtitle')
?.textContent.startsWith('GHC-01 ·')"""
)
await page.select_option("#mission-select", "GHC-05")
await page.locator("#go-btn").click()
await page.wait_for_function(
"""() => document.querySelector('#page-subtitle')
?.textContent.startsWith('GHC-05 ·')"""
)
await page.go_back()
await page.wait_for_function(
"""() => document.querySelector('#page-subtitle')
?.textContent.startsWith('GHC-01 ·')"""
)
self.assertEqual(
await page.locator("#mission-select").input_value(),
"GHC-01",
)
await browser.close()
with topology_server() as base_url:
asyncio.run(scenario(base_url))
if __name__ == "__main__":
unittest.main()
+19
View File
@@ -181,6 +181,25 @@ class TopologyApiQueryTests(unittest.TestCase):
},
)
def test_components_include_introduction_mission_and_time(self) -> None:
response = self.client.get(
"/api/v1/bases/guanghan/snapshot?mission=GHC-05"
)
components = {
component["key"]: component
for component in response.get_json()["components"]
}
self.assertEqual(
components["core_cabin"]["introducedMission"],
"GHC-01",
)
self.assertEqual(
datetime.fromisoformat(
components["core_cabin"]["introducedAt"]
).astimezone(timezone.utc),
datetime.fromisoformat("2024-06-16T07:23:00+00:00"),
)
if __name__ == "__main__":
unittest.main()