# -*- coding: utf-8 -*- """PLAN 224-1 — B05/B06 구조물 조합 고르기 모달 맨 위 = M02 구조물조합 상단 표(구조물집계표). ① 행동(Node · 대역): 모달 상단 표 부품(`ui_template_item_picker_table.ts`)을 표 부품 · 집계표 모듈 · 서버 읽기 대역 위에서 돌려 — 고른 항목의 층 표를 보기 전용으로 그리고, 같은 층 다른 조합 = 열만 옮김 · 다른 층 = 표가 바뀜 · 읽는 사이 바뀌면 마지막 것만 · 번호 읽기 실패해도 표 · 표 읽기 실패 = 까닭 글. ② 같은 부품(소스): M02 관리 화면 · 모달이 같은 `createSheet` · 같은 줄 글 도우미(`numberLabels`) · 같은 숨김 열 규칙(`comboView`)을 씀 · 모달이 상단 표를 배선(고르면 보임 · 편집 화면에선 숨김). """ import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).resolve().parent ROOT = HERE.parents[1] UI = ROOT / "ui_template" M02 = ROOT / "M02_MasterTemplete" def _text(path: Path) -> str: return path.read_text(encoding="utf-8") @pytest.fixture(scope="module") def out(): proc = subprocess.run( ["node", str(HERE / "helper_224_1_picker_top_table.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_처음엔_숨김_고르면_보임_비우면_다시_숨김(out): assert out["startHidden"] is True assert out["nullHidden"] is True assert out["nullCalls"] == [] # 고른 것 없으면 서버도 안 부름 assert out["shownHidden"] is False assert out["hideAgain"] is True def test_고른_항목_층의_집계표를_보기_전용으로(out): # 그 층 · 그 주인의 구조물집계표 + 번호 목록 assert out["firstReads"] == [ ["readTemplate", "personal", "table", "구조물집계표", None, "1/3"], ["numbers", "personal", "1/3"], ] first = out["first"] assert first["count"] == 1 assert first["readOnly"] is True # 보기 전용 — 고침은 M02 에서 assert first["lockHead"] is True assert first["combo"] is True # M02 「구조물 조합」 상단 표 꼴 assert first["comboDoc"] is True # 숨김 열 규칙 = M02 와 같은 `comboView` assert first["docTag"] == "personal|1/3" assert first["numbersSeen"] == {"rv1": {"도번": "SD1"}} # 줄 글 도우미가 같은 번호 목록을 받음 def test_같은_층_다른_조합은_열만_옮김_다른_층은_표가_바뀜(out): same = out["sameLayer"] assert same["calls"] == [] # 서버 · 표 다시 안 그림 assert same["selected"] == ["rv1", "rv2"] assert same["destroyed"] is False other = out["otherLayer"] assert other["reads"] == [["readTemplate", "system", "table", "구조물집계표", None, None]] assert other["creates"] == 1 assert other["oldDestroyed"] is True # 옛 표를 거둠 assert other["selected"] == ["rv9"] assert other["docTag"] == "system|null" def test_읽는_사이_바뀌면_마지막_조합만(out): assert out["race"] == {"creates": 1, "docTag": "system|null"} def test_번호_읽기_실패해도_표는_그려지고_표_읽기_실패는_까닭_글(out): assert out["numbersFail"] == {"creates": 1, "seen": {}} assert out["tableFail"] == {"creates": 0, "text": "표 실패 그 층은 아직 만든 것이 없음"} def test_표_키_같은_층_주인이면_같고_층_주인이_다르면_다름(out): assert out["keys"] == { "mineSame": True, "layerDiffers": True, "ownerDiffers": True, "mine": "personal|1/3", } def test_모달과_M02_가_같은_표_부품_줄_글_도우미_숨김_열_규칙(): table = _text(UI / "ui_template_item_picker_table.ts") main = _text(M02 / "M02_MasterTemplete_UI_Main.ts") struct = _text(M02 / "M02_MasterTemplete_Structure.ts") # 같은 표 부품(관리 화면은 이 파일을 glob 으로 받음) assert 'import("./sheet/ui_template_sheet")' in table assert '"../ui_template/sheet/ui_template_sheet.ts"' in main # 보기 전용 · 상단 표 꼴 assert "readOnly: true," in table and "combo: {}," in table # 줄 글 도우미 한 벌 — 둘 다 같은 함수 assert "export function numberLabels(" in struct assert "...struct.numberLabels(() => numbers)," in table assert "...numberLabels(struct.numbers)" in main # 숨김 열 규칙 한 벌 assert "struct.comboView(got.문서)" in table assert "comboView(doc)" in main # 서버 읽기 = 고른 층 · 주인 · 같은 집계표 이름 assert 'readTemplate(layer, "table", struct.STRUCTURE_TABLE, null, owner)' in table assert 'STRUCTURE_TABLE = "구조물집계표"' in struct def test_모달_배선_고르면_보이고_편집_화면에서는_숨김(): ts = _text(UI / "ui_template_item_picker.ts") assert "createComboTable((colId) => pickColumn(colId))" in ts # 280-2 표 고름 → 나무 assert "paintTable();" in ts # 고른 항목 · 층이 바뀔 때마다(280-2) assert "body.append(tableWrap, cols, editHost," in ts # 맨 위 assert ts.count("tableWrap.hidden = true;") == 1 # 편집 화면 열 때 assert ts.count("tableWrap.hidden = false;") == 1 # 돌아올 때 assert "comboTable.destroy();" in ts # 닫을 때 표 거둠 def test_표_높이_제한과_숨김_css(): css = _text(UI / "ui_template_item_picker.css") assert ".ui-item-picker__table .ui-sheet__scroll {" in css assert "max-height: 26vh;" in css assert ".ui-item-picker__table-wrap[hidden]" in css def test_번호_읽기_층_길_추가_지금_층을_안_바꿈(): api = _text(M02 / "M02_MasterTemplete_Api_Fetch.ts") assert "export const fetchStructureNumbersAt = (" in api assert "call(owned(layer, `/layers/${layer}/structures/numbers`, owner));" in api