- 기준지정 시점 · 종점 목록 → 「지점 목록」 하나 · [+ 지점] · 지점마다 차례 색 여섯 돌림(줄 왼 띠 · 지도 이름표 바탕)
- 저장 꼴 plan_base_json {epsg, points} · 옛 starts + ends · start · end 는 읽을 때 이어 붙임(옮김 없음) · 상한 40
- 노선분석 지점 = 핀 + 「지점 N」 · 기준지정과 같은 색 · 겹 목록 맨 끝(늘 맨 위) · 지점 누름 = 새 본선(No.0 = 그 지점) · 선 놓인 지점 = 갈래
- 공용 카카오 지도 = 휠 설정 방향 한 단(마우스 자리 고정) · 가운데 끌기 옮김 — 기준지정 · 지형 범위 창 · B08 이정표 같이
- 시험: 529-3 · 530-2 새 꼴 · 585-1 새 지킴 시험 · 낡은 B08 가짜 카카오(바탕 종류 · 사건 받기 없음) 맞춤
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
101 lines
3.5 KiB
Python
101 lines
3.5 KiB
Python
"""D 지형 API(PLAN 530-1 · 561-2) — 범위 = 전체 시점 · 종점(D02 정본) 상자 + 여유 · 받기 = 한 벌.
|
|
|
|
옛 분석 API 시험(GET · PUT analysis · 꺾임점 고침)은 옛 추천 엔진과 함께 걷음(PLAN 562-2) ·
|
|
노선 정본 시험 = `test_530_2_plan_analyze.py` · 지형 셈 시험 = `test_530_1_plan_terrain.py`.
|
|
|
|
./venv/Scripts/python.exe -m pytest resources/tester/test_530_2_plan_router.py -q
|
|
"""
|
|
|
|
import asyncio
|
|
import json
|
|
from contextlib import asynccontextmanager
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
|
|
from D03_PlanAnalysis import D03_PlanAnalysis_Router as router_mod
|
|
|
|
PID = "12953f5a-5ba1-42ad-a427-8ac857a58bc2"
|
|
P0, P2 = (0.0, 0.0), (900.0, 400.0)
|
|
URL = f"/api/projects/{PID}/plan/terrain"
|
|
|
|
|
|
class _Pool:
|
|
@asynccontextmanager
|
|
async def acquire(self):
|
|
yield None
|
|
|
|
|
|
@pytest.fixture
|
|
def client(tmp_path, monkeypatch):
|
|
plan = {
|
|
"epsg": 5186,
|
|
"points": [
|
|
{"lon": 0, "lat": 0, "x": P0[0], "y": P0[1]},
|
|
{"lon": 0, "lat": 0, "x": P2[0], "y": P2[1]},
|
|
],
|
|
}
|
|
|
|
async def load_base(project_id):
|
|
return plan
|
|
|
|
async def stored(connection, project_id):
|
|
return "1/3/p"
|
|
|
|
monkeypatch.setattr(router_mod.base, "load_base", load_base)
|
|
monkeypatch.setattr(router_mod, "get_db_pool", lambda: _Pool())
|
|
monkeypatch.setattr(router_mod, "get_project_storage_relative_path", stored)
|
|
monkeypatch.setattr(router_mod, "resolve_stored_project_path", lambda s: str(tmp_path))
|
|
app = FastAPI()
|
|
app.include_router(router_mod.router)
|
|
test = TestClient(app)
|
|
test.plan = plan
|
|
return test
|
|
|
|
|
|
def test_extent_uses_whole_ends(client) -> None:
|
|
got = client.get(f"{URL}/extent?margin_m=400").json()
|
|
m = 400.0
|
|
assert got["margin_m"] == m and got["have"] is None and got["covered"] is False
|
|
# 지점 모두(D02 정본) — 연도 구간 아님
|
|
assert got["box_m"] == [P0[0] - m, P0[1] - m, P2[0] + m, P2[1] + m]
|
|
extra = client.get(f"{URL}/extent", params={"extra": json.dumps([[2000, 0]])}).json()
|
|
assert extra["box_m"][2] == 2000 + extra["margin_m"]
|
|
assert client.get(f"{URL}/extent", params={"extra": "[1]"}).status_code == 400
|
|
client.plan["points"] = [] # 지점 빔 — 1단계로
|
|
assert client.get(f"{URL}/extent").status_code == 400
|
|
|
|
|
|
def test_post_runs_one_set(client, monkeypatch) -> None:
|
|
calls: list = []
|
|
saved: list = []
|
|
works: list = []
|
|
|
|
def ensure(root, points, epsg, margin_m, report):
|
|
calls.append((points, epsg, margin_m))
|
|
return {"sheets": {"downloaded": ["1"]}, "models": [{"model_file_path": "m"}]}
|
|
|
|
async def save(project_id, models, epsg):
|
|
saved.append((models, epsg))
|
|
|
|
def start(project_id, kind, work):
|
|
works.append(work)
|
|
return {"status": "accepted", "kind": kind}
|
|
|
|
def post(body):
|
|
res = client.post(URL, json=body)
|
|
asyncio.run(works.pop()(lambda percent, message: None))
|
|
return res
|
|
|
|
monkeypatch.setattr(router_mod.terrain, "ensure_plan_terrain", ensure)
|
|
monkeypatch.setattr(router_mod, "_save_models", save)
|
|
monkeypatch.setattr(router_mod, "_start_job", start)
|
|
res = post({"margin_m": 500, "extra": [[5, 6]]})
|
|
assert res.json() == {"status": "accepted", "kind": "terrain"}
|
|
assert calls == [([P0, P2, (5.0, 6.0)], 5186, 500.0)]
|
|
assert saved == [([{"model_file_path": "m"}], 5186)]
|
|
# 옛 화면 꼴(points 몸) — 여유 처음 값 · 전체 시점 · 종점
|
|
post({"points": []})
|
|
assert calls[-1] == ([P0, P2], 5186, None)
|