"""463 B05 · B06 한 페이지 — 페이지 설정 한 칸(요구 271-5 · 분석 4장 (B)). ① 종단도 기준(기울기 상한 · 최소고 강제 · 시작 측점) = 세션 초안(448) ?? 저장 노선 설정 · 빈 칸 = 좌측 패널 기본(설계속도 20 · 특수지형 · 강제 해제 · 0) · 작업임도는 20 만 · 둘 다 없으면 종단도 그대로 ② 이음 — 횡단 보기 · 종단 보기 둘 다 종단도를 그린 뒤 같은 함수 · 옛 코드 = B05 좌측 패널만 얹어 B06 새로고침에서 라벨 오프셋 · 기울기 빨강 · 강제가 B05 열기 전까지 다름 · B06 이 받은 노선은 캐시에 둠 ③ 좌측 패널 상한 = 같은 기준 함수 TS 셈은 `helper_271_profile_settings.cjs`. ./venv/Scripts/python.exe -m pytest resources/tester/test_271_profile_settings.py -q """ import json import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HELPER = Path(__file__).with_name("helper_271_profile_settings.cjs") pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules" / "typescript").is_dir(), reason="프론트엔드 의존성 미설치", ) def src(*parts: str) -> str: return ROOT.joinpath(*parts).read_text(encoding="utf-8") @pytest.fixture(scope="module") def got() -> dict: run = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", str(HELPER)], capture_output=True, text=True, encoding="utf-8", timeout=120, ) assert run.returncode == 0, run.stderr return json.loads(run.stdout) def test_초안이_저장_설정을_이김(got): assert got["nothing"] == {} assert got["saved"] == { "grade": 8, "enforce": True, "display": {"station": 3, "cumulative": 60}, } assert got["draft"] == { "grade": 12, "enforce": False, "display": {"station": 5, "cumulative": 100}, } assert got["work"] == got["draft"] assert got["draftOnly"] == { "grade": 10, "enforce": True, "display": {"station": 0, "cumulative": 0}, } def test_빈_칸은_좌측_패널_기본(got): zero = {"station": 0, "cumulative": 0} assert got["workSaved"] == {"grade": 9, "enforce": False, "display": zero} # 작업임도 30 → 20 assert got["defaults"] == {"grade": 14, "enforce": False, "display": zero} # 20 · 특수 def test_두_보기가_같은_함수로_얹음(): cross = src("B06_Section", "B06_Section_UI_Section_View_Profile.ts") render = cross[cross.index(" profile.render(") :] assert render.index("applyPageSettings(profile, id);") < render.index("lane.paint();") loader = cross[cross.index("function loadRoute(") :] loader = loader[: loader.index("\n}\n")] assert "writeRouteLatestCache(projectId, latest);" in loader assert "applyPageSettings(profile, projectId, latest);" in loader assert "enforceKnown" not in cross sections = src("A00_Common", "design", "design_view_profile_sections.ts") body = sections[sections.index(" function renderSections(") :] body = body[: body.index("\n }\n")] assert "applyPageSettings(profilePanel, projectId, state.latest ?? undefined);" in body assert "panel.gradeLimitPct()" not in body def test_좌측_패널_상한도_같은_기준(): part = src("B05_Profile", "B05_Profile_UI_Panel_Settings.ts") assert "return gradeLimitOf(currentSpeed(), terrain, parseOptional(maxGradePct));" in part def test_지표면_설정_없는_노선도_안_죽음(got): # 463 덧 — latest 에 surface_params 없음(옛 · 시험 · 막 만든 프로젝트) = 종단도 기준은 저장 설정대로 · 등고선 칸 그대로 assert got["noSurface"] == { "grade": 14, "enforce": True, "display": {"station": 0, "cumulative": 0}, } assert got["noSurfacePanel"] is None fetch = src("B05_Profile", "B05_Profile_Api_Fetch.ts") assert "latest?.surface_params.source_filter" not in fetch # [저장] 상단측 차례도 같은 꼴