Files
Aislo/resources/tester/test_384_1_session_keys.py
T
eomsangdonandClaude Opus 5.5 002d0e85ac refactor(387-1): 설계 화면 세션 직접 접근 → 등록부 · 프로젝트 없는 열쇠 걷음
- 되돌리기 사진 = 연 프로젝트 초안 칸만(projectStateKeys) · 옛 b05/b06 접두 지움
- 관 자리 b05:pipes 걷음 → 가게 pipes 초안으로 되돌림
- 조정창 · 연동 · 세월교 · BOX 세션 맵 = readByKey · writeByKey
- 노선 편집 횡단 반폭 = routeStateKeys · 계획고 옛 키(프로젝트 없음) 안 받음
- 새 test_384_1_session_keys · 사진첩 시험 헬퍼 = 진짜 등록부 부름

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
2026-10-17 17:29:17 +09:00

78 lines
3.0 KiB
Python

"""387-1(384 단계 1) 세션 열쇠 — 설계 화면은 세션을 등록부(`b_page_state`)로만 · 프로젝트 없는 열쇠 0.
· design · B05/B06 UI_* 파일 코드(주석 뺌)에 직접 sessionStorage 0
· 등록부 초안 · 결과 칸 옛 키는 모두 프로젝트를 품음 · `b05:pipes` 글 0
· `projectStateKeys` = 그 통 · 그 프로젝트 키만(노선 칸 포함 · 다른 프로젝트 · 다른 통 · 옛 키 밖)
./venv/Scripts/python.exe -m pytest resources/tester/test_384_1_session_keys.py -q
"""
from __future__ import annotations
import json
import re
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
LOADER = Path(__file__).resolve().parent / "helper_ts_cjs_load.cjs"
def _code(path: Path) -> str:
text = path.read_text(encoding="utf-8")
text = re.sub(r"/\*.*?\*/", "", text, flags=re.S)
return re.sub(r"(?m)^\s*//.*$|\s//\s.*$", "", text)
def _screen_files() -> list[Path]:
files = list((ROOT / "A00_Common" / "design").rglob("*.ts"))
files += (ROOT / "B05_Profile").glob("B05_Profile_UI_*.ts")
files += (ROOT / "B06_Section").glob("B06_Section_UI_*.ts")
return sorted(files)
def test_화면_파일에_직접_세션_0() -> None:
files = _screen_files()
assert len(files) > 100
hits = [str(p.relative_to(ROOT)) for p in files if "sessionStorage" in _code(p)]
assert hits == []
def test_프로젝트_없는_열쇠_0() -> None:
hits = [str(p.relative_to(ROOT)) for p in _screen_files() if '"b05:pipes"' in _code(p)]
assert hits == []
DRIVER = r"""
const data = new Map();
const fake = {
get length() { return data.size; },
key: (i) => [...data.keys()][i] ?? null,
getItem: (k) => (data.has(k) ? data.get(k) : null),
setItem: (k, v) => data.set(k, String(v)),
removeItem: (k) => data.delete(k),
};
globalThis.window = { sessionStorage: fake, localStorage: fake };
const { loadTs } = require(process.argv[1]);
const s = loadTs(process.argv[2]);
const legacy = Object.entries(s.STATE_REGISTRY)
.filter(([, e]) => e.bucket !== "pref" && e.legacy)
.map(([name, e]) => [name, e.legacy("PX", "RX")]);
for (const k of [
"aislo:draft:crossw:p1:7", "aislo:draft:pipes:p1", "aislo:draft:pipes:p10",
"aislo:draft:crossw:p2:7", "aislo:result:latest:p1", "b05:pipes", "b06:crossw:p1:7",
]) fake.setItem(k, "1");
process.stdout.write(JSON.stringify({ legacy, keys: s.projectStateKeys("draft", "p1").sort() }));
"""
def test_등록부_옛_키는_프로젝트_품음_사진_칸은_그_프로젝트만() -> None:
run = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", "-e", DRIVER, str(LOADER), str(ROOT / "A00_Common" / "b_page_state.ts")],
capture_output=True, text=True, encoding="utf-8", cwd=str(ROOT),
) # fmt: skip
assert run.returncode == 0, run.stderr
out = json.loads(run.stdout)
assert out["legacy"] and all("PX" in key for _, key in out["legacy"])
assert out["keys"] == ["aislo:draft:crossw:p1:7", "aislo:draft:pipes:p1"]