- 되돌리기 사진 = 연 프로젝트 초안 칸만(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
78 lines
3.0 KiB
Python
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"]
|