diff --git a/M02_MasterTemplete/M02_MasterTemplete_Labor.css b/M02_MasterTemplete/M02_MasterTemplete_Labor.css index 3a42026b5..e4f13d0f6 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Labor.css +++ b/M02_MasterTemplete/M02_MasterTemplete_Labor.css @@ -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; } diff --git a/resources/tester/ui_checks/44-6_일위대가_표.js b/resources/tester/ui_checks/44-6_일위대가_표.js new file mode 100644 index 000000000..e64d366e3 --- /dev/null +++ b/resources/tester/ui_checks/44-6_일위대가_표.js @@ -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); +})();