fix(505-4 B05 작은 흠 둘): 구조물 고른 채 새로 고침 = 횡단 뜸 콜백 한 박자 뒤 그림(TDZ) · 관경 빈칸 = 빈 선택지(안 채움)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -124,6 +124,10 @@ export function createSpecForm(links: SpecLinks | null, hooks: SpecFormHooks = {
|
||||
return slot;
|
||||
};
|
||||
|
||||
/** 관경 빈칸 = 빈 보기 그대로 — 기본값 1000 을 몰래 채우지 않음(505-4 · 295). */
|
||||
const blankKept = (c: SpecContainer, item: SpecItem): boolean =>
|
||||
spec?.typeId === "pipe" && c.id === "pipe" && item.id === "diameter";
|
||||
|
||||
const control = (
|
||||
c: SpecContainer,
|
||||
item: SpecItem,
|
||||
@@ -140,7 +144,7 @@ export function createSpecForm(links: SpecLinks | null, hooks: SpecFormHooks = {
|
||||
const blank = !tag ? "" : name ? `${name} (${tag})` : tag;
|
||||
// 필수 상자 = 빈 보기 없음(54-43) · 선택 상자 빈 보기 = 빈 글
|
||||
select.replaceChildren(
|
||||
...(c.required && !tag ? [] : [new Option(blank, "")]),
|
||||
...(c.required && !tag && !blankKept(c, item) ? [] : [new Option(blank, "")]),
|
||||
...choices.map((ch) => new Option(choiceLabel(c, item, ch, names), ch.value)),
|
||||
);
|
||||
// 선택지 밖 옛 값은 그 값만 남겨 보임(지운 값을 몰래 바꾸지 않음)
|
||||
@@ -223,6 +227,7 @@ export function createSpecForm(links: SpecLinks | null, hooks: SpecFormHooks = {
|
||||
for (const item of c.items) {
|
||||
if (item.kind !== "select" || values[item.id] || (item.by && !branchOf(item, values)))
|
||||
continue;
|
||||
if (blankKept(c, item)) continue;
|
||||
const choices = choicesOf(item, values);
|
||||
const key = branchOf(item, values)?.key;
|
||||
const wanted = String((key ? defaults[key] : undefined) ?? item.default ?? "");
|
||||
|
||||
@@ -191,7 +191,8 @@ export async function mountRouteEditor(
|
||||
station_interval_m: stationIntervalM,
|
||||
station_snap: stationSnap,
|
||||
}),
|
||||
onShown: () => draw(), // 횡단이 뜨면 그 측점 반폭 선을 그린다.
|
||||
// 횡단이 뜨면 그 측점 반폭 선을 그린다 — 새로 고침 뒤 고른 측점은 만드는 도중 불려 아래 선언이 아직이라 한 박자 뒤에(505-4).
|
||||
onShown: () => queueMicrotask(draw),
|
||||
});
|
||||
/** 구간 재기 — 계획·예상 노선 위 두 점. 셈·서버 묻기는 `_Measure` 몫(계획서 0-9 ⑤). */
|
||||
const measure = createMeasureTool({
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
"""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]
|
||||
BASE = "http://localhost:5179"
|
||||
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()
|
||||
Reference in New Issue
Block a user