Merge remote-tracking branch 'origin/sub_laptop_3' into main_laptop_1
This commit is contained in:
@@ -264,8 +264,10 @@ def test_화면_브라우저_캡처_없음_길찾기_뒤_자동():
|
||||
assert "캡처는 localhost" not in text, name
|
||||
state = read("B08_Quantity_UI_Milestone_State.ts")
|
||||
# 244-13 — 연결선 한 구간 [길찾기] · 거래처 쪽 구간만 자동 그림
|
||||
assert 'if (image && seg.key === "route" && paths.has(from))' in state
|
||||
assert "void autoRouteImage(projectId, from, routePaths(from));" in state
|
||||
assert (
|
||||
'if (image && seg.key === "route" && path) void autoRouteImage(projectId, from, [path]);'
|
||||
in state
|
||||
)
|
||||
assert "JSON.stringify({ lines, marks })" in state and "/image/auto?route=" in state
|
||||
assert "user_only=true" in state and "showToast(reason," in state
|
||||
route = read("B08_Quantity_UI_Milestone_Route.ts")
|
||||
|
||||
@@ -245,8 +245,8 @@ const writes = WRITES.n;
|
||||
await findSegmentKm("p1", "b1"); // 같은 km = 캐시 안 씀
|
||||
const live = liveMilestone("p1");
|
||||
console.log(JSON.stringify({{ a, b, calls: CALLS.slice(1), afterRoute, writes, again: WRITES.n,
|
||||
route: live.routes[0].legs, base: live.bases[0].legs, path: segmentPath("g"),
|
||||
routeLines: routePaths("g"), baseLines: routePaths("b1"),
|
||||
route: live.routes[0].legs, base: live.bases[0].legs, path: segmentPath("p1", "g"),
|
||||
routeLines: [segmentPath("p1", "g")], baseLines: [segmentPath("p1", "b1")],
|
||||
start: await findSegmentKm("p1", "start") }}));"""
|
||||
got = _node([CALC, LAYOUT, STATE], script, STATE_STUBS)
|
||||
assert got["a"] == "g → 병곡리 10.5 km" and got["b"] == "병곡리 → 시점 10.5 km"
|
||||
@@ -268,6 +268,8 @@ console.log(JSON.stringify({{ a, b, calls: CALLS.slice(1), afterRoute, writes, a
|
||||
assert got["routeLines"] == [got["path"]] and got["baseLines"] == [
|
||||
got["path"]
|
||||
] # 구간마다 길 선
|
||||
assert got["route"][0]["path"] == [[35.68, 127.9], [35.66, 127.85]] # 373 길 선 = 구간 자료에
|
||||
assert got["base"][0]["path"] == got["path"]
|
||||
assert got["start"] == "" # 시점 → 중점 = 길찾기 없음
|
||||
|
||||
|
||||
@@ -302,7 +304,7 @@ def test_화면_등록_모달_연결선_모달():
|
||||
assert "길찾기" not in mid.replace("길찾기 없음", "") and "editMap" not in mid
|
||||
assert 'if (from === "start") return openMidLeg(projectId);' in leg
|
||||
assert "void reverseAddress(projectId, lon, lat)" in leg and "void run();" in leg
|
||||
assert "if (!manual.input.checked && !segmentPath(from).length && seg.from && seg.to)" in leg
|
||||
assert "!manual.input.checked && !segmentPath(projectId, from).length" in leg
|
||||
for rel in (B08 + "UI_Milestone_Modal.ts", B08 + "UI_Milestone_Place.ts",
|
||||
B08 + "UI_Milestone_LegModal.ts", KMAP, STATE, LAYOUT, CALC,
|
||||
B08 + "UI_Milestone.ts", B08 + "UI_Milestone_Diagram.ts",
|
||||
|
||||
@@ -11,8 +11,10 @@ import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import ValidationError
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
@@ -93,12 +95,15 @@ def test_깨진_좌표_km_그대로_길_선만_없음(monkeypatch):
|
||||
|
||||
def test_좌표_저장_안_함(tmp_path):
|
||||
route = {"id": "r1", "name": "거창군청", "legs": [{"road": None, "auto_km": 10.5}]}
|
||||
route["path"] = [[35.6866, 127.9095], [35.66, 127.85]] # 화면이 잘못 실어 보내도
|
||||
route["path"] = [
|
||||
[35.6866, 127.9095],
|
||||
[35.66, 127.85],
|
||||
] # 화면이 잘못 실어 보내도(거래처 칸 = 안 받음)
|
||||
ms.save_data(tmp_path, ms.Milestone.model_validate({"routes": [route]}))
|
||||
files = [p for p in tmp_path.rglob("*") if p.is_file()]
|
||||
assert [p.name for p in files] == ["milestone.json"]
|
||||
text = files[0].read_text(encoding="utf-8")
|
||||
assert '"path"' not in text and "35.6866" not in text and '"auto_km": 10.5' in text
|
||||
assert '"path": null' in text and "35.6866" not in text and '"auto_km": 10.5' in text
|
||||
|
||||
|
||||
def test_JS_키_길(monkeypatch):
|
||||
@@ -229,10 +234,34 @@ def test_화면_자리_캡처_키_서버만():
|
||||
assert "routeMapView" not in route and "다음 지도에서 길찾기" not in route
|
||||
assert "routeMapView" not in kmap
|
||||
state = _read("B08_Quantity/B08_Quantity_UI_Milestone_State.ts")
|
||||
assert "paths.set(from, res.path!);" in state # 메모리만(캐시 · 서버 안 감)
|
||||
assert "putFound(projectId, from, res.km, path);" in state # 373 구간 자료(캐시 → [저장])
|
||||
for rel in Path(ROOT / "B08_Quantity").glob("*.ts"): # 키 이름은 서버만
|
||||
text = rel.read_text(encoding="utf-8")
|
||||
assert "KAKAO_JS_KEY" not in text and "KAKAO_REST_API_KEY" not in text, rel
|
||||
for rel in (KMAP, "B08_Quantity/B08_Quantity_UI_Milestone_Modal.ts", LAYOUT,
|
||||
"B08_Quantity/B08_Quantity_Router_Milestone.py"): # fmt: skip
|
||||
assert len(_read(rel).splitlines()) <= 700
|
||||
|
||||
|
||||
def test_373_구간_길_선_저장_소수_5자리_점_줄임(tmp_path):
|
||||
line = [[35.6866123, 127.9095456], [35.686612, 127.909546], [35.66, 127.85]]
|
||||
leg = {"road": None, "auto_km": 10.5, "path": line}
|
||||
ms.save_data(tmp_path, ms.Milestone.model_validate({"routes": [{"id": "r1", "legs": [leg]}]}))
|
||||
saved = ms.read_data(tmp_path)["routes"][0]["legs"][0]["path"]
|
||||
assert [list(p) for p in saved] == [
|
||||
[35.68661, 127.90955],
|
||||
[35.68661, 127.90955],
|
||||
[35.66, 127.85],
|
||||
]
|
||||
with pytest.raises(ValidationError):
|
||||
ms.Milestone.model_validate({"routes": [{"id": "r1", "legs": [{"path": [[95.0, 127.0]]}]}]})
|
||||
with pytest.raises(ValidationError): # 상한
|
||||
ms.Milestone.model_validate(
|
||||
{"routes": [{"id": "r1", "legs": [{"path": [[35.0, 127.0]] * (ms.PATH_MAX + 1)}]}]}
|
||||
)
|
||||
# 길찾기 응답 줄이기 — 같은 점 이어짐 뺌 · 상한 안 · 두 끝 유지
|
||||
thin = ms.thin_path([[35.0, 127.0], [35.0, 127.0], [35.00001, 127.0]])
|
||||
assert thin == [[35.0, 127.0], [35.00001, 127.0]]
|
||||
wavy = [[35 + i * 1e-4, 127 + (i % 2) * 1e-5] for i in range(2000)]
|
||||
small = ms.thin_path(wavy)
|
||||
assert len(small) <= ms.PATH_MAX and small[0] == [35.0, 127.0] and small[-1][0] == wavy[-1][0]
|
||||
|
||||
@@ -113,8 +113,8 @@ def test_연결_점_왼쪽_위_안쪽_기준점도_돌기_취소():
|
||||
ui = _read(B08 + "UI_Milestone_Diagram.ts")
|
||||
dot = ui[ui.index("const connectDot") :]
|
||||
dot = dot[: dot.index("return dot;")]
|
||||
# 왼쪽 위 안쪽 — 가운데 (10, 10) · 반지름 6 + 테두리 2 = 상자 안
|
||||
assert "const cx = box.x + 10;" in dot and "const cy = box.y + 10;" in dot and "r: 6" in dot
|
||||
# 왼쪽 위 안쪽 — 가운데 (12, 12) · 반지름 9 + 테두리 2 = 상자 안(373)
|
||||
assert "const cx = box.x + 12;" in dot and "const cy = box.y + 12;" in dot and "r: 9" in dot
|
||||
assert (
|
||||
'if (box.kind === "route" || box.kind === "base") g.append(connectDot(box, shift));' in ui
|
||||
)
|
||||
|
||||
@@ -113,7 +113,9 @@ def test_경로_탭_끌기_다시_길찾기():
|
||||
assert "fresh.site.start_pin = { lon, lat };" in route
|
||||
assert "await refind(touchingSegments(fresh, key));" in route
|
||||
assert "findSegmentKm(projectId, id, false)" in route # 끌기 · 열기 = 그림 캡처 없음
|
||||
assert "[routeId, ...chain].filter((id) => !segmentPath(id).length)" in route # 열 때 모든 구간
|
||||
assert (
|
||||
"[routeId, ...chain].filter((id) => !segmentPath(projectId, id).length)" in route
|
||||
) # 열 때 모든 구간
|
||||
assert "status.hidden = !bad.length;" in route # 실패 안내
|
||||
calc = _read("B08_Quantity/B08_Quantity_Milestone_Calc.ts")
|
||||
assert "start_pin?: { lon: number; lat: number } | null;" in calc
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
"""373 B08 거리이정표 — 연결 없이 소재지 넣기 · 구간 길 선 저장 · 다시 이음 · 시점 미연결 · 녹색 점.
|
||||
|
||||
화면 코드는 소스 확인 + node 로 실제 TS(`findSegmentKm` · `reachesSite`)를 돌림. 서버 쪽 `path` 칸은
|
||||
`test_244_9_b08_milestone_route_map.py`.
|
||||
"""
|
||||
|
||||
from resources.tester.test_244_13_b08_milestone_place_leg import (
|
||||
CALC,
|
||||
LAYOUT,
|
||||
STATE,
|
||||
STATE_STUBS,
|
||||
_node,
|
||||
_read,
|
||||
)
|
||||
|
||||
B08 = "B08_Quantity/B08_Quantity_"
|
||||
ROW = [{"item": "철근", "dest": "start", "note": ""}]
|
||||
DATA = {
|
||||
"site": {"mid_station_m": None, "mid_road": "비포장"},
|
||||
"bases": [
|
||||
{"id": "b1", "name": "병곡리", "address": "", "dir": None, "lon": 127.85, "lat": 35.66,
|
||||
"legs": [{"road": None, "km": None}], "to": "site", "linked": False},
|
||||
],
|
||||
"routes": [
|
||||
{"id": "g", "name": "g", "address": "", "to": "b1", "dir": None, "lon": 127.9,
|
||||
"lat": 35.68, "linked": True, "legs": [{"road": "2차포장", "km": 23.8}], "rows": ROW},
|
||||
],
|
||||
} # fmt: skip
|
||||
FAIL_STUBS = STATE_STUBS.replace(
|
||||
'if (url.includes("/directions")) return {',
|
||||
'if (url.includes("/directions") && (globalThis as any).FAIL)'
|
||||
' return { km: null, reason: "카카오 실패", path: [] };\n'
|
||||
' if (url.includes("/directions")) return {',
|
||||
)
|
||||
|
||||
|
||||
def test_373_안_이은_기준점에_이으면_시점_미연결_실패면_옛_거리_선_지움():
|
||||
script = f"""const DATA = {__import__("json").dumps(DATA)};
|
||||
await loadMilestone("p1");
|
||||
const a = await findSegmentKm("p1", "g", false);
|
||||
const first = liveMilestone("p1");
|
||||
const open = reachesSite(first, "g");
|
||||
first.bases[0].linked = true;
|
||||
const closed = reachesSite(first, "g");
|
||||
(globalThis as any).FAIL = true;
|
||||
const b = await findSegmentKm("p1", "g", false);
|
||||
const after = liveMilestone("p1").routes[0].legs;
|
||||
console.log(JSON.stringify({{ a, b, open, closed, first: first.routes[0].legs, after,
|
||||
line: segmentPath("p1", "g") }}));"""
|
||||
got = _node([CALC, LAYOUT, STATE], script, FAIL_STUBS)
|
||||
assert got["a"] == "g → 병곡리 10.5 km — 시점 미연결" and got["open"] is False
|
||||
assert got["closed"] is True
|
||||
assert got["first"][0]["path"] == [[35.68, 127.9], [35.66, 127.85]] # 구간 자료에 길 선
|
||||
assert got["b"] == "g → 병곡리 — 카카오 실패"
|
||||
assert got["after"] == [{"road": "2차포장", "km": 23.8, "auto_km": None}] # 사용자 km 만 남음
|
||||
assert got["line"] == []
|
||||
|
||||
|
||||
def test_373_화면_소재지_지도_누름_저장된_선_녹색_점():
|
||||
route = _read(B08 + "UI_Milestone_Route.ts")
|
||||
assert (
|
||||
'label: "소재지"' in route
|
||||
and "openPlaceModal(projectId, { add: false, id: routeId })" in route
|
||||
)
|
||||
assert "onClick: (lon, lat) => void moveTo(routeId, lon, lat)," in route # 연결 없어도 누름
|
||||
assert "center: () => startPoint(liveMilestone(projectId))," in route # 점 없으면 시점 쪽
|
||||
assert "reachesSite(d, routeId)" in route and "시점 미연결" in route
|
||||
leg = _read(B08 + "UI_Milestone_LegModal.ts")
|
||||
assert "path: leg.path," in leg and "...(path ? { path } : {})" in leg # 모달이 선 안 지움
|
||||
assert "{ ...l, auto_km: null, path: null }" in leg # 수기 = 선 지움
|
||||
diagram = _read(B08 + "UI_Milestone_Diagram.ts")
|
||||
assert "route.legs = [{ road: null, km: null }];" in diagram # 다시 이음 = 옛 거리 · 선 지움
|
||||
state = _read(B08 + "UI_Milestone_State.ts")
|
||||
assert "paths" not in state.replace("path:", "").replace("segmentPath", "") # 메모리 표 없음
|
||||
assert "path?: Array<[number, number]> | null;" in _read(CALC)
|
||||
css = _read(B08 + "UI_Milestone.css")
|
||||
dot = css[css.index(".b08-milestone__connect {") :]
|
||||
assert "opacity: 0.85;" in dot[: dot.index("}")]
|
||||
Reference in New Issue
Block a user