/* 집수정 「동물이동형」 칸(PLAN 173-7 · 177-2 고르기 유 / 무) 단위검증 헬퍼 — 공용 명세 폼을 그 자리에서 트랜스파일해 Node 로 돌린다. * 빈 값 = 유("true" 적힘) · 무 = "false" · 다시 유 = "true" · 흙막이 갈래엔 칸 없음. 결과는 표준출력에 JSON 한 벌. * 짝 = `test_173_7_inlet_animal.py` · 화면 그릇 흉내는 `helper_54_10_soil_tiers.cjs` 꼴(+ 듣개). */ const fs = require("fs"); const path = require("path"); const { makeLoader } = require("./helper_ts_stub_loader.cjs"); const CATALOG = require("./helper_322_catalog_module.cjs"); // 구조물 표(322-1) const ROOT = path.join(__dirname, "..", ".."); class FakeNode { constructor(tag) { this.tagName = tag.toUpperCase(); this.children = []; this.dataset = {}; this.style = {}; this._classes = new Set(); this._on = {}; this._text = ""; this.value = ""; const self = this; this.classList = { add: (...n) => n.forEach((c) => self._classes.add(c)), remove: (...n) => n.forEach((c) => self._classes.delete(c)), toggle: (c, f) => (f ?? !self._classes.has(c)) ? self._classes.add(c) : self._classes.delete(c), contains: (c) => self._classes.has(c), }; } set className(v) { this._classes = new Set(String(v).split(/\s+/).filter(Boolean)); } set textContent(v) { this._text = String(v); this.children = []; } get textContent() { return this._text + this.children.map((c) => c.textContent ?? "").join(""); } append(...kids) { kids.forEach((k) => this.children.push(typeof k === "string" ? { textContent: k } : k)); } replaceChildren(...kids) { this.children = []; this.append(...kids); } add(kid) { this.children.push(kid); } setAttribute(n, v) { this[n] = v; } addEventListener(type, fn) { (this._on[type] ??= []).push(fn); } fire(type) { (this._on[type] ?? []).forEach((fn) => fn({ target: this })); } closest() { return null; } matches(sel) { return sel.split(",").some((s) => { s = s.trim(); return s.startsWith(".") ? this._classes.has(s.slice(1)) : this.tagName === s.toUpperCase(); }); } querySelectorAll(sel) { const found = []; const walk = (n) => (n.children ?? []).forEach((k) => { if (k.matches?.(sel)) found.push(k); walk(k); }); walk(this); return found; } querySelector(sel) { return this.querySelectorAll(sel)[0] ?? null; } } globalThis.document = { createElement: (t) => new FakeNode(t) }; globalThis.queueMicrotask = (fn) => fn(); globalThis.Option = function (text, value) { const o = new FakeNode("option"); o.textContent = text; o.value = value; return o; }; const STUBS = { "@ui/ui_template_elements": { showToast: () => {} }, "@config/config_frontend": { FORD_MANNING_N: 0.03, FORD_SLOPE: 0.02 }, "./ui_template_checkbox.css": {}, "../../B05_Profile/B05_Profile_UI_Structures_Summary_Row": { buildSummaryRow: () => null }, }; const { loadTs } = makeLoader({ root: ROOT, requireFor: (full) => (request) => { if (CATALOG.isCatalogRequest(request)) return CATALOG; if (STUBS[request]) return STUBS[request]; if (request.startsWith("@util/")) return loadTs(path.join(ROOT, "common_util", `${request.slice(6)}.ts`)); return loadTs(path.join(path.dirname(full), `${request}.ts`)); }, }); const { createSpecForm } = loadTs( path.join(ROOT, "A00_Common", "design", "design_structure_form.ts"), ); const { PIPE_SPEC } = loadTs( path.join(ROOT, "A00_Common", "design", "logic", "design_structure_pipe.ts"), ); const form = createSpecForm(null, {}); // 177-2 — 체크박스 → 고르기(유 / 무) · 저장 글 "true" / "false" 그대로 const box = () => form.root .querySelectorAll("label") .find((l) => l.dataset.specItem === "inlet.animal") ?.querySelector("select") ?? null; const animal = () => form.read().inlet_basin_animal ?? null; const pick = (v) => { const select = box(); select.value = v; select.fire("change"); }; const shown = () => { const select = box(); return select ? { value: select.value, options: select.children.map((o) => [o.value, o.textContent]), saved: animal(), } : null; }; const out = {}; form.write(PIPE_SPEC, { pipe_diameter_mm: 1000, inlet_type: "집수정" }); out.blank = shown(); pick("false"); out.off = shown(); pick("true"); out.on = shown(); form.write(PIPE_SPEC, { pipe_diameter_mm: 1000, inlet_type: "집수정", inlet_basin_animal: "false", }); out.storedOff = shown(); form.write(PIPE_SPEC, { pipe_diameter_mm: 1000, inlet_type: "기슭막이" }); out.soil = { shown: box() !== null, saved: animal() }; out.checkbox = form.root.querySelectorAll("input").some((i) => i.type === "checkbox"); process.stdout.write(JSON.stringify(out));