Files
Aislo/resources/tester/helper_202_1_fill_below.cjs
T
eomsangdonandClaude Opus 5.5 a8cf79cee0 fix(공용 표 높이): 창 끝까지 셈(spaceBelow)이 열린 창 가림막 · 알림(fixed · absolute)을 표 아래 자리로 재던 흠 (PLAN 707-5 딸림)
- body 끝 가림막(창 높이)이 뒤 형제로 잡혀 창이 열린 채 다시 그리면 표가 최소 120px 로 짜부
- 흐름 밖(position fixed · absolute) 형제 = 자리 안 씀
- 부품 모음 견본(화면 끝 표 · 견본 창): 전 794 → 120px · 뒤 794 → 794px(밝음 · 어두움)
- 시험 test_202_1 가림막 줄 덧붙임

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 17:14:51 +09:00

92 lines
3.1 KiB
JavaScript

/* 202-1 — 표 칸 아래로 간 안내 줄 몫이 창 끝까지 셈(`ui_template_data_table.ts` fillViewport)에 들어가는지 단위검증 헬퍼.
* 카드 본문 = [표 칸][아래 줄][안내 줄 · 안내 줄 …](B08 `tableCard` 꼴) 가짜 DOM 에서 돌리고 JSON 으로 냄. */
const fs = require("fs");
const path = require("path");
const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript"));
const file = path.join(__dirname, "..", "..", "ui_template", "ui_template_data_table.ts");
const js = ts.transpileModule(fs.readFileSync(file, "utf8"), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText;
const win = { innerHeight: 900, scrollY: 0, addEventListener() {}, removeEventListener() {} };
const observers = [];
class RO {
constructor(fn) {
this.fn = fn;
observers.push(this);
}
observe() {}
disconnect() {}
}
const el = (name, css = {}, height = 0) => ({
name,
css,
height,
top: 0,
parentElement: null,
nextElementSibling: null,
isConnected: true,
style: {},
getBoundingClientRect() {
return { top: this.top, height: this.height };
},
});
function link(parent, ...kids) {
kids.forEach((k, i) => {
k.parentElement = parent;
k.nextElementSibling = kids[i + 1] ?? null;
});
return parent;
}
const sty = (n) => ({
rowGap: n.css.rowGap ?? "normal",
paddingBottom: n.css.paddingBottom ?? "0px",
borderBottomWidth: n.css.borderBottomWidth ?? "0px",
marginBottom: n.css.marginBottom ?? "0px",
position: n.css.position ?? "static",
});
const box = { exports: {} };
new Function(
"exports",
"module",
"require",
"window",
"document",
"getComputedStyle",
"ResizeObserver",
js,
)(box.exports, box, (p) => (p.endsWith(".css") ? {} : require(p)), win, { body: null }, sty, RO);
const m = box.exports;
// 문서: body(padding-bottom 8) > card(padding-bottom 12 · gap 8) > [root][avg 20][info 30][hint 40]
const body = el("body", { paddingBottom: "8px" });
const card = el("card", { paddingBottom: "12px", rowGap: "8px" });
const root = el("root");
const avg = el("avg", {}, 20);
const info = el("info", {}, 30);
const hint = el("hint", {}, 40);
link(body, card);
link(card, root, avg, info, hint);
root.top = 200;
m.fillViewport(root);
observers.forEach((o) => o.fn());
const out = { first: parseFloat(root.style.maxHeight) };
out.below = m.spaceBelow(root);
out.belowExpected = 3 * 8 + 20 + 30 + 40 + 12 + 8; // 줄 사이 8 셋 · 아래 줄 · 안내 둘 · 카드 · 본문 여백
out.bottom = root.top + out.first + out.below; // 문서 맨 아래 = 창 아래 끝(페이지 스크롤 0)
out.viewport = win.innerHeight;
// 안내 줄이 두 줄로 늘어남 → 표 칸이 그만큼 줄어듦
hint.height = 60;
observers.forEach((o) => o.fn());
out.afterHintGrow = parseFloat(root.style.maxHeight);
out.firstMinusGrow = out.first - 20;
// 열린 창 가림막(body 끝 · position fixed · 창 높이) = 아래 자리에 안 셈(707-5)
link(body, card, el("backdrop", { position: "fixed" }, 900));
out.belowWithModal = m.spaceBelow(root);
out.belowAfterGrow = 3 * 8 + 20 + 30 + 60 + 12 + 8;
console.log(JSON.stringify(out));