Files
Aislo/resources/tester/test_design_page_single.py
T
eomsangdonandClaude Opus 5.5 54cc970746 fix(b05,b06): 종단도 알약 고름 · 풂 — 측점 없는 알약 = 측점선 안 켬 · B06 다시 누름 = 풀기 한 길 (284)
- 측점 있음 = 제 측점을 심는 알약(272 한 벌 — A군 · C · D 구간형 · 관은 물넘이포장 뺌) · 그 밖 알약은 같은 자리 · 근처 측점선을 짝으로 켜지 않음(plantsStation · stationIdAtStructure)
- B06 알약 다시 누름 = Esc 와 같은 풀기 한 길(카드 · 폼 · 알약 · 범위 테두리) — 옛 처리는 풂 신호를 버림
- B06 측점 없는 구조물 고름 = 노면공처럼 카드 안 고름 · 스크롤만 · 물넘이포장 알약 = 그 관 폼 · 알약 · 고름 값에 알약 id(selectPipeAt)
- B05 물넘이포장 알약 = 고름 값에 알약 id(같은 m 일반 측점선 안 켬)
- 시험: test_284_1 새로 · 옛 시험 글 대조 · 표지 카드 기대값(None) · 헬퍼 stub(진짜 plantsStation)
- 기준점 = 태그 base-284-pill-before(282e9fcfc) · 되돌리기 = 이 커밋 git revert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C6BNBFXFndbqYxu6sZuknK
2026-10-12 19:52:13 +09:00

116 lines
5.9 KiB
Python

# -*- coding: utf-8 -*-
"""한 페이지 뼈대(계획서 24-3a) · 겹친 알약(24-6b) 회귀검증.
주소 둘(`#/b05-profile` · `#/b06-section`)이 같은 페이지(`A00_Common/design/design_page.ts`)를
열고, 같은 페이지 안 이동은 다시 만들지 않고 보기만 바꾸는지, 떠날 때 3D(WebGL 문맥) ·
종단도 · 횡단을 정리하는지, 숨긴 3D 는 그리기 루프를 멈추는지, 창에 건 키 듣기를 떼는지 본다.
화면 수치(문맥 수 · 루프 · 같은 노드 · 전환 시간)는 ORCA 로 잰다 — 여기서는 길이 끊기지 않게 잠근다.
"""
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent.parent
def _read(relative: str) -> str:
return (ROOT / relative).read_text(encoding="utf-8")
def test_주소_둘이_같은_페이지():
router = _read("A00_Common/router.ts")
assert router.count('(await import("./design/design_page")).renderDesignPage') == 2
assert "export function showWithinPage(" in router
# 다른 페이지로 떠나면 정리 · 늦게 끝난 옛 렌더는 버림
assert "mounted?.dispose();" in router
assert "if (page && seq !== renderSeq) page.dispose();" in router
def test_같은_페이지면_셸도_다시_안_그림():
main = _read("A00_Common/main.ts")
within = main.index("showWithinPage(currentRoute())")
assert within < main.index("renderShell(appRoot")
assert "if (within) return;" in main
def test_보기_약속_가운데만():
"""끝 모습(24-3b) — 보기는 가운데 위 칸만 채우고 좌측 패널 · 단추 · 종단도는 한 벌을 쓴다."""
page = _read("A00_Common/design/design_page.ts")
assert "export interface DesignPageView" in page
assert "mount?: (root" not in page # 보기가 틀을 통째로 그리던 중간 길은 걷음
assert "mountCenter: (" in page and "shared: DesignPageShared" in page
assert 'import("./design_view_profile")).mountProfileView' in page
assert 'import("./design_view_cross")).mountCrossView' in page
for hook in ("onShow:", "onHide:", "onDispose:"):
assert hook in page
# 보기는 처음 보일 때 한 번만 만든다 — 있으면 보이기만.
assert "if (slot) {\n slot.show();" in page
def test_페이지가_숨김_떠남을_건다():
life = _read("B05_Profile/B05_Profile_UI_Page_Life.ts")
assert "deps.viewer.setActive(false)" in life and "deps.viewer.dispose()" in life
assert "bindProfileViewLife(host," in _read("A00_Common/design/design_view_profile.ts")
cross = _read("A00_Common/design/design_view_cross.ts")
assert "sectionView.dispose();" in cross[cross.index("host.onDispose(") :]
# 종단도는 한 벌 — 보기가 숨어도 그대로 두고, 페이지를 떠날 때 한 번 정리한다.
assert "shared.profile?.dispose();" in _read("A00_Common/design/design_page.ts")
def test_3D_멈춤과_문맥_놓기():
viewer = _read("B05_Profile/B05_Profile_UI_Viewer.ts")
assert "setActive(active)" in viewer
assert "renderer.forceContextLoss();" in viewer
# 보관 지형은 다음 뷰어가 쓴다 — 떠날 때 버리지 않는다.
assert "if (terrain !== cachedTerrain.object) disposeObject(terrain);" in viewer
assert len(viewer.splitlines()) <= 700
def test_창_키_듣기를_뗌():
tools = _read("B05_Profile/B05_Profile_UI_Profile_Panel_Tools.ts")
assert 'window.removeEventListener("keydown", onKeyDown);' in tools
assert 'window.addEventListener("keydown", (event)' not in tools
profile = _read("A00_Common/design/design_profile.ts")
assert "setListening(false);" in profile # dispose
pick = _read("B05_Profile/B05_Profile_UI_Viewer_Structure_Pick.ts")
assert "setListening(on)" in pick
def test_겹친_알약은_누른_것을_그대로():
profile = _read("A00_Common/design/design_profile.ts")
assert re.search(r"structureIdKeeping\(\s*stationId,\s*selectedStructureId", profile)
# 판정은 `_Profile_Structures` 로 옮김 — 비정규 측점 짝 · 규칙 측점(B06 카드) 기준점(53-2)
rule = _read("B05_Profile/B05_Profile_UI_Profile_Structures.ts")
assert "stationIdAtStructure(selectedId, stations, structures, types) === stationId" in rule
assert "Math.abs(structureAnchorM(selected) - at) < SAME_CHAINAGE_M" in rule
def test_진행_단계_두_칸이_보기를_따라감():
"""종단설계 · 횡단설계 두 칸은 같은 페이지 — 누르면 주소만 바꿔 보기만 바뀐다(계획서 24-3b)."""
page = _read("A00_Common/design/design_page.ts")
assert "const VIEW_STEP: Record<DesignView, number> = { profile: 2, cross: 3 };" in page
assert "layout?.setActiveStep(VIEW_STEP[view]);" in page
assert "layout?.setTitle(" in page
click = page[page.index("onStepClick: (stepIndex) => {") :][:260]
assert "if (designViewOf(route)) navigateTo(route);" in click
layout = _read("ui_template/ui_template_workflow_layout.ts")
assert "setActiveStep: (stepIndex) =>" in layout and "setTitle: (title) =>" in layout
def test_초기화_계획노선_편집은_다시_세움():
"""[초기화] · 계획노선 편집 [확인] = 새 초기값 — 옛 캐시를 다 버리고 페이지를 통째로 다시 읽는다(PLAN 77)."""
reset = _read("A00_Common/design/design_reset.ts")
assert "clearDrafts(projectId);" in reset and "clearResults(projectId);" in reset
assert "location.reload()" in reset
assert "openRouteEditModal(activeProjectId, () => location.reload()" in _read(
"A00_Common/design/design_view_profile.ts"
)
def test_종단_보기_확정은_횡단_보기를_숨긴_채_세움():
page = _read("A00_Common/design/design_page.ts")
assert "ensureView: (view) => (slots.get(view) ?? mountView(view, false)).ready," in page
cross = _read("A00_Common/design/design_view_cross.ts")
# 숨긴 채 섰으면 한 벌 폼은 종단 보기 몫 — 보일 때 싣는다.
assert "if (host.visible()) void structuresPanel.load()" in cross