test(M02): 44-6 일위대가 표 화면 시나리오 · 옵션 값 줄 한 줄 높이

- 옵션 값 줄 칸 위 여백 없앰 · 작은 글(줄 높이 42 → 22)
- resources/tester/ui_checks/44-6_일위대가_표.js 시나리오 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
This commit is contained in:
2026-10-05 11:28:05 +09:00
co-authored by Claude Opus 5.5
parent 411ad7de7d
commit 32192e819a
2 changed files with 107 additions and 2 deletions
@@ -79,12 +79,17 @@
}
/* 옵션 값 줄(44-6) — 이름 ~ 합계에 걸친 한 줄 말줄임(max-width 0 = 표 폭을 안 늘림) · 위 줄과 한 덩이 */
.m02-labrow .m02-labrow__optrow td {
padding-top: 0;
padding-bottom: var(--spacing-4);
font-size: var(--text-caption);
line-height: 1.5;
}
.m02-labrow__opt {
max-width: 0;
overflow: hidden;
padding-top: 0;
color: var(--color-text-secondary);
font-size: var(--text-caption);
white-space: nowrap;
text-overflow: ellipsis;
}
@@ -0,0 +1,100 @@
/* 44-6 일위대가 단가산출 로직 표 — `orca eval --expression "$(cat 이 파일)"` 한 번에 돎 · JSON 돌려줌.
*
* 시작 화면: M02 마스터 템플릿(시스템 관리자) · 좌측 일위대가 줄 「SU-000003」 이 보이는 상태 ·
* 첫 로직 줄(GF000219 돌쌓기)에 고르기 입력이 있음 · 저장은 안 함(끝에 [다시 열기] → 확인 → 버림).
* 기대 수치:
* heads[2] = "별칭" · alias.inputs = 줄 수 · foot.totalBorder ≥ 1.5(2px · 화면 배율) · foot.totalBg ≠ 다른 금액 칸 배경
* opt.row = true · opt.colspan = 8(이름 ~ 합계) · opt.nowrap = "nowrap" · opt.ellipsis = "ellipsis" ·
* opt.height < 30(한 줄) · opt.mainGrow ≤ 2(옵션을 넣어도 위 줄 높이 그대로) · opt.title = 옵션 글 전체
* alias.noModal = true(칸 누름이 입력 모달을 안 엶) · alias.dirty = true · alias.kept = "시험별칭"(다시 그려도 남음)
* discarded = true(버린 뒤 별칭 빈 칸 · 옵션 줄 처음과 같음)
*/
(async () => {
const W = (ms) => new Promise((r) => setTimeout(r, ms));
const $ = (s, root = document) => root.querySelector(s);
const $$ = (s, root = document) => [...root.querySelectorAll(s)];
const btn = (root, text) => $$("button", root).find((b) => b.innerText.trim() === text);
const out = {};
const side = $$(".m02-side__item").find((b) => b.innerText.startsWith("SU-000003"));
if (!side) return JSON.stringify({ error: "SU-000003 줄 없음" });
side.click();
await W(5000);
const table = () => $(".m02-labrow");
const first = () => $("tbody tr[data-labor-logic]", table());
const key = first()?.getAttribute("data-labor-logic");
if (!key) return JSON.stringify({ error: "로직 줄 없음" });
const optRow = () => $(`tr[data-labor-opt="${key}"]`, table());
out.heads = $$("thead th", table()).map((t) => t.innerText.trim());
// ③ 전체 합계 칸
const total = $("tfoot .m02-labrow__total", table());
const other = $$("tfoot .m02-labrow__money", table())[0];
const cs = total && getComputedStyle(total);
out.foot = {
total: !!total,
totalBorder: cs ? parseFloat(cs.borderTopWidth) : 0,
totalBg: cs?.backgroundColor,
otherBg: getComputedStyle(other).backgroundColor,
};
out.foot.colored = out.foot.totalBg !== out.foot.otherBg;
// ② 옵션 값 줄 — 입력 모달에서 고르기 칸을 모두 끝 값으로
const optBefore = optRow()?.innerText ?? null;
const mainBefore = first().getBoundingClientRect().height;
$(".m02-labrow__name", first()).click();
await W(500);
const im = $(".m02-labin");
const picked = [];
for (const s of $$("select[data-labor-input]", im)) {
const opts = [...s.options].filter((o) => o.value);
if (!opts.length) continue;
s.value = opts[opts.length - 1].value;
s.dispatchEvent(new Event("change", { bubbles: true }));
picked.push(s.getAttribute("data-labor-input"));
}
btn(im, "확인")?.click();
await W(3500);
const o = optRow();
const td = o && $(".m02-labrow__opt", o);
const tcs = td && getComputedStyle(td);
out.opt = {
picked,
row: !!o,
colspan: td ? Number(td.getAttribute("colspan")) : null,
nowrap: tcs?.whiteSpace,
ellipsis: tcs?.textOverflow,
height: o ? Math.round(o.getBoundingClientRect().height) : null,
mainGrow: Math.round(first().getBoundingClientRect().height - mainBefore),
title: td?.getAttribute("title"),
text: td?.innerText,
inName: !!$(".m02-labrow__name .m02-labrow__note", first())?.innerText.includes(
picked[0] ?? "\u0000",
),
};
// ④ 별칭 — 칸 누름 · 입력 · 다시 그려도 남음
out.alias = { inputs: $$("[data-labor-alias]", table()).length };
const ai = $("[data-labor-alias]", first());
ai.click();
await W(300);
out.alias.noModal = !$(".m02-labin");
ai.value = "시험별칭";
ai.dispatchEvent(new Event("input", { bubbles: true }));
await W(200);
out.alias.dirty =
!!btn($(".m02-main__head"), "저장") && !btn($(".m02-main__head"), "저장").disabled;
// 다시 그림(입력 모달 확인 → 다시 셈) 뒤에도 남는지
$(".m02-labrow__name", first()).click();
await W(500);
btn($(".m02-labin"), "확인")?.click();
await W(3500);
out.alias.kept = $("[data-labor-alias]", first())?.value;
// 버림
btn($(".m02-main__head"), "다시 열기").click();
await W(600);
btn($(".ui-confirm"), "확인")?.click();
await W(4500);
out.after = {
alias: $("[data-labor-alias]", first())?.value,
opt: optRow()?.innerText ?? null,
};
out.discarded = out.after.alias === "" && out.after.opt === optBefore;
return JSON.stringify(out);
})();