# -*- coding: utf-8 -*- """계획노선 편집 창 — **초기노선 갈래**(계획서 20) 셈 회귀검증. 비중 슬라이더 셋은 합 100 을 지키고(하나를 옮기면 나머지가 비율대로), 서버 답은 노드 목록 꼴과 `/route/plan` 꼴(노드+곡선) 둘 다 편집값 한 벌로 펴야 한다. 비교값 · 기준값은 서버 값을 글로만 보이고, 확정 표시가 없으면 「사용자 확정 대기」를 붙인다. 마지막 초기값은 결과 통 프로젝트 칸. Node 헬퍼(`helper_b05_routeedit_initial.cjs`)가 TS 를 트랜스파일해 돌리고, 여기서 값을 판정한다. """ import json import os import subprocess import pytest HERE = os.path.dirname(os.path.abspath(__file__)) @pytest.fixture(scope="module") def results(): proc = subprocess.run( ["node", os.path.join(HERE, "helper_b05_routeedit_initial.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_비중은_늘_합_100_정수(results): for weights in results["moves"]: assert list(weights) == ["expected", "earthwork", "grade"] assert sum(weights.values()) == 100 assert all(isinstance(v, int) and 0 <= v <= 100 for v in weights.values()) def test_비중은_나머지를_지금_비율대로_나눔(results): moves = results["moves"] assert moves[0] == {"expected": 70, "earthwork": 15, "grade": 15} assert moves[1] == {"expected": 40, "earthwork": 40, "grade": 20} # 나머지가 모두 0 이면 반씩. assert moves[2] == {"expected": 60, "earthwork": 20, "grade": 20} assert moves[3] == {"expected": 0, "earthwork": 0, "grade": 100} assert moves[5]["grade"] == 0 def test_노드_목록_꼴을_편집값으로(results): snap = results["plain"]["snapshot"] assert snap["planned"] == [[0, 0], [50, 10], [100, 0]] assert snap["curveOn"] == [True, True, False] assert snap["curveRadius"] == [None, 30, None] assert snap["curveLock"] == [None, None, None] assert snap["apexLock"] == [False, False, False] assert snap["picked"] == -1 def test_노선계획_꼴도_같은_규칙으로(results): shape = results["planShape"] snap = shape["snapshot"] assert snap["planned"] == [[0, 0], [40, 30], [90, 30]] assert snap["curveOn"] == [False, True, False] assert snap["curveRadius"] == [None, 25, None] assert shape["weights"] == {"expected": 60, "earthwork": 20, "grade": 20} assert shape["metrics"] is None and shape["criteria"] is None def test_노드가_모자라면_싣지_않음(results): assert "모자랍니다" in results["tooShort"] def test_비교값과_기준값_글(results): labels = results["labels"] assert labels["follow"] == "예상노선 추종" assert labels["weighted"] == "비중 계산 60/20/20" assert labels["metrics"] == ( "연장 1,234.6m · 기울기 최대 12.3% · 평균 6.1% · 절토 1,500㎥ · 성토 900㎥" " · 기준 초과 2구간 · 이격 3.3m" ) assert "로직을 누르면" in labels["metricsNone"] assert labels["criteria"] == ( "공통 제약 종단기울기 ≤ 14.0% · 최소 R 12m · 계류 이격 ≥ 5.0m (후보 · 사용자 확정 대기)" ) assert labels["criteriaConfirmed"].endswith("5.0m") assert labels["pendingEmpty"] is True assert labels["criteriaFallback"] == ( "공통 제약 종단기울기 ≤ — · 최소 R 15m · 계류 이격 ≥ — (후보 · 사용자 확정 대기)" ) def test_서버가_적어_둔_현재_초기값(results): bases = results["bases"] assert bases["follow"] == {"logic": "follow", "weights": None} assert bases["weighted"] == { "logic": "weighted", "weights": {"expected": 70, "earthwork": 15, "grade": 15}, } assert bases["unknown"] == {"logic": "follow", "weights": None} assert bases["none"] == {"logic": "follow", "weights": None} same = results["sameAsServer"] assert same == { "earthVsFollow": False, "earthVsEarth": True, "weightedSame": True, "weightedOther": False, } def test_캐시는_결과_통_프로젝트_칸(results): assert results["keys"] == ["aislo:result:routeedit-initial:p-1"] assert results["readBack"]["logic"] == "earthwork" assert results["readBack"]["snapshot"]["planned"] == [[0, 0], [50, 10], [100, 0]] assert results["other"] is None assert results["badLogic"] is None assert results["cleared"] is None