from __future__ import annotations import asyncio import functools import threading import unittest from contextlib import contextmanager from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path from playwright.async_api import async_playwright ROOT = Path(__file__).resolve().parents[1] @contextmanager def local_server(): handler = functools.partial(SimpleHTTPRequestHandler, directory=str(ROOT)) server = ThreadingHTTPServer(("127.0.0.1", 0), handler) thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() try: yield f"http://127.0.0.1:{server.server_port}" finally: server.shutdown() server.server_close() thread.join(timeout=2) class GuanghanTopologyE2ETests(unittest.TestCase): def test_rendered_topology_and_modal_interactions(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": 1100}) errors: list[str] = [] page.on("console", lambda msg: errors.append(msg.text) if msg.type == "error" else None) await page.goto( f"{base_url}/data/wiki/guanghan_topology_demo.html", wait_until="networkidle", ) self.assertEqual(await page.locator("[data-module]").count(), 14) self.assertEqual(await page.locator('[data-connection="pressurized"]').count(), 2) strokes = await page.locator('[data-connection="pressurized"]').evaluate_all( "(els) => els.map((el) => getComputedStyle(el).stroke)" ) self.assertEqual(strokes, ["rgb(81, 232, 156)", "rgb(81, 232, 156)"]) for forbidden in ("未来北部十字结构", "未来东部十字结构", "未来西部十字结构"): self.assertEqual(await page.get_by_text(forbidden, exact=False).count(), 0) await page.locator('[data-module="core"]').click() self.assertEqual(await page.locator("#detail-modal").count(), 1) self.assertEqual(await page.locator("#detail-modal").get_attribute("aria-hidden"), "false") self.assertEqual(await page.locator("#detail-title").inner_text(), "广寒核心舱") await page.keyboard.press("Escape") self.assertEqual(await page.locator("#detail-modal").get_attribute("aria-hidden"), "true") await page.locator('[data-module="habitat-1"]').click() self.assertIn("运输:高2.7 m", await page.locator("#detail-dimensions").inner_text()) await page.locator("#detail-modal").click(position={"x": 5, "y": 5}) self.assertEqual(await page.locator("#detail-modal").get_attribute("aria-hidden"), "true") self.assertEqual(errors, []) await browser.close() with local_server() as base_url: asyncio.run(scenario(base_url)) if __name__ == "__main__": unittest.main()