- 공용 표 rowClass(줄) 곁값 — 본문 줄 class · 안 주면 글 그대로 · is-title 굵게 - 공용 표 칸 앞 빈칸 · 겹 빈칸 접지 않음(white-space-collapse: preserve-spaces) - B09 일위대가표 = 머리 · 합계 굵게 · 품셈 인용 · 줄 = 들여쓰기 「ㄴ」(2단) - 시험 test_ui_data_table 줄 꼴 · 새 test_155_b09_tabs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KYZ2HWWdUwZWYnn3tQz7X
125 lines
4.8 KiB
Python
125 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""공용 표 양식(PLAN 70-1) 회귀검증 — 묶음 머리 · 고정 열 · 숫자 꼴 · 빈 값 · 합계 · 1,000줄.
|
||
|
||
Node 헬퍼(`helper_ui_data_table.cjs`)가 `ui_template/ui_template_data_table.ts` 를 트랜스파일해
|
||
견본(`fixture_data_table_sample.js` · 머리 3줄 · 30열 · 66줄)으로 HTML 을 만들고, 여기서 판정함.
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
import subprocess
|
||
|
||
import pytest
|
||
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
|
||
@pytest.fixture(scope="module")
|
||
def r():
|
||
proc = subprocess.run(
|
||
["node", os.path.join(HERE, "helper_ui_data_table.cjs")],
|
||
capture_output=True,
|
||
text=True,
|
||
encoding="utf-8",
|
||
timeout=60,
|
||
)
|
||
assert proc.returncode == 0, proc.stderr
|
||
return json.loads(proc.stdout)
|
||
|
||
|
||
def test_견본_크기(r):
|
||
assert r["cols"] == 30
|
||
assert r["headRows"] == 3
|
||
assert r["bodyRows"] == 66
|
||
|
||
|
||
def test_묶음_머리_합침(r):
|
||
first = r["firstHeadRow"]
|
||
# 측점 · 거리 · 유용토 등 묶음 없는 열은 머리 3줄을 세로로 차지
|
||
assert 'rowspan="3" class="is-frozen is-edge" style="left:0px" title="측점">측점</th>' in first
|
||
assert first.count('rowspan="3"') == 5 # 측점 거리 유용토 차인토량 누가토량
|
||
assert 'colspan="13">절토</th>' in first # 토사 · 연암 · 측구파기 토사 · 암 각 3 + 보정량계
|
||
assert 'colspan="4">면고르기</th>' in first
|
||
assert 'colspan="2">노면정리</th>' in first
|
||
second = r["secondHeadRow"]
|
||
assert 'colspan="3">토사</th>' in second and 'colspan="3">연암</th>' in second
|
||
assert 'rowspan="2" data-num="" title="보정량계"' in second # 한 단 묶음은 머리 2줄
|
||
|
||
|
||
def test_고정_열과_숫자_칸(r):
|
||
row = r["firstBodyRow"]
|
||
assert row.startswith('<tr><td class="is-frozen is-edge" style="left:0px">120</td>')
|
||
assert r["frozenCells"] == 66
|
||
assert '<td data-num="">0</td>' in row # 거리 0 은 빈 값 아님
|
||
|
||
|
||
def test_숫자_꼴(r):
|
||
f = r["fmt"]
|
||
assert f["thousands"] == "1,234,567.89"
|
||
assert f["neg"] == "-97.90"
|
||
assert f["zero"] == "0.00"
|
||
assert f["nul"] == f["undef"] == f["blank"] == f["nan"] == "-"
|
||
assert f["text"] == "120+18" and f["textNum"] == "5"
|
||
|
||
|
||
def test_합계_줄(r):
|
||
assert r["foot"].startswith('<tr><td class="is-frozen is-edge" style="left:0px">합계</td>')
|
||
assert "is-empty" in r["foot"] # 누가토량 합계는 비움
|
||
assert r["noTotal"] is False
|
||
|
||
|
||
def test_글_새지_않음(r):
|
||
assert "<b>" in r["escaped"] and "a&<" in r["escaped"]
|
||
|
||
|
||
def test_천_줄_빠름(r):
|
||
assert r["bigRows"] == 1000
|
||
assert r["bigMs"] < 300
|
||
|
||
|
||
def test_보이는_줄만_그림(r):
|
||
w = r["win"]
|
||
assert w["n"] == 62 # 위 빈 줄 + 60줄 + 아래 빈 줄
|
||
assert 'style="height:1525px"><td colspan="30">' in w["top"] # 61줄 × 25
|
||
assert w["second"].startswith(
|
||
'<tr class="is-alt">'
|
||
) # 61 번째(홀수) 줄 — 번갈아 색은 전체 줄 번호로
|
||
assert 'style="height:21975px"' in w["bottom"] # (1000 - 121) × 25
|
||
|
||
|
||
def test_빈_칸_글_풍선_꾸밈_옵션(r):
|
||
o = r["opts"]
|
||
assert '<td class="is-empty"></td>' in o # empty="" — 「-」 대신 빈칸
|
||
assert '<th scope="col" rowspan="1" class="is-missing" title="풍선">메쌓기</th>' in o
|
||
assert 'rowspan="2" class="is-frozen is-edge" style="left:0px" title="측점">측점</th>' in o
|
||
|
||
|
||
def test_줄_누름_옵션일_때만_data_i(r):
|
||
# 95-3 — onRowClick 을 주면 본문 줄에만 data-i · is-clickable(합계 줄 제외) · 안 주면 글 그대로
|
||
pick = r["pick"]
|
||
assert '<tr class="is-clickable" data-i="0">' in pick
|
||
assert '<tr class="is-alt is-clickable" data-i="1">' in pick
|
||
assert pick.count("data-i=") == 2
|
||
assert "data-i" not in r["opts"] and "is-clickable" not in r["foot"]
|
||
|
||
|
||
def test_155_1_글자_14px_열_폭_같은_비율(r):
|
||
# 155-1 — 표 글 12 → 14px · 열 폭(12px 글 기준 값)에 14/12 를 곱함 · 줄 높이 28px
|
||
assert abs(r["scale"] - 14 / 12) < 1e-9
|
||
w = r["widths"]
|
||
assert '<col style="width:112px"><col style="width:98px"><col style="width:140px">' in w
|
||
assert 'style="width:350px"' in w # 표 폭 = 112 + 98 + 140
|
||
assert 'class="is-frozen is-edge" style="left:112px"' in w # 둘째 고정 열 left 도 같이
|
||
assert "font-size: var(--text-body-sm);" in r["css"]
|
||
assert "--dt-row-h: 28px;" in r["css"]
|
||
|
||
|
||
def test_155_2_줄_꼴_곁값(r):
|
||
# 155-2 — rowClass 가 낸 class 를 본문 줄에만 · 빈 값이면 안 붙임 · 앞 빈칸을 접지 않는 서식
|
||
rc = r["rowClass"]
|
||
assert '<tr class="is-title"><td>제 1 호표</td></tr>' in rc
|
||
assert '<tr class="is-alt"><td> ㄴ 석공</td></tr>' in rc
|
||
assert rc.count("is-title") == 1 # 합계 줄엔 안 붙음
|
||
assert "white-space-collapse: preserve-spaces;" in r["css"]
|
||
assert "tr.is-title td" in r["css"]
|