- 묶음 drainage 단계 입력 지문(노선 초안 rev 뺌 · 관 id · 자리 cm) — 같은 노선 · 관으로 다시 돈 묶음은 흘려보냄(떠 있는 요청 안 끊음 · 다시 안 흐림) - 차례 번호는 요청마다 하나 · 답은 차례 + 지문이 지금과 같을 때만 받음 - 서버 답이 「낡음」(노선 [저장] 뒤 등) = 수동은 흐림 + [업데이트] · 자동은 3 s 뒤 조용히(markStale) - 시험 test_349_drainage_live_flow(가짜 DOM · 시계 · fetch 로 화면 파일 실행 — 수동 · 자동 · 제안 [적용]) · 347-2 헬퍼 새 받기 규칙 - PLAN.md 349-0b Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
"""349 배수유역 자동/수동 흐름 — 화면 파일(`B05_Profile_UI_Drainage_Live` · `_Run` · `_Suggest`)을
|
|
가짜 DOM · 시계 · fetch 로 돌림(`helper_349_drainage_live_flow.cjs`).
|
|
|
|
- 수동: 꼭짓점 옮김 = 흐림 + [업데이트] · [업데이트] 뒤 묶음이 같은 노선 · 관으로 다시 돌아도 답을 받음
|
|
(입력 지문) · 답이 오면 흐림 · 「계산 중」 사라짐 · 제안 「제안 N건」 · [적용].
|
|
- 요청 중 또 옮기면 앞 요청 끊고 다시 흐림.
|
|
- 노선 [저장] 뒤 서버 답이 「낡음」 = 수동은 흐림 + [업데이트] · 자동은 3 s 뒤 조용히.
|
|
- ⚙ 자동: 3 s 조용한 뒤 셈 · 그 사이 또 옮기면 처음부터 · [업데이트] 막 없음.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def r():
|
|
proc = subprocess.run(
|
|
["node", os.path.join(HERE, "helper_349_drainage_live_flow.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
encoding="utf-8",
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def state(stale, veil, busy, fetches):
|
|
return {"stale": stale, "blur": stale, "veil": veil, "busy": busy, "fetches": fetches}
|
|
|
|
|
|
def test_manual_update_answer_lands_after_same_rerun(r):
|
|
assert r["moved"] == state(True, True, False, 0)
|
|
assert r["sameAgain"] == state(True, True, False, 0) # 판 번호만 바뀜 — 다시 안 흐림
|
|
assert r["sent"]["fetches"] == 1 and r["sent"]["busy"] and not r["sent"]["veil"]
|
|
rerun = r["rerunWhileBusy"]
|
|
assert not rerun["aborted"] and rerun["busy"] # 같은 입력 다시 돎 — 요청 그대로
|
|
assert r["answered"] == {**state(False, False, False, 1), "applied": 1}
|
|
|
|
|
|
def test_suggestions_and_apply(r):
|
|
assert r["suggest"]["shown"] and r["suggest"]["title"] == "제안 2건"
|
|
assert len(r["suggest"]["rows"]) == 2
|
|
points = {p["chainage_m"]: p for p in r["applied"]["points"]}
|
|
assert points[100]["options"]["pipe_diameter_mm"] == 1200
|
|
assert points[200]["source"] == "spacing"
|
|
assert r["applied"]["remembered"] == 1
|
|
|
|
|
|
def test_move_while_busy_cancels(r):
|
|
moved = r["movedWhileBusy"]
|
|
assert moved["aborted"] and moved["veil"] and not moved["busy"]
|
|
assert r["fresh"] == state(False, False, False, 3)
|
|
|
|
|
|
def test_saved_stale_shows_update(r):
|
|
assert {k: v for k, v in r["savedStale"].items() if k != "status"} == state(
|
|
True, True, False, 3
|
|
)
|
|
assert r["savedStale"]["status"] == "배수유역 낡음"
|
|
|
|
|
|
def test_auto_mode(r):
|
|
assert r["autoSwitch"] == state(True, False, False, 3) # 자동 — 흐림만 · [업데이트] 없음
|
|
assert r["auto2999"]["fetches"] == 3
|
|
assert r["auto3000"]["fetches"] == 4 and r["auto3000"]["route"] is None
|
|
assert r["autoDone"] == state(False, False, False, 4)
|
|
assert r["autoRestart"] == state(True, False, False, 4) # 2 s + 2 s — 처음부터 다시 3 s
|
|
assert r["autoMoved"] == {**state(False, False, False, 5), "mode": "auto"}
|
|
assert r["autoSavedStale"] == state(True, False, False, 5)
|
|
assert r["autoSavedDone"] == state(False, False, False, 6)
|
|
|
|
|
|
def test_input_key(r):
|
|
assert r["keys"] == {
|
|
"rev": True,
|
|
"order": True,
|
|
"node": False,
|
|
"pipe": False,
|
|
"id": False,
|
|
"saved": True,
|
|
}
|