Files
Aislo/resources/tester/test_505_4_refresh_blank_pipe.py
T

105 lines
4.7 KiB
Python

"""PLAN 505-4 — 구조물 고른 채 새로 고침 = 평면 편집기 뜸 · 빈 관경 = 빈 선택지(값 안 채움).
글 시험 = 소스 순서 · 화면 시험 = 자기 포트(5179) Playwright 머리 없는 브라우저 · 서버가 떠 있을 때만 · 검증_sub4.
./venv/Scripts/python.exe -m pytest resources/tester/test_505_4_refresh_blank_pipe.py -q
"""
from __future__ import annotations
import json
import urllib.request
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
from helper_verify_project import own_ports # noqa: E402
BASE = own_ports()[1] # 화면 서버 = OWNERS.md 이 폴더 줄
PROJECT = "c725d747-50ae-46b0-87ce-4d4e56a53cf3" # 검증_sub4(OWNERS.md)
LIST_URL = f"{BASE}/api/projects/{PROJECT}/route/structures"
def _read(*parts: str) -> str:
return ROOT.joinpath(*parts).read_text(encoding="utf-8")
def test_횡단_뜸_콜백은_만드는_도중_안_그림() -> None:
edit = _read("B05_Profile", "B05_Profile_UI_RouteEdit.ts")
# createCrossPreview 가 고른 측점을 만들며 곧바로 부름 — draw 는 아래 선언(closed · view)이 선 뒤에
assert "onShown: () => queueMicrotask(draw)," in edit
assert "onShown: () => draw()" not in edit
assert edit.index("const crossPreview = createCrossPreview(") < edit.index(
"let closed = false;"
)
def test_관경_빈칸은_빈_보기_채움_없음() -> None:
form = _read("A00_Common", "design", "design_structure_form.ts")
assert 'spec?.typeId === "pipe" && c.id === "pipe" && item.id === "diameter"' in form
assert "c.required && !tag && !blankKept(c, item) ? [] : [new Option(blank," in form
fill = form.index("필수 상자 빈 고르기 칸 = 정의 기본값")
assert form.index("if (blankKept(c, item)) continue;", fill) < form.index(
"values[item.id] =", fill
)
def _up() -> bool:
try:
urllib.request.urlopen(BASE, timeout=3)
return True
except Exception:
return False
JS_DIAMETER = """() => [...document.querySelectorAll('select')]
.filter((s) => s.offsetParent && [...s.options].some((o) => o.value === '800'))
.map((s) => ({ value: s.value, first: s.options[0].value, count: s.options.length }))"""
JS_CANVAS = """() => {
const c = document.querySelector('.b05-routeedit__canvas');
const d = c.getContext('2d').getImageData(0, 0, c.width, c.height).data;
let n = 0;
for (let i = 3; i < d.length; i += 4) if (d[i] > 0) n += 1;
return { visible: !!c.offsetParent, painted: n };
}"""
@pytest.mark.skipif(not _up(), reason="5179 서버 없음")
def test_화면_새로_고침_편집기_뜸_빈_관경_빈_선택지() -> None:
sync = pytest.importorskip("playwright.sync_api")
cred = json.loads((ROOT / "tmp" / "aislo_cred.json").read_text(encoding="utf-8"))
with sync.sync_playwright() as play:
chrome = play.chromium.launch(channel="msedge", headless=True)
try:
ctx = chrome.new_context(viewport={"width": 1600, "height": 1000})
login = {k: cred[k] for k in ("email", "password")}
assert ctx.request.post(f"{BASE}/api/auth/login/request", data=login, timeout=60000).ok
tab = ctx.new_page()
errors: list[str] = []
tab.on("pageerror", lambda e: errors.append(str(e)))
tab.add_init_script(f"localStorage.setItem('frd_current_project_id', '{PROJECT}')")
tab.goto(f"{BASE}/#/b05-profile", wait_until="domcontentloaded")
tab.wait_for_function("() => !!window.__aisloPipeline", timeout=90000)
tab.wait_for_timeout(8000)
before = ctx.request.get(LIST_URL).text()
# 관경 빈칸 관(19+8) — 빈 선택지 · 값 안 채움
tab.locator(".b05-route__irregular-item", has_text="19+8").first.click()
tab.wait_for_timeout(3000)
if not tab.evaluate(JS_DIAMETER):
tab.get_by_text("구조물 배치", exact=True).click()
tab.wait_for_timeout(1500)
assert tab.evaluate(JS_DIAMETER) == [{"value": "", "first": "", "count": 5}]
assert ctx.request.get(LIST_URL).text() == before # 열기만 — 저장 값 그대로
# 고른 채 새로 고침 — 편집기가 뜸(전엔 `closed` 선언 전 씀으로 멈춤)
errors.clear()
tab.reload(wait_until="domcontentloaded")
tab.wait_for_function("() => !!window.__aisloPipeline", timeout=90000)
tab.wait_for_timeout(9000)
assert not [e for e in errors if "before initialization" in e], errors
canvas = tab.evaluate(JS_CANVAS)
assert canvas["visible"] and canvas["painted"] > 0
assert ctx.request.get(LIST_URL).text() == before
finally:
chrome.close()