Files
Aislo/resources/tester/test_298_3_save_shape.py
T
eomsangdonandClaude Opus 5.5 ed9e014db2 feat(520-4): B05 · B06 페이지 넘김 공용 moveStage — B06 [>] 잠금판 「설계 확정」 서버 저장 차례 n/N 이름 · 배수유역 다시 셈 한 번
- B06 [>] · 단계 판 B07~B09 = moveStage 한 단계(설계 확정) · progress = GET /design/save/progress 1 s 물음 · B03 · B04 로 = moveStage 잠금 길(떠남 확인은 잠금 풀린 뒤)
- 낡음 확인 창 · 화면 side.update() 걷음 — 배수유역은 서버 [확정] 관 차례가 한 번만 셈 · 진행 이름 「배수유역 다시 셈」(basins)
- 서버 _run_steps step() 진행을 메모리(B06_Section_Router_DesignSave_Progress) · 차례 목록 = N · 끝에 비움
- 노선 바뀐 채 [>] = 물음(잠금판 위 · z 1050 > 900) → 다시 세운 페이지 둘째 확정을 저장 줄 밖에서 기다림 → 잠금판이 다시 마운트를 넘어 이어져 이동 · 120 s 넘으면 머묾
- saveSharedDesign 이 참 · 거짓을 돌려줌 · 확정 이동은 부른 쪽(moveStage)
- 낡은 시험 고침 — 512_2(확인 창 → 잠금판 한 단계 · 서버 basins) · 298_3 · 272 · b06_save_channels · b06_save_recompute(글 약속 새 길)
- helper_ts_stub_loader .css = 빈 모듈 — 520-3 ui_template_progress.css import 로 451 · 384_4 · 416 등 helper 시험이 깨짐(브레인 승인)
- 새 시험 test_520_4_save_progress(n/N · 배수유역 자리)

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

113 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")]
# 잠금판 한 단계 — 확정됐으면 저장 없이 이동(520-4 moveStage)
assert "run: async () => (await alreadyConfirmed(id)) || saveSharedDesign(shared, true)," in go
# 줄 세움 = [저장] · 확정 한 곳
assert "await queueDesignSave(shared.projectId, confirm, () =>" in shared
assert "saveOnce(shared, confirm, moved)," 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 보류)