Files
Aislo/resources/tester/test_272_detail_memory.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

123 lines
5.2 KiB
Python

"""PLAN 466 (요구 272 · 분석 4장 (A)) — 상세 가게 메모리 = 페이지 수명.
못박는 것
- 관 초안으로 갈아끼운 상세(메모리) → [폐기] → 페이지를 떠남 = 메모리 비움 → 다시 열기(B05 · B06 · B07) =
세션 정본(새로고침 길 · 뒤에서 판 확인 한 번) · 초안 측점이 남지 않음. 다른 프로젝트 메모리는 그대로.
- 페이지 dispose 가 비움(`design_page`) · 묶음 열 때 관 · 구조물 · 추가 측점 초안이 있으면 측점을 냄
(초안 남긴 채 떠남 · 새로고침 = 초안 측점 · 갈아끼움).
- 화면 선만 바뀜(비정규 측점 도착) = 상세가 그 선 대비 낡았으면 cross 한 번 더(`recrossIfStale`).
짝: `helper_272_detail_memory_entry.ts` + `helper_272_detail_memory.mjs`(진짜 상세 가게 · vite ssr).
./venv/Scripts/python.exe -m pytest resources/tester/test_272_detail_memory.py -q
"""
from __future__ import annotations
import json
import shutil
import subprocess
from pathlib import Path
import pytest
HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
pytestmark = pytest.mark.skipif(
not (ROOT / "config" / "node_modules" / "vite").is_dir(),
reason="프론트엔드 의존성 미설치",
)
def run_helper(work: Path) -> dict:
"""vite ssr 로 진짜 모듈을 묶어 헬퍼를 돌림 — 466 두 시험이 같이 씀."""
build = subprocess.run( # noqa: S603 — 고정 실행 파일
[
"node",
str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"),
"build",
"--configLoader",
"runner",
"--ssr",
"../resources/tester/helper_272_detail_memory_entry.ts",
"--outDir",
str(work),
"--logLevel",
"error",
],
cwd=ROOT,
capture_output=True,
text=True,
encoding="utf-8",
timeout=300,
)
assert build.returncode == 0, build.stderr
bundle = work / "bundle.mjs"
shutil.copy(work / "helper_272_detail_memory_entry.js", bundle)
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", str(HERE / "helper_272_detail_memory.mjs"), str(bundle)],
capture_output=True,
text=True,
encoding="utf-8",
timeout=120,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
@pytest.fixture(scope="module")
def got(tmp_path_factory) -> dict:
return run_helper(tmp_path_factory.mktemp("b272"))
def test_초안_동안은_메모리만_갈아끼움(got) -> None:
m = got["memory"]
assert m["swapped"] and m["during"] == [0, 20, 30, 40, 60]
assert m["session"] == [0, 20, 40, 60] # 세션 = 저장 정본
def test_폐기만으론_메모리_그대로_떠나면_정본(got) -> None:
m = got["memory"]
assert m["pipesAfterDiscard"] is None # 관 초안 지움
assert m["afterDiscard"] == [0, 20, 30, 40, 60] # 같은 페이지 안 = 메모리(떠날 때 비움)
assert m["peekAfterForget"] is None
assert m["reopened"] == [0, 20, 40, 60] and m["reopenedSame"] is False # 새로고침 길
assert m["canonAsked"] == 1 # 세션으로 서고 뒤에서 판 확인(새로고침과 같음)
assert m["otherKept"] is True
def test_페이지가_떠날_때_비움() -> None:
page = (ROOT / "A00_Common/design/design_page.ts").read_text(encoding="utf-8")
dispose = page[page.index(" covers: (route)") :]
assert "forgetSectionMemory(projectId);" in dispose[: dispose.index("\n };\n")]
def test_초안_있으면_열_때_측점_냄() -> None:
src = (ROOT / "A00_Common/design/design_pipeline_page.ts").read_text(encoding="utf-8")
start = src[src.index(" const start = (): void => {") :]
body = start[: start.index("\n };\n")]
assert 'store.get("pipes") ?? store.get("structures") ?? readPlusDraft(projectId)' in body
assert "quietGeneration = inputs.route || drafts ? -1 : pipe.generation;" in body
def test_화면_선만_바뀌면_낡음_다시_셈() -> None:
src = (ROOT / "A00_Common/design/design_pipeline_page.ts").read_text(encoding="utf-8")
restart = src[src.index(" restart() {") :]
# 정본 지문은 `design_pipeline_page_saved`(472-5 나눔) — 노선 번호를 거기서 읽음
assert (
"publisher.recheck(projectId, pageSaved.canonRouteId()"
in restart[: restart.index(" },")]
)
store = (ROOT / "B06_Section/B06_Section_Section_Store.ts").read_text(encoding="utf-8")
fn = store[store.index("export function recrossIfStale(") :]
assert "recrossSaved(projectId, key, detail, routeId)" in fn[: fn.index("\n}\n")]
def test_확정_성공도_상세_비움() -> None:
# 470 N1 — [확정] 은 다음 페이지(B07)로 바로 감 · [저장]처럼 상세 메모리 · 옛 세션 사본을 비움
# (이동은 잠금판 `moveStage` 가 · 520-4)
shared = (ROOT / "A00_Common/design/design_shared.ts").read_text(encoding="utf-8")
done = shared[shared.index(" done: async (isConfirm, reload = true) => {") :]
confirm = done[done.index("if (isConfirm) {") : done.index('L("B06_Profile_Confirm_Success")')]
assert "invalidateSectionDetail(shared.projectId);" in confirm