# -*- coding: utf-8 -*- """설계 가게 한 곳 · 저장 한 줄기(계획서 24-2a) 회귀검증. - 가게(`design_store`) — 밑은 등록 키 · 같은 칸이면 어느 가게든 같은 값 · 듣는 쪽. - 계획고 가게 한 벌 — B05 종단 패널 · B06 계획선 편집이 같은 벌을 씀(옛 두 가게 덮어쓰기 흠). - 저장 한 줄기(`saveDesign`) — 관 → 구조물 → 계획고 → 암거 옵션 → 오르막 → 횡단 · 관 · 구조물 · 계획고는 실패해도 다음 차례로. Node 헬퍼(`helper_design_store_save.cjs`)가 TS 를 트랜스파일해 돌린다. """ import json import os import subprocess import pytest HERE = os.path.dirname(os.path.abspath(__file__)) @pytest.fixture(scope="module") def out(): proc = subprocess.run( ["node", os.path.join(HERE, "helper_design_store_save.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_가게는_등록_키_밑_같은_칸은_같은_값(out): assert out["pipesShared"] == [{"chainage_m": 10, "source": "user"}] assert out["pipesKey"] == ["aislo:draft:pipes:p1"] assert out["heard"] == [1], "끊은 뒤에는 안 불려야 함" assert out["otherProject"] is None assert out["noRoute"] is None assert out["selection"] == {"chainageM": 12.5, "structureId": "s-1"} def test_계획고_가게_한_벌(out): assert out["b05SeesB06"] == {"20.000": 0.5} assert out["b05Dirty"] is True assert out["afterBoth"] == {"20.000": 0.5, "60.000": -0.2} assert out["draft"] == out["afterBoth"] == out["pending"] assert out["rebuiltSeenByB06"] == {"20.000": 0.1} def test_저장_차례(out): assert out["order"] == [ "route", "pipes", "structures", "alignment", "culvertOptions", "uphill", "cross", ] # 346-3 노선 먼저 assert out["saveOk"] is True assert out["saveCalls"] == [ "overlay:on", "prepare", "pipes", "pipes:screen", "structures", 'alignment:7:{"20.000":0.1}', "culvert:aislo:draft:culvertopt:p1:7", "uphill", "cross:false", "done:false", "overlay:off", ] assert out["afterSave"] == {"dirty": False, "draft": None} def test_구조물_실패는_알리고_넘어감_확정_노선없음(out): calls = out["tolerant"] assert "toast:error" in calls assert calls.index("structures") < calls.index("toast:error") < calls.index("uphill:screen") assert "uphill" not in calls, "보기 몫이 기본 창구를 갈음" assert calls[-2:] == ["cross:true", "overlay:off"] assert "failed" not in calls assert out["noRouteSave"] is False and out["noRouteCalls"] == [] def test_초기화는_초안과_한_벌을_버림(out): assert out["cleared"] == {"draft": None, "pending": None} def test_노선이_바뀌면_노선_먼저_뒤_차례는_새_노선(out): """346-3 — 노선 초안이 있으면 맨 앞 · 관 · 구조물 기본 창구 · 계획고 초안(옛 노선 7 칸)을 새 노선 9 로 · 화면 몫 일(옛 노선 판)은 건너뜀 · 횡단 초안 넘김(측점 열쇠) · 결과 한 줄 · 다시 세움.""" assert out["routeOk"] is True assert out["routeCalls"] == [ "overlay:on", "prepare", "route", "pipes", "structures", 'alignment:9:{"30.000":0.2}', "culvert:aislo:draft:culvertopt:p1:7", "uphill", "carry:7->9", "summary:9:2", "toast:info", "done:false", "rebuild", "overlay:off", ] assert "pipes:screen" not in out["routeCalls"] and "alignment:screen" not in out["routeCalls"] assert "cross:false" not in out["routeCalls"] # 옛 노선 횡단 본문 대신 넘김 def test_노선이_그대로면_안_보냄(out): assert "route" not in out["saveCalls"] def test_노선_저장_실패는_멈추고_초안_남음(out): assert out["routeFailOk"] is False assert out["routeFailCalls"] == ["overlay:on", "route", "failed", "overlay:off"] assert out["routeFailDraft"] == {"50.000": 0.3} # 계획고 초안 그대로 def test_확정_중_노선이_바뀌면_다시_세우고_확정은_다시(out): calls = out["routeConfirmCalls"] assert calls[1] == "route" and calls[-2:] == ["rebuild", "overlay:off"] assert "done:true" not in calls and "cross:true" not in calls def test_노선_초안_칸_계획고가_새_노선으로(out): """346-3 덧 — 노선 초안 동안 계획고는 노선 0 칸(sub7) · 노선 저장 뒤 그 칸이 새 노선 9 로 · 0 · 7 칸 다 비움.""" assert out["draftRouteCalls"] == ['alignment:9:{"35.000":0.4}'] assert out["draftRouteLeft"] == {"draft": None, "old": None} design = os.path.join(HERE, "..", "..", "A00_Common", "design") with open(os.path.join(design, "design_pipeline_page.ts"), encoding="utf-8") as f: pipeline = f.read() with open(os.path.join(design, "design_save.ts"), encoding="utf-8") as f: save = f.read() assert "const DRAFT_ROUTE_ID = 0;" in save if "export const DRAFT_ROUTE_ID" in pipeline: # 합친 뒤 — 두 값이 같아야 함 assert "export const DRAFT_ROUTE_ID = 0;" in pipeline