Files
Aislo/resources/tester/test_481_2_save_move.py
T
eomsangdonandClaude Opus 5.5 59a694a7ed feat(B09): 단가연결 즉시 금액(뒤에서 서버 셈) · [저장] 단추 · 옮길 때 물음(PLAN 702-3)
- 새 산근(로직 연결 · 입력값) = 연결 즉시 뒤에서 POST …/estimation/calc(화면 캐시로 셈 ·
  저장 안 함) · 차례 번호 · 옛 요청 끊기 · 오는 동안 그 줄 금액 칸만 「셈 중」 · 잠금 없음
  (새 `B09_Estimation_UI_Live.ts`) · 기준 = payload.user(서버가 그 셈에 쓴 값)
- 조작 중 셈 = 마지막 GET · [저장] 의 B08 원천 다시 씀(120 s · 0.6 → 0.15 s) · [저장] · GET 은 늘 새로 읽음
- [저장] 단추 = 왼쪽 아래 [초기화] 옆(B08 과 같은 부품 · 꼴) · 고침 없으면 알림만
- 단계 이동 · [>] = 저장 안 한 고침 있으면 공용 떠남 물음(취소 · 폐기 · 저장) — 옛 자동 저장 없앰
- 서고 사본 payload 의 user 받음(서버 기준) — 화면 캐시와 다른 로직 줄은 뒤에서 다시 셈
- 낡은 시험 고침: 481-2 · 298-2(자동 저장 → 물음 · [저장] 단추) · 184-3 · 304(단추 줄) ·
  204-2(user 받음) · 200-2(701-3 띠 · 702-1 펼침 뒤 셸 꼴)
- 확인 = test_702_3 3 · B09 관련 312 통과 · typecheck 0 · 검증_sub5 T6 11 누름 · 연결 뒤 0.32~0.49 s 금액

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

86 lines
3.2 KiB
Python

# -*- coding: utf-8 -*-
"""481-2 B08 · B09 단계 이동(☰ · 진행 단계 · [<] [>]) = 보이는 화면 저장 성공 뒤 · 실패면 머묾.
`helper_481_2_save_move.cjs` 가 진짜 `B08_Quantity_UI_Page.ts` · `B08_Quantity_UI_Options.ts` ·
`B09_Estimation_UI_Shell.ts` 를 가짜 DOM · 가짜 의존 위에서 돌림.
"""
import json
import os
import re
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
HERE = os.path.dirname(os.path.abspath(__file__))
@pytest.fixture(scope="module")
def r():
proc = subprocess.run(
["node", os.path.join(HERE, "helper_481_2_save_move.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_B08_저장_성공_뒤_이동_왼쪽_다음_지금_탭(r):
b = r["b08"]
assert b["summaryOk"] == ["save:options", "req:complete", "go:b09"] # 298-2 단계 5 완료
assert b["materialOk"] == ["save:options", "save:material", "go:b07"]
def test_B08_저장_실패면_머묾(r):
b = r["b08"]
assert b["optionsFail"] == ["save:options"]
assert b["materialFail"] == ["save:options", "save:material"]
assert b["optionsFailSkipsTab"] == ["save:options"]
assert b["hydroFail"] == ["save:options", "save:hydro"]
def test_B08_떠난_탭은_저장_안_부름(r):
assert r["b08"]["leftTab"] == ["save:options", "req:complete", "go:b09"]
def test_B08_좌측_옵션_save(r):
o = r["options"]
assert o["clean"] == [True, []] # 고침 없음 = 요청 없이 참
assert o["changed"] == [True, ["req:PUT", "req:milestone", "redraw"]]
assert o["after"] is False
assert o["milestoneOnly"][0] is True and "req:PUT" in o["milestoneOnly"][1]
assert o["blankPipe"] == [False, []] # 1본 빈칸 = 머묾
assert o["fail"] == [False, ["req:PUT"]]
assert o["keptOnFail"] is True
def test_B09_고친_값_있으면_물음_뒤_이동(r):
# 702-3 B09 [저장] 단추 생김 — 단계 이동 = 저장 안 한 고침 있으면 물음(저장 · 버림 · 머묾)
b = r["b09"]
assert b["beforeLoad"] == ["go:b08"] # 불러오기 전 = 물음 · 저장 없이(캐시 남음)
assert b["clean"] == ["go:b08"] # 고침 없음 = 요청 없이
put = "fetch:PUT:/api/projects/P1/estimation"
assert b["fail"] == ["ask", put] # [저장] 실패 = 머묾
assert b["ok"] == ["ask", put, "go:b08"]
assert b["discard"] == [["ask", "go:b08"], False] # [버림] = 캐시 지움 · 저장 없이
assert b["stay"] == [["ask"], True]
def test_자재_수리_탭_저장_등록():
material = (ROOT / "B08_Quantity/B08_Quantity_UI_Material.ts").read_text(encoding="utf-8")
hydro = (ROOT / "B08_Quantity/B08_Quantity_UI_Hydro.ts").read_text(encoding="utf-8")
assert re.search(
r'onSave\?\.\(async \(\) => !readState\("b08-materials", projectId\) \|\| saveAll\(\)\)',
material,
)
assert re.search(
r"onSave\?\.\(async \(\) => !Object\.keys\(drafts\)\.length \|\| saveAll\(\)\)", hydro
)
for src in (material, hydro):
assert "const saveAll = async (): Promise<boolean>" in src