Merge remote-tracking branches 'origin/sub_laptop_5' and 'origin/sub_laptop_6' into sub_laptop_7
This commit is contained in:
@@ -18,6 +18,7 @@ GROUPS = "B09_Estimation/B09_Estimation_UI_Tabs_Groups.ts"
|
||||
# 기억(b_page_state) 대신 Map · 탭 줄(fillTabs) 대신 가짜 button 줄 · 단추(createButton) 대신 가짜 button · 호버(attachHoverInfo) = 부른 자리 기록 · 157-3 원문번호 풍선(raw) 짝
|
||||
STUBS = r"""
|
||||
const kept = new Map();
|
||||
const dateTimeText = (iso) => String(iso).replace("T", " "); // 593-1 PC 시간대 글 — 견본은 시간대 없음
|
||||
const readState = (name) => (kept.has(name) ? JSON.parse(kept.get(name)) : null);
|
||||
const writeState = (name, value) => kept.set(name, JSON.stringify(value));
|
||||
const createButton = (o) => {
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
- 묶음 이름 = 데이터 점검 · 안 설명 글 없음(굳힌 시각 · 까닭 = [업데이트] 공용 호버)
|
||||
- [단가 갱신] → [업데이트] · 낡으면(서버 `book_stale` = 지금 M01 로 굳힌 책과 다름) 점 배지(is-pending)
|
||||
- 「연결 점검」 탭 내용 = 묶음 안 목록(누르면 그 탭 그 줄) · 위 탭 줄에서 뺌 · 첫 탭 = 공사원가계산서
|
||||
- 「연결 점검」 탭 내용 = 묶음 안 목록(누르면 그 탭 그 줄) · 위 탭 줄에서 뺌
|
||||
- 701-2 첫 화면 = 설계내역서 · 목록 머리 「빈 줄 n」 = 설계내역서 금액 모르는 줄(줄마다 하나 · 까닭 모음) ·
|
||||
그 밖(호표 · 재료) = 「그 밖 확인 n곳」(탭 · 키마다 하나)
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -31,15 +33,15 @@ def test_묶음_이름_단추_글_설명_없음():
|
||||
assert "check.draw(payload, sheets);" in SHELL
|
||||
|
||||
|
||||
def test_연결_점검_탭_없음_첫_탭_공사원가계산서():
|
||||
def test_연결_점검_탭_없음_첫_화면_설계내역서():
|
||||
out = run(
|
||||
[TABS],
|
||||
"\nconsole.log(JSON.stringify({ ids: TABS.map(([t]) => t), names: TABS.map(([, n]) => n),"
|
||||
" groups: TAB_GROUPS.map(([n]) => n), first: TABS[0][0] }));",
|
||||
)
|
||||
assert "check" not in out["ids"] and "연결 점검" not in out["names"] + out["groups"]
|
||||
assert out["first"] == "cost" and out["groups"][0] == "공사원가계산서"
|
||||
assert "let current: TabId = TABS[0][0];" in SHELL
|
||||
assert out["first"] == "cost" and out["groups"][0] == "공사원가계산서" # 엑셀 탭 차례 그대로
|
||||
assert 'let current: TabId = "bill";' in SHELL
|
||||
assert "buildCheck" not in SHELL and "check:" not in SHELL
|
||||
|
||||
|
||||
@@ -50,43 +52,64 @@ def test_좌측_목록_이동_호버_배지():
|
||||
const moves = [];
|
||||
const refresh = document.createElement("button");
|
||||
const panel = createCheckPanel(refresh, (link) => moves.push(link));
|
||||
const sheets = { gaps: [
|
||||
{ tab: "dg", key: "DG1", name: "찰쌓기", why: "대가 원천 없음" },
|
||||
{ tab: "material", key: "MT9", name: "모래", why: "단가 없음" },
|
||||
] };
|
||||
const sheets = {
|
||||
bill: { rows: [
|
||||
{ kind: "title", cost: "direct", key: "sec:1", name: "토공사", sum: null },
|
||||
{ kind: "item", cost: "direct", key: "earth:3", name: "제근", sum: null },
|
||||
{ kind: "item", cost: "direct", key: "earth:4", name: "절토", sum: 100 },
|
||||
{ kind: "item", cost: "direct", key: "st:w", name: "옹벽", sum: null },
|
||||
{ kind: "item", cost: "owner", key: "mat:1", name: "레미콘", sum: null },
|
||||
] },
|
||||
gaps: [
|
||||
{ tab: "bill", key: "earth:3", name: "제근", why: "수량 연결 없음" },
|
||||
{ tab: "bill", key: "earth:3", name: "제근", why: "준비공 대가 — 연결 없음" },
|
||||
{ tab: "dg", key: "DG1", name: "찰쌓기", why: "대가 원천 없음" },
|
||||
{ tab: "dg", key: "DG1", name: "찰쌓기", why: "대가 원천 없음" },
|
||||
{ tab: "material", key: "MT9", name: "모래", why: "단가 없음" },
|
||||
],
|
||||
};
|
||||
const payload = { book: { made: "2026-10-01T09:00:00" }, stale: "M01 에서 바뀐 단가 2",
|
||||
notes: ["B08 자재 집계표 못 읽음"], inputs: { missing: ["EQ1", "LB2"] } };
|
||||
panel.draw(payload, sheets);
|
||||
const view = () => ({
|
||||
pending: refresh.classList.contains("is-pending"),
|
||||
texts: panel.list.children.map((c) => c.text),
|
||||
rows: (panel.list.children[1]?.children ?? []).map((r) => [r.dataset.i, r.className, r.text]),
|
||||
rows: [1, 3].flatMap((n) =>
|
||||
(panel.list.children[n]?.children ?? []).map((r) => [r.dataset.i, r.className, r.text])),
|
||||
});
|
||||
const a = view();
|
||||
const rowsBox = panel.list.children[1];
|
||||
const blankBox = panel.list.children[1];
|
||||
const rowsBox = panel.list.children[3];
|
||||
rowsBox.children[1].click();
|
||||
const tipRefresh = hoverCalls.find((h) => h.root === refresh).text();
|
||||
const rowHover = hoverCalls.find((h) => h.root === panel.list);
|
||||
const tipRow = rowHover.text(rowsBox.children[0]);
|
||||
const tipBlank = [0, 1].map((n) => rowHover.text(blankBox.children[n]));
|
||||
panel.draw({ book: null, stale: null }, { gaps: [] });
|
||||
const b = view();
|
||||
const tipEmpty = refreshTip({ book: null, stale: "단가 아직 안 굳힘" });
|
||||
console.log(JSON.stringify({ a, b, moves, tipRefresh, tipRow, selector: rowHover.selector, tipEmpty }));
|
||||
console.log(JSON.stringify({ a, b, moves, tipRefresh, tipRow, tipBlank, selector: rowHover.selector,
|
||||
tipEmpty }));
|
||||
""",
|
||||
)
|
||||
a, b = out["a"], out["b"]
|
||||
assert a["pending"] and not b["pending"]
|
||||
assert a["texts"][0] == "연결 없음 2곳"
|
||||
# 빈 줄 = 직접공사 항목 중 금액 모름(관급 · 제목 · 아는 줄 빼고) · 같은 줄 까닭은 하나로
|
||||
assert a["texts"][0] == "빈 줄 2" and a["texts"][2] == "그 밖 확인 2곳"
|
||||
assert a["rows"] == [
|
||||
["0", "ui-sidebar-row", "찰쌓기일위대가표"],
|
||||
["1", "ui-sidebar-row", "모래재료비목록표"],
|
||||
["0", "ui-sidebar-row", "제근설계내역서"],
|
||||
["1", "ui-sidebar-row", "옹벽설계내역서"],
|
||||
["2", "ui-sidebar-row", "찰쌓기일위대가표"],
|
||||
["3", "ui-sidebar-row", "모래재료비목록표"],
|
||||
]
|
||||
assert a["texts"][2:] == ["B08 자재 집계표 못 읽음", "M01 에 없는 키 2 — EQ1 · LB2"]
|
||||
assert out["tipBlank"][0] == "수량 연결 없음 · 준비공 대가 — 연결 없음"
|
||||
assert out["tipBlank"][1].startswith("금액 모름") # 까닭 없는 빈 줄(이은 대가에 빈 줄)
|
||||
assert a["texts"][4:] == ["B08 자재 집계표 못 읽음", "M01 에 없는 키 2 — EQ1 · LB2"]
|
||||
assert out["moves"] == [{"tab": "material", "key": "MT9"}]
|
||||
assert out["tipRow"] == "대가 원천 없음" and out["selector"] == "[data-i]"
|
||||
assert "단가 굳힘 2026-10-01 09:00:00" in out["tipRefresh"]
|
||||
assert "업데이트 필요 — M01 에서 바뀐 단가 2" in out["tipRefresh"]
|
||||
assert b["texts"] == ["연결 없음 0곳"] and b["rows"] == []
|
||||
assert b["texts"] == ["빈 줄 0"] and b["rows"] == []
|
||||
assert out["tipEmpty"].startswith("단가 아직 안 굳힘") and "업데이트 필요" in out["tipEmpty"]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user