Files
Aislo/resources/tester/test_298_3_save_shape.py
T
eomsangdonandClaude Opus 5.5 4046178a5d fix(498-3 저장 모양): 노선 그대로 [저장] = 잠금 없이 뒤에서 · 저장 중 [저장] 막음 · 저장 중 [>] = 앞 저장 끝 뒤 확정 · 결과 한 줄 토스트 걷음 — 요구 298-3 · 302 D1
- 잠금 = 확정 · 노선 모양 바뀐 [저장]만 · 그 밖 [저장]은 뒤에서 · 끝나면 「저장했습니다」
- 줄 세움 queueDesignSave — 저장 중 [저장] = 「이전 수정을 저장 중입니다…」 + 막음 · 저장 중 확정 = 잠그고 기다린 뒤 지금 화면 · 서버 저장 도중 안 끊음
- 저장 도중 고침 = 조각 정리 · 깨끗한 표 건너뜀(초안 남아 다음 저장에서 다시 나감)
- 노선 바뀐 [저장] = 옛 페이지 두 보기 헛 다시 읽기 걷음 · 떠남 표 · 알림만 뒤 다시 세움
- B06 [>] = 고친 것 없음 + 단계 2 · 3 COMPLETE 면 저장 없이 이동 · 그 밖 496 확정 그대로
- 노선 저장 알림 = 따라감 실패 · 새 교차 관 한 줄만(routeSaveSummary · 노선 밖 되풀이 지움)
- 시험 test_298_3_save_shape 새로 · 옛 요약 · 잠금 단언 고쳐 씀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:08:12 +09:00

117 lines
4.7 KiB
Python

"""요구 298-3 · 302 D1 — B05 · B06 [저장] 모양 · 저장 알림 정리(PLAN 498-3).
① 노선 모양 안 바뀐 [저장] = 잠금 없이 뒤에서 · 끝나면 알림(`design_shared` done)
② 노선 모양 바뀐 [저장] = 잠금 + 다시 세움 · 옛 페이지 헛 다시 읽기 없음(`done(false, false)`)
③ 고친 것 없고 단계 2 · 3 이미 완료 = [>] 저장 없이 바로 이동 · 그 밖 = 496 확정 그대로
④ 저장 중 확정 = 잠그고 앞 저장 끝을 기다린 뒤 지금 화면으로 · ⑤ 저장 중 [저장] = 막음 + 알림
알림 — 결과 한 줄(관 지킴 · 노선 밖 고침 · 배수 낡음 · 구조물 옮김) · 노선 밖 되풀이 지움 ·
남김 = 새 교차 관 한 줄 · 따라감 실패.
"""
import json
import pathlib
import subprocess
import pytest
HERE = pathlib.Path(__file__).resolve().parent
ROOT = HERE.parents[1]
BUSY = "toast:warning:이전 수정을 저장 중입니다. 잠시 후 다시 해 주세요."
def _read(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
@pytest.fixture(scope="module")
def out() -> dict:
proc = subprocess.run(
["node", str(HERE / "helper_298_3_save_shape.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_1_노선_그대로_저장은_잠금_없음(out):
assert out["plain"]["ok"] is True
assert out["plain"]["calls"] == [
"post:false",
"pipes:after",
"cross:after",
"clean",
"done:false:undefined",
]
assert not any(c.startswith("overlay") for c in out["plain"]["calls"])
def test_2_노선_모양_바뀐_저장은_잠금_다시_세움(out):
calls = out["route"]["calls"]
assert calls[0] == "overlay:on" and calls[-1] == "overlay:off"
assert calls.index("done:false:false") < calls.index(
"rebuild"
) # 다시 읽기 없이 알림만 · 다시 세움
assert calls.index("clean") < calls.index("done:false:false")
def test_2_노선_저장_알림은_따라감_실패_새_교차_관만(out):
toasts = [c for c in out["route"]["calls"] if c.startswith("toast:")]
assert toasts == [
"toast:error:구조물 따라감 실패 — 옛 누가거리 그대로입니다.",
"toast:info:새 교차 관 2개 — 새 세류선 교차점에 더했습니다.",
]
assert not [c for c in out["routeQuiet"]["calls"] if c.startswith("toast:")]
def test_저장_도중_고침은_정리_깨끗한_표_건너뜀(out):
assert out["touched"]["ok"] is True
assert out["touched"]["calls"] == ["post:false", "done:false:undefined"]
def test_5_저장_중_저장은_막음_알림(out):
assert out["busyWhile"] is True
assert out["second"] is False
assert "job2" not in out["queueCalls"]
assert out["queueCalls"].count(BUSY) == 2 # 저장 중 [저장] · 확정 중 확정
def test_4_저장_중_확정은_앞_저장_끝을_기다림(out):
calls = out["queueCalls"]
assert out["firstResult"] == "one" and out["confirmResult"] == "three"
assert calls.index("overlay:on") < calls.index("release") < calls.index("job1:end")
assert calls.index("job1:end") < calls.index("job3") < calls.index("overlay:off")
assert out["thirdBlocked"] is False and "job4" not in calls
assert out["busyAfter"] is False
assert out["otherProject"] == "p2" and out["otherCalls"] == [] # 프로젝트마다 따로
def test_3_고친_것_없고_단계_완료면_바로_이동():
shared = _read("A00_Common/design/design_shared.ts")
fn = shared[shared.index("async function alreadyConfirmed(") :]
fn = fn[: fn.index("\n}\n")]
assert "designSaveBusy(projectId) || designDirty(projectId)" in fn
assert "await pendingRouteSave(projectId)" in fn
assert 's.state === "COMPLETE"' in fn and "done(2) && !!done(3)" in fn
go = shared[shared.index("export function confirmAndGo(") :]
go = go[: go.index("\n}\n")]
assert (
"skip ? goToWorkflowStage(shared.projectId, route) : saveSharedDesign(shared, true, route)"
in go
)
# 줄 세움 = [저장] · 확정 한 곳
assert (
"await queueDesignSave(shared.projectId, confirm, () => saveOnce(shared, confirm, target));"
in shared
)
def test_결과_한_줄_걷음():
apply = _read("B05_Profile/B05_Profile_UI_RouteEdit_Apply.ts")
save = _read("A00_Common/design/design_save.ts")
assert "routeSaveSummary" not in apply and "routeSaveSummary" not in save
assert "outsideNotice" not in save # 노선 밖 = 편집 중 경고만(저장 뒤 되풀이 없음)
assert "noticeDroppedEdits(response)" in save # 계획고 편집 지움 알림은 그대로(498-2 보류)