121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import threading
|
|
import unittest
|
|
from contextlib import contextmanager
|
|
|
|
from playwright.async_api import async_playwright
|
|
from werkzeug.serving import make_server
|
|
|
|
from topology_api.app import create_app
|
|
|
|
|
|
@contextmanager
|
|
def topology_server():
|
|
app = create_app()
|
|
app.config.update(TESTING=True)
|
|
server = make_server("127.0.0.1", 0, app, threaded=True)
|
|
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
|
thread.start()
|
|
try:
|
|
port = server.socket.getsockname()[1]
|
|
yield f"http://127.0.0.1:{port}"
|
|
finally:
|
|
server.shutdown()
|
|
server.server_close()
|
|
thread.join(timeout=2)
|
|
|
|
|
|
class GuanghanTopologyE2ETests(unittest.TestCase):
|
|
def test_historical_graph_and_ghc05_rendering(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}
|
|
)
|
|
console_errors: list[str] = []
|
|
page.on(
|
|
"console",
|
|
lambda msg: (
|
|
console_errors.append(msg.text)
|
|
if msg.type == "error"
|
|
else None
|
|
),
|
|
)
|
|
|
|
async def open_mission(code: str) -> None:
|
|
await page.goto(
|
|
f"{base_url}/guanghan_topology_demo.html"
|
|
f"?mission={code}",
|
|
wait_until="networkidle",
|
|
)
|
|
await page.wait_for_function(
|
|
"""code => (
|
|
document.querySelector('#page-subtitle')
|
|
?.textContent.startsWith(code + ' ·')
|
|
)""",
|
|
arg=code,
|
|
)
|
|
|
|
await open_mission("BL-01")
|
|
self.assertEqual(
|
|
await page.locator(".topology-node").count(), 1
|
|
)
|
|
self.assertEqual(
|
|
await page.locator(".connection").count(), 0
|
|
)
|
|
self.assertEqual(await page.locator(".radiator").count(), 0)
|
|
|
|
await open_mission("GHC-01")
|
|
self.assertEqual(
|
|
await page.locator(".topology-node").count(), 2
|
|
)
|
|
self.assertEqual(
|
|
await page.locator(".connection").count(), 0
|
|
)
|
|
|
|
await open_mission("GHC-05")
|
|
self.assertEqual(
|
|
await page.locator(".topology-node").count(), 14
|
|
)
|
|
self.assertEqual(
|
|
await page.locator(".connection.pressurized").count(), 2
|
|
)
|
|
self.assertEqual(await page.locator(".radiator").count(), 4)
|
|
strokes = await page.locator(
|
|
".connection.pressurized"
|
|
).evaluate_all(
|
|
"(els) => els.map((el) => getComputedStyle(el).stroke)"
|
|
)
|
|
self.assertEqual(
|
|
strokes,
|
|
["rgb(81, 232, 156)", "rgb(81, 232, 156)"],
|
|
)
|
|
|
|
overflows = await page.locator(
|
|
".topology-node"
|
|
).evaluate_all(
|
|
"""nodes => nodes.flatMap(node => {
|
|
const rect = node.querySelector('rect').getBBox();
|
|
return [...node.querySelectorAll('text')]
|
|
.map(text => ({text: text.textContent,
|
|
box: text.getBBox()}))
|
|
.filter(item =>
|
|
item.box.x < rect.x ||
|
|
item.box.x + item.box.width > rect.x + rect.width
|
|
);
|
|
})"""
|
|
)
|
|
self.assertEqual(overflows, [])
|
|
self.assertEqual(console_errors, [])
|
|
await browser.close()
|
|
|
|
with topology_server() as base_url:
|
|
asyncio.run(scenario(base_url))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|