Files
Aislo/resources/tester/test_283_route_reset_confirm.py
T
eomsangdonandClaude Opus 5.5 4aeaa9442b fix(493-5 [적용] 뒤 화면 초안 = 새 초기값): 추천 [적용] 뒤 추가 측점 저장분 다시 받음
- 원인: 페이지를 다시 세워도 추가 측점 저장분 기억(모듈 캐시 · 따라감 기억)이 남아 [적용]으로 지운 측점을 목록 · [저장]에 되살림
- reloadSavedPlusStations — 저장분 · 땅 위 자리 · 받음 표시 · 따라감 기억 비우고 다시 받음 · saveRecommendedRoute 가 clearDrafts 뒤 · 다시 세우기 앞에서 부름
- 시험: test_283_route_reset_confirm 에 [적용] 뒤 저장분 = 서버(0) · [저장] 본문 없음 · 대조(다시 안 받으면 옛 저장분) · 배선 차례

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:14:00 +09:00

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)")
)