feat(종단보기): 346-3 [노선 반영] 없앰 — [저장]이 노선부터(POST /route/replan · draft = 계약 RouteDraft · 안 바뀌면 안 보냄) · 뒤 차례는 새 노선 · 횡단 초안 측점 열쇠로 넘김 · 결과 한 줄
- design_save 차례 = 노선 → 관 → 구조물 → 계획고(옛 노선 칸 → 새 노선) → 암거 옵션 → 상단측 → 횡단(carryStationDrafts 뒤 저장) · 잠금 막 = [저장] 하나 · 실패 = 멈춤 · 초안 그대로 · 오류 한 줄 - [확정] 중 노선이 바뀌면 노선만 저장하고 다시 세움(새 노선으로 다시 [확정]) - _RouteEdit_Apply = 노선 저장 이음(편집기 등록부 · pendingRouteSave · saveRouteDraft · carryAfterRouteSave · routeSaveSummary · rebuildAfterRouteSave) · 단추 듣기 없음 - 결과 한 줄 = 관 지킴 · 새 교차 관 · 오목 보충 · 구조물 옮김 · 멀어짐 · 노선 밖 고침(서버 cross_dropped + 화면) · 배수유역 낡음 - RE_Chrome [노선 반영] 지움 · [반영 전으로] → [저장 전으로] · replanRoute 본문 = RouteSaveBody - 시험: test_design_store_save 차례 넷 더함 · 꼴 시험 셋 고쳐 씀 · 323_9 대역 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
This commit is contained in:
@@ -33,6 +33,10 @@ const STUBS = {
|
||||
showLoadingOverlay: () => calls.push("overlay:on"),
|
||||
hideLoadingOverlay: () => calls.push("overlay:off"),
|
||||
},
|
||||
// 노선 저장(346-3) — 이 시험은 노선이 그대로인 [저장]만 봄
|
||||
[path.join(ROOT, "B05_Profile", "B05_Profile_UI_RouteEdit_Apply.ts")]: {
|
||||
pendingRouteSave: async () => null,
|
||||
},
|
||||
[path.join(B06, "B06_Section_Api_Fetch.ts")]: {
|
||||
fetchSectionDetail: async () => (calls.push(`fetch:${server}`), detail()),
|
||||
saveSections: async () => calls.push("cross:save"),
|
||||
|
||||
@@ -30,7 +30,22 @@ const record = (name, fail) => async () => {
|
||||
if (fail) throw new Error(`${name} 실패`);
|
||||
};
|
||||
let failStructures = false;
|
||||
// 노선 저장(346-3) — 초안 · 실패를 시험이 정함
|
||||
let routeBody = null;
|
||||
let failRoute = false;
|
||||
const routeStub = {
|
||||
pendingRouteSave: async () => routeBody,
|
||||
saveRouteDraft: async () => {
|
||||
calls.push("route");
|
||||
if (failRoute) throw new Error("노선 저장 실패");
|
||||
return { route_id: 9, pipes: { kept: 3, crossing: 1, concave: 0 }, cross_dropped: 1 };
|
||||
},
|
||||
carryAfterRouteSave: async (_p, from, to) => (calls.push(`carry:${from}->${to}`), 2),
|
||||
routeSaveSummary: (saved, outside) => (calls.push(`summary:${saved.route_id}:${outside}`), ""),
|
||||
rebuildAfterRouteSave: async () => calls.push("rebuild"),
|
||||
};
|
||||
const STUBS = {
|
||||
"../../B05_Profile/B05_Profile_UI_RouteEdit_Apply": routeStub,
|
||||
"@ui/ui_template_elements": {
|
||||
showToast: (text, kind) => calls.push(`toast:${kind}`),
|
||||
showLoadingOverlay: () => calls.push("overlay:on"),
|
||||
@@ -161,6 +176,57 @@ async function run() {
|
||||
});
|
||||
out.noRouteCalls = [...calls];
|
||||
|
||||
// ⑥ 노선이 바뀜(346-3) — 노선 먼저 · 뒤 차례는 새 노선(9) · 화면 몫 건너뜀 · 횡단 초안 넘김 · 다시 세움
|
||||
b05.replace({ station_offsets: { "30.000": 0.2 }, curve_radii: {} }); // 옛 노선(7) 계획고 초안
|
||||
routeBody = {
|
||||
draft: {
|
||||
rev: 1,
|
||||
nodes: [
|
||||
[0, 0],
|
||||
[10, 0],
|
||||
],
|
||||
},
|
||||
};
|
||||
calls.length = 0;
|
||||
out.routeOk = await saveDesign({
|
||||
projectId: "p1",
|
||||
routeId: () => 7,
|
||||
prepare: record("prepare"),
|
||||
steps: { pipes: record("pipes:screen"), alignment: record("alignment:screen") },
|
||||
cross: async (confirm) => calls.push(`cross:${confirm}`),
|
||||
done: async (confirm) => calls.push(`done:${confirm}`),
|
||||
failed: () => calls.push("failed"),
|
||||
});
|
||||
out.routeCalls = [...calls];
|
||||
// ⑦ 노선 저장 실패 — 거기서 멈춤 · 다른 초안 그대로
|
||||
b05.replace({ station_offsets: { "50.000": 0.3 }, curve_radii: {} });
|
||||
failRoute = true;
|
||||
calls.length = 0;
|
||||
out.routeFailOk = await saveDesign({
|
||||
projectId: "p1",
|
||||
routeId: () => 7,
|
||||
cross: async (confirm) => calls.push(`cross:${confirm}`),
|
||||
done: async (confirm) => calls.push(`done:${confirm}`),
|
||||
failed: () => calls.push("failed"),
|
||||
});
|
||||
out.routeFailCalls = [...calls];
|
||||
out.routeFailDraft = edit.pendingAlignment(7)?.station_offsets ?? null;
|
||||
failRoute = false;
|
||||
// ⑧ [확정] 중 노선이 바뀜 — 노선 저장 뒤 다시 세움 · 확정 단계는 안 닫음(새 노선으로 다시)
|
||||
calls.length = 0;
|
||||
await saveDesign(
|
||||
{
|
||||
projectId: "p1",
|
||||
routeId: () => 7,
|
||||
cross: async (confirm) => calls.push(`cross:${confirm}`),
|
||||
done: async (confirm) => calls.push(`done:${confirm}`),
|
||||
failed: () => calls.push("failed"),
|
||||
},
|
||||
{ confirm: true },
|
||||
);
|
||||
out.routeConfirmCalls = [...calls];
|
||||
routeBody = null;
|
||||
|
||||
// ⑤ [초기화] — 초안 · 한 벌 모두 버림
|
||||
b05.replace({ station_offsets: { "80.000": 1 }, curve_radii: {} });
|
||||
edit.clearAlignmentDrafts();
|
||||
|
||||
@@ -291,6 +291,7 @@ def test_화면_확인이_고른_지형을_실음():
|
||||
page = ROOT / "B05_Profile"
|
||||
apply = (page / "B05_Profile_UI_RouteEdit_Apply.ts").read_text(encoding="utf-8")
|
||||
main = (page / "B05_Profile_UI_RouteEdit.ts").read_text(encoding="utf-8")
|
||||
assert "terrain: params.terrain()," in apply
|
||||
# 346-3 — 노선 초안(draft.terrain)에 실림 · [저장]이 보냄
|
||||
assert "terrain: params.terrain() })" in apply and "terrain: settings.terrain," in apply
|
||||
assert "pickedTerrain() !== designTerrain" in main # 지형만 바꿔도 [확인]이 다시 셈
|
||||
assert "analysisTerrain(projectId, designTerrain)" in main # 고른 값 없으면 설계 지형
|
||||
|
||||
@@ -33,10 +33,12 @@ def test_겉틀은_본문_칸():
|
||||
assert 'overlay.className = "b05-routeedit";' in chrome
|
||||
assert "b05-routeedit__close" not in chrome and 'data-slot="close"' not in chrome
|
||||
assert '"tools"' in chrome and "replaceWith(...tools)" in chrome
|
||||
assert ">반영 전으로</button>" in chrome and ">노선 반영</button>" in chrome
|
||||
# 346-3 — [노선 반영] 없앰(노선은 페이지 [저장]이 맨 앞에서 보냄) · [취소] = [저장 전으로]
|
||||
assert ">저장 전으로</button>" in chrome and 'data-act="apply"' not in chrome
|
||||
assert "노선 반영</button>" not in chrome
|
||||
assert ">취소</button>" not in chrome and ">확인</button>" not in chrome
|
||||
# 시험 · 배선이 집는 자리는 남김
|
||||
for hook in ('data-act="apply"', 'data-act="cancel"', "b05-routeedit__measure-close"):
|
||||
for hook in ('data-act="cancel"', "b05-routeedit__measure-close"):
|
||||
assert hook in chrome
|
||||
assert 'data-act="side-toggle"' in chrome and "is-collapsed" in chrome
|
||||
|
||||
|
||||
@@ -114,9 +114,9 @@ def test_초기화_계획노선_편집은_다시_세움():
|
||||
assert step in rebuild
|
||||
assert rebuild.index("invalidateSectionDetail") < rebuild.index("remountRoute(")
|
||||
assert "mountRouteEditor(mainContent, host, activeProjectId, rebuildAfterReplan," in view
|
||||
# 346-3 — [저장]이 노선을 보낸 뒤 결과 캐시를 비우고 편집기가 건 다시 세우기(rebuildAfterReplan)
|
||||
apply = _read("B05_Profile/B05_Profile_UI_RouteEdit_Apply.ts")
|
||||
assert apply.index("clearDrafts(projectId);") < apply.index("await params.onApplied();")
|
||||
assert "clearResults(projectId);" in apply
|
||||
assert "clearResults(projectId);" in apply and "rebuild: params.onApplied," in apply
|
||||
|
||||
|
||||
def test_종단_보기_확정은_횡단_보기를_숨긴_채_세움():
|
||||
|
||||
@@ -48,7 +48,15 @@ def test_계획고_가게_한_벌(out):
|
||||
|
||||
|
||||
def test_저장_차례(out):
|
||||
assert out["order"] == ["pipes", "structures", "alignment", "culvertOptions", "uphill", "cross"]
|
||||
assert out["order"] == [
|
||||
"route",
|
||||
"pipes",
|
||||
"structures",
|
||||
"alignment",
|
||||
"culvertOptions",
|
||||
"uphill",
|
||||
"cross",
|
||||
] # 346-3 노선 먼저
|
||||
assert out["saveOk"] is True
|
||||
assert out["saveCalls"] == [
|
||||
"overlay:on",
|
||||
@@ -78,3 +86,43 @@ def test_구조물_실패는_알리고_넘어감_확정_노선없음(out):
|
||||
|
||||
def test_초기화는_초안과_한_벌을_버림(out):
|
||||
assert out["cleared"] == {"draft": None, "pending": None}
|
||||
|
||||
|
||||
def test_노선이_바뀌면_노선_먼저_뒤_차례는_새_노선(out):
|
||||
"""346-3 — 노선 초안이 있으면 맨 앞 · 관 · 구조물 기본 창구 · 계획고 초안(옛 노선 7 칸)을 새 노선 9 로 ·
|
||||
화면 몫 일(옛 노선 판)은 건너뜀 · 횡단 초안 넘김(측점 열쇠) · 결과 한 줄 · 다시 세움."""
|
||||
assert out["routeOk"] is True
|
||||
assert out["routeCalls"] == [
|
||||
"overlay:on",
|
||||
"prepare",
|
||||
"route",
|
||||
"pipes",
|
||||
"structures",
|
||||
'alignment:9:{"30.000":0.2}',
|
||||
"culvert:aislo:draft:culvertopt:p1:7",
|
||||
"uphill",
|
||||
"carry:7->9",
|
||||
"summary:9:2",
|
||||
"toast:info",
|
||||
"done:false",
|
||||
"rebuild",
|
||||
"overlay:off",
|
||||
]
|
||||
assert "pipes:screen" not in out["routeCalls"] and "alignment:screen" not in out["routeCalls"]
|
||||
assert "cross:false" not in out["routeCalls"] # 옛 노선 횡단 본문 대신 넘김
|
||||
|
||||
|
||||
def test_노선이_그대로면_안_보냄(out):
|
||||
assert "route" not in out["saveCalls"]
|
||||
|
||||
|
||||
def test_노선_저장_실패는_멈추고_초안_남음(out):
|
||||
assert out["routeFailOk"] is False
|
||||
assert out["routeFailCalls"] == ["overlay:on", "route", "failed", "overlay:off"]
|
||||
assert out["routeFailDraft"] == {"50.000": 0.3} # 계획고 초안 그대로
|
||||
|
||||
|
||||
def test_확정_중_노선이_바뀌면_다시_세우고_확정은_다시(out):
|
||||
calls = out["routeConfirmCalls"]
|
||||
assert calls[1] == "route" and calls[-2:] == ["rebuild", "overlay:off"]
|
||||
assert "done:true" not in calls and "cross:true" not in calls
|
||||
|
||||
Reference in New Issue
Block a user