From bf33a8a9a206e2f3a8c5e05de92695d4f74a1494 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Tue, 6 Oct 2026 00:16:37 +0900 Subject: [PATCH] =?UTF-8?q?test(B05):=20=EC=98=9B=20=EC=A2=85=EB=A5=98=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=EB=AC=BC=20=EC=A0=80=EC=9E=A5=20=EC=99=95?= =?UTF-8?q?=EB=B3=B5=20=EC=8B=9C=ED=97=98=20=E2=80=94=20=EC=88=98=20=C2=B7?= =?UTF-8?q?=20=EC=A2=85=EB=A5=98=20=C2=B7=20=EC=98=B5=EC=85=98=20=EA=B7=B8?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20(PLAN=2052-7c)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 옛 대피소 · 정차·작업장 · 차돌림곳 · 종단배수 6 · 계류사방 3(기슭막이 = pipe_points 정본 제외) = 12 건 - 저장 → 다시 열기 → 다시 저장 → 다시 열기 = 12 건 · 측점 · 옵션 같음 · 임시 storage - 랩탑_보조 7+5~8+0 대피소 = 52-7 화면 검증 seed 단계가 넣은 시험 건(memo 「52-7 옛 대피소」) · restore 단계가 원래 목록(6 건)으로 되돌림 = 데이터 잃음 아님 · 코드 원인 없음 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt --- .../tester/test_52_7c_legacy_roundtrip.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 resources/tester/test_52_7c_legacy_roundtrip.py diff --git a/resources/tester/test_52_7c_legacy_roundtrip.py b/resources/tester/test_52_7c_legacy_roundtrip.py new file mode 100644 index 000000000..e02ed795b --- /dev/null +++ b/resources/tester/test_52_7c_legacy_roundtrip.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +"""옛 종류 구조물 저장 왕복(PLAN 52-7c) — 저장 · 다시 열기 · 다시 저장 뒤에도 수 · 종류 그대로. + +옛 대피소 · 정차·작업장 · 차돌림곳(52-7 고르기 목록 뺌) · 종단배수 · 계류사방(52-8 숨김) 모두. +임시 storage(tmp_path) · 라우터 PUT/GET. +""" + +from fastapi import FastAPI +from fastapi.testclient import TestClient + +import B05_Profile.B05_Profile_Structures_Router as router_module +from B05_Profile.B05_Profile_Structures_Schema import structure_type_map + +PROJECT_ID = "52700000-0000-0000-0000-00000000007c" +URL = f"/api/projects/{PROJECT_ID}/route/structures" +LEGACY = ("refuge", "work_yard", "turnaround") + + +def _client(tmp_path, monkeypatch): + async def project_root(project_id): + return str(tmp_path / "project") + + async def invalidate(project_id): + return True + + async def route_length(project_id): + return None + + monkeypatch.setattr(router_module, "_project_root", project_root) + monkeypatch.setattr(router_module, "_invalidate_downstream", invalidate) + monkeypatch.setattr(router_module, "_route_length", route_length) + app = FastAPI() + app.include_router(router_module.router) + return TestClient(app) + + +def _record(type_, at): + options = {} + for o in type_.options: + if o.default not in (None, ""): + options[o.key] = o.default + elif o.required: + options[o.key] = o.choices[0] if o.choices else 1 + record = {"type_id": type_.type_id, "placement": type_.placement, "options": options} + if type_.placement == "interval": + record.update(chainage_m=at, start_m=at, end_m=at + 10) + else: + record["chainage_m"] = at + return record + + +def _kinds(body): + return sorted((s["type_id"], s["chainage_m"]) for s in body["structures"]) + + +def test_옛_종류_저장_왕복_수_그대로(tmp_path, monkeypatch): + types = structure_type_map() + ids = [*LEGACY, *(t for t, v in types.items() if v.group in ("B", "D") and not v.managed_by)] + assert len(ids) >= 3 + 6 + 3 # 기슭막이 = pipe_points 정본 + records = [_record(types[t], 20.0 * (i + 1)) for i, t in enumerate(ids)] + client = _client(tmp_path, monkeypatch) + + first = client.put(URL, json={"base_revision": 0, "structures": records}) + assert first.status_code == 200, first.text + opened = client.get(URL).json() + assert len(opened["structures"]) == len(ids) + want = _kinds(opened) + assert sorted(t for t, _ in want) == sorted(ids) + + # 다시 연 목록 그대로 저장 → 다시 열기 + again = client.put( + URL, json={"base_revision": opened["revision"], "structures": opened["structures"]} + ) + assert again.status_code == 200, again.text + reopened = client.get(URL).json() + assert _kinds(reopened) == want + by_id = {s["structure_id"]: s["options"] for s in opened["structures"]} + assert {s["structure_id"]: s["options"] for s in reopened["structures"]} == by_id