"""462 B05 · B06 한 페이지 — 시설 줄 페이지 한 벌(요구 271-5 · 분석 4장 (A) · (E)). ① R3 뒤집기 — B06 만 연 채 351 관 → 360 → 버림 → 카드가 351 관 id 를 물어 헛 id → 목록 다시 실음 = 장부 한 줄(처음 id · 351) · 옛 코드 = {s1@360 헛 · s2@351}(장부 맞춤이 B05 보기에만) ② 같은 조작 — B05 먼저 듣는 중 = B06 먼저(끝에 B05 가 읽음) · 알약 · 측점 · 흙덮기 관 · 종단도 받은 것 같음 · 헛 id 0 ③ 노선 따라감 = 편집 안 옮김 · 숨었던 보기가 같은 목록을 다시 실음 = 안 옮김 · 측점 다시 안 씀 · 사용자 옮김 = 옮김 ④ 이음 — 관 알림 · 노선 따라감 · B06 목록이 페이지 한 벌로 · 보기는 읽기만 · B05 → B06 관 옵션 = 세션 칸 TS 셈은 `helper_271_facility_lane.cjs`. ./venv/Scripts/python.exe -m pytest resources/tester/test_271_facility_lane.py -q """ import json import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HELPER = Path(__file__).with_name("helper_271_facility_lane.cjs") pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules" / "typescript").is_dir(), reason="프론트엔드 의존성 미설치", ) def src(*parts: str) -> str: return ROOT.joinpath(*parts).read_text(encoding="utf-8") @pytest.fixture(scope="module") def got() -> dict: run = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", str(HELPER)], capture_output=True, text=True, encoding="utf-8", timeout=120, ) assert run.returncode == 0, run.stderr return json.loads(run.stdout) def test_B06_만_열어도_장부_헛_id_없음(got) -> None: r3 = got["r3"] assert r3["first"] == r3["moved"] == "pipe-s1" # 옮겨도 그 id assert r3["ghostBeforeReload"] is True # 버린 사이 카드가 지은 헛 id(재현) assert r3["after"] == [{"id": "pipe-s1", "at": 351}] # 다시 실으면 처음 id 한 줄 assert r3["afterId"] == "pipe-s1" assert r3["marks"] == [["pipe-s1", "pipe", 351]] def test_B06_먼저_B05_먼저_같음(got) -> None: first, late = got["b05First"], got["b06First"] for key in ("marks", "stations", "minCover", "resets"): assert first[key] == late[key], key assert first["stations"] == [60, 120, 135, 140, 145, 230] assert first["minCover"] == [60, 120, 230] for one in (first, late): assert one["profileMarks"] is True and one["profileStations"] is True assert one["ghostIds"] == 0 assert first["heardB05"] == 6 # 숨은 보기도 바뀔 때마다 들음 def test_노선_따라감은_편집_안_옮김(got) -> None: follow = got["follow"] assert follow["followed"] == {"stations": [95, 145, 150, 155], "resets": []} assert follow["reshown"] == {"resets": 0, "writes": 0} assert follow["userMove"] == [[145, 165], [150, 170], [155, 175]] def test_이음_페이지_한_벌() -> None: shared = src("A00_Common", "design", "design_shared.ts") changed = shared[shared.index("onPipesChanged: (pipes) => {") :] changed = changed[: changed.index("},")] assert changed.index("shared.lane.set({ pipes });") < changed.index("toAll(") assert "shared.lane.follow();" in shared[shared.index("onFacilitiesFollowed: (far)") :][:200] assert "shared.lane.paint();" in shared # 종단도가 막 섰을 때 page = src("A00_Common", "design", "design_page.ts") assert "lane: createFacilityLane(projectId, () => shared.profile)," in page assert "shared.lane.dispose();" in page # 종단도에 알약 · 측점 · 흙덮기 관을 쓰는 자리 = 시설 줄 하나 for parts in ( ("A00_Common", "design", "design_view_profile.ts"), ("B05_Profile", "B05_Profile_UI_Page_Structures.ts"), ("B06_Section", "B06_Section_UI_Section_View_Profile.ts"), ): text = src(*parts) for call in ( "setIrregularStations(", "setMinCoverPipes(", "placePipeIds(", "prunePipeIds(", ): assert call not in text, (parts[-1], call) assert "planStations(" not in text, parts[-1] panel = src("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts") push = panel[panel.index("const pushMarks") :] assert "deps.shared.lane.set({ structures, pipes: pipeFacilities }, carryEdits);" in push[:600] view = src("A00_Common", "design", "design_view_profile.ts") assert "marks: shared.lane.marks," in view and "types: shared.lane.types," in view def test_관_옵션_넘김은_세션_칸() -> None: shared = src("A00_Common", "design", "design_shared.ts") assert "pipeOptionQueue" not in shared assert 'writeState("pipe-option-queue"' in shared assert '"pipe-option-queue": { bucket: "draft", scope: "project" },' in src( "A00_Common", "b_page_state.ts" )