"""591-1 예정노선 등록 기준점 · 주소 · 설계속도 지움(요구 452 · 453). - 좌표 → {address, region} — 지번 먼저(산 번지) · region = 「시군구 (구) 읍면」 · 도로명만 = 행정동 · 실패 = 빈 값 - B08 한 줄 주소(도로명 먼저)는 그대로 - GET /api/map/address — 출처 VWorld - 등록 몸 — 기준점 필수 · 경위도 범위 · 설계속도 칸 없음 - 행 만들기 = 기준점 칸 셋 · 설계속도 칸 안 씀 - 화면 — 지도 · 기준점 필수 · 출처 표기 · 설계속도 글 없음 """ import asyncio import json import sys from pathlib import Path import pytest from pydantic import ValidationError ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from B01_Dashboard import B01_Dashboard_Map as vmap # noqa: E402 from common_util import common_util_map_router as map_router # noqa: E402 from D01_PlanRegister import D01_PlanRegister_Router as d01 # noqa: E402 PARCEL = {"type": "parcel", "text": "경상북도 울진군 금강송면 광회리 산 47", "structure": {"level1": "경상북도", "level2": "울진군", "level3": "", "level4L": "금강송면", "level4A": ""}} # fmt: skip ROAD = {"type": "road", "text": "경기도 수원시 장안구 정조로 1", "structure": {"level2": "수원시", "level3": "장안구", "level4L": "정조로", "level4A": "파장동"}} # fmt: skip def _body(*items): return json.dumps({"response": {"status": "OK", "result": list(items)}}).encode() def test_좌표_주소_지번_먼저(monkeypatch): monkeypatch.setattr(vmap, "_fetch", lambda url, timeout=5: _body(ROAD, PARCEL)) assert vmap._place_sync(129.1, 36.95) == { "address": "경상북도 울진군 금강송면 광회리 산 47", "region": "울진군 금강송면", } assert vmap._reverse_sync(129.1, 36.95) == "경기도 수원시 장안구 정조로 1" # B08 그대로 monkeypatch.setattr(vmap, "_fetch", lambda url, timeout=5: _body(ROAD)) assert vmap._place_sync(127.0, 37.3)["region"] == "수원시 장안구 파장동" monkeypatch.setattr(vmap, "_fetch", lambda url, timeout=5: b"not json") assert vmap._place_sync(127.0, 37.3) == {"address": None, "region": None} def test_주소_길_출처(monkeypatch): async def place(lon, lat): return {"address": "주소", "region": "울진군 금강송면"} monkeypatch.setattr(map_router, "reverse_place", place) out = asyncio.run(map_router.map_address(lon=129.1, lat=36.95)) assert out == {"address": "주소", "region": "울진군 금강송면", "source": "VWorld"} def test_등록_몸_기준점_필수(): base = {"project_name": "예정", "project_year": 2026, "region": "울진"} with pytest.raises(ValidationError): d01.CreatePlanRequest(**base) with pytest.raises(ValidationError): d01.CreatePlanRequest(**base, site={"lon": 200, "lat": 36}) ok = d01.CreatePlanRequest(**base, site={"lon": 129.1, "lat": 36.95}) assert "design_speed_kph" not in d01.CreatePlanRequest.model_fields assert (ok.site.lon, ok.site.lat) == (129.1, 36.95) def test_행_만들기_기준점_칸(): src = (ROOT / "common_util" / "common_util_project_kind.py").read_text(encoding="utf-8") assert "site_lon, site_lat, site_address" in src and "design_speed_kph" not in src sql = (ROOT / "db_management" / "024_plan_site.sql").read_text(encoding="utf-8") assert "site_lon DOUBLE" in sql and "site_address VARCHAR(255)" in sql assert "SET design_speed_kph = NULL WHERE project_kind = 'PLAN'" in sql def test_화면_지도_출처(): page = (ROOT / "D01_PlanRegister" / "D01_PlanRegister_UI_Page.ts").read_text(encoding="utf-8") assert "editMap(" in page and "/map/address" in page and "DE_Reg_SiteSource" in page assert "site: { lon: at[0], lat: at[1] }" in page and "DE_Reg_SiteRequired" in page assert "DesignSpeed" not in page def test_D04_연결_설계속도_안_넘김(): # 590-1 이 씨앗 줄을 걷음 — 연결이 설계속도를 안 넘김(B05 기본 20) link = (ROOT / "D04_PlanConfirm" / "D04_PlanConfirm_Link.py").read_text(encoding="utf-8") assert "design_speed" not in link