- 원인: 페이지를 다시 세워도 추가 측점 저장분 기억(모듈 캐시 · 따라감 기억)이 남아 [적용]으로 지운 측점을 목록 · [저장]에 되살림 - reloadSavedPlusStations — 저장분 · 땅 위 자리 · 받음 표시 · 따라감 기억 비우고 다시 받음 · saveRecommendedRoute 가 clearDrafts 뒤 · 다시 세우기 앞에서 부름 - 시험: test_283_route_reset_confirm 에 [적용] 뒤 저장분 = 서버(0) · [저장] 본문 없음 · 대조(다시 안 받으면 옛 저장분) · 배선 차례 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
142 lines
6.1 KiB
Python
142 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""283 · 493-2 · 493-5 B05 [저장] = 보이는 화면 그대로 · 초기화 기준 = 노선 추천 [적용](요구 289 · 290).
|
|
|
|
- 손 고침 [저장] — 띠 · 확인 창 · 저장 뒤 초기화 알림 · 세션 초안 통째 비움 없음(492-2 걷음 · 소스 확인).
|
|
- 추천 [적용] 확인 창 — 지워질 수 = 서버 저장분(구조물 · 관 · 추가 측점) = 적용 뒤 알림 수
|
|
(서버 `route_reset.dropped` = 저장 파일 길이) · 세션 초안은 안 셈 · 관 저장 파일 없음 = 0.
|
|
- [적용] 뒤 추가 측점 저장분 다시 받음 — 지운 측점이 목록 · [저장]에 남지 않음(493-5).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
ROOT = HERE.parents[1]
|
|
|
|
pytestmark = pytest.mark.skipif(
|
|
not (ROOT / "config" / "node_modules" / "typescript").is_dir(),
|
|
reason="프론트엔드 의존성 미설치",
|
|
)
|
|
|
|
SERVERS = {
|
|
"saved": {
|
|
"structures": {"structures": [{"id": "s1"}]},
|
|
"pipes": {"saved": True, "pipe_points": [{}, {}, {}]},
|
|
"plus": [120],
|
|
},
|
|
"unsaved_pipes": { # 관 저장 파일 없음 — 응답 관은 자동 제안 · 서버가 지울 것 0
|
|
"structures": {"structures": []},
|
|
"pipes": {"saved": False, "pipe_points": [{}, {}]},
|
|
"plus": [],
|
|
},
|
|
"fail": {"structures": "fail", "pipes": "fail", "plus": "fail"},
|
|
}
|
|
RESET = {"reset": True, "dropped": {"structures": 1, "pipes": 3, "plus_stations": 1}}
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def ts(tmp_path_factory):
|
|
source = tmp_path_factory.mktemp("s283") / "in.json"
|
|
source.write_text(json.dumps({"servers": SERVERS, "reset": RESET}), encoding="utf-8")
|
|
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
["node", str(HERE / "helper_283_route_reset_confirm.cjs"), str(source)],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=120,
|
|
check=False,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def _read(*parts: str) -> str:
|
|
return ROOT.joinpath(*parts).read_text(encoding="utf-8")
|
|
|
|
|
|
# ── 손 고침 [저장] = 보이는 화면 그대로 ───────────────────────────────────────
|
|
|
|
|
|
def test_저장_확인창_초기화알림_초안비움_없음():
|
|
src = _read("A00_Common", "design", "design_save.ts")
|
|
for gone in ("confirmRouteReset", "routeResetNotice", "route_reset", "clearDrafts("):
|
|
assert gone not in src
|
|
body = src[src.index("export async function saveDesign(") :]
|
|
# 잠금 막 앞에 묻는 것 없음 — 노선 초안 읽기는 잠금 막 뒤(492 이전 차례)
|
|
assert body.index("showLoadingOverlay()") < body.index("pendingRouteSave(")
|
|
|
|
|
|
def test_띠_걷음():
|
|
assert "mountRouteResetBand" not in _read("A00_Common", "design", "design_view_profile.ts")
|
|
assert "reset-band" not in _read("B05_Profile", "B05_Profile_UI_Style_RouteEdit.css")
|
|
assert "pageRoutePlan" not in _read("A00_Common", "design", "design_page_data.ts")
|
|
assert "routeShapeChanged" not in _read("B05_Profile", "logic", "B05_Profile_Grade_Carry.ts")
|
|
logic = _read("B05_Profile", "logic", "B05_Profile_Route_Reset.ts")
|
|
for gone in ("ROUTE_RESET_BAND", "draftShapeChanged", "askRouteReset"):
|
|
assert gone not in logic
|
|
|
|
|
|
# ── 추천 [적용] 확인 창 = 서버가 지울 수 ─────────────────────────────────────
|
|
|
|
|
|
def test_적용_확인창_서버_저장분_수(ts):
|
|
text = ts["texts"]["saved"]
|
|
assert text.startswith("추천 노선을 [적용]하면 초기화")
|
|
for part in ("구조물 1", "관 3", "추가 측점 1", "종단 · 횡단 손 입력"):
|
|
assert part in text
|
|
assert text.endswith("적용할까요?")
|
|
|
|
|
|
def test_적용_확인창_수_적용뒤_알림_수_같음(ts):
|
|
dropped = RESET["dropped"]
|
|
text, notice = ts["texts"]["saved"], ts["notice"]
|
|
for name, key in (("구조물", "structures"), ("관", "pipes"), ("추가 측점", "plus_stations")):
|
|
assert f"{name} {dropped[key]} " in text and f"{name} {dropped[key]}" in notice
|
|
|
|
|
|
def test_관_저장파일_없음_0_받기실패_0(ts):
|
|
assert "구조물 0 · 관 0 · 추가 측점 0" in ts["texts"]["unsaved_pipes"]
|
|
assert "구조물 0 · 관 0 · 추가 측점 0" in ts["texts"]["fail"]
|
|
|
|
|
|
def test_적용_확인창_배선():
|
|
initial = _read("B05_Profile", "B05_Profile_UI_RouteEdit_Initial.ts")
|
|
assert "confirmText: () => applyResetText(projectId)" in initial
|
|
ui = _read("B05_Profile", "B05_Profile_UI_RouteReset.ts")
|
|
assert "useDesignStore" not in ui # 세션 초안 안 셈
|
|
|
|
|
|
# ── 적용 뒤 알림 ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
def test_적용뒤_알림_dropped(ts):
|
|
assert ts["notice"] == (
|
|
"노선이 바뀌어 초기화했습니다 — 지움: 구조물 1 · 관 3 · 추가 측점 1 · 새 교차 관 2"
|
|
)
|
|
assert ts["noticeNone"] == [None, None]
|
|
|
|
|
|
# ── 493-5 [적용] 뒤 화면 초안 = 새 초기값 ────────────────────────────────────
|
|
|
|
|
|
def test_적용뒤_추가측점_저장분_다시받음(ts):
|
|
fixed, stale = ts["plusApply"]["fixed"], ts["plusApply"]["stale"]
|
|
assert fixed["before"] == [127, 163]
|
|
assert fixed["after"] == [] and fixed["body"] is None # [저장]이 지운 측점을 다시 안 보냄
|
|
assert stale["after"] == [127, 163] # 대조 — 다시 안 받으면 옛 저장분이 남음(고치기 전)
|
|
|
|
|
|
def test_적용_배선_추가측점_다시받기():
|
|
src = _read("B05_Profile", "B05_Profile_UI_RouteEdit_Apply.ts")
|
|
body = src[src.index("export async function saveRecommendedRoute(") :]
|
|
assert (
|
|
body.index("clearDrafts(projectId)")
|
|
< body.index("await reloadSavedPlusStations(projectId)")
|
|
< body.index("await rebuildAfterRouteSave(projectId)")
|
|
)
|