Files
Aislo/resources/tester/test_ui_data_table.py
T
eomsangdonandClaude Sonnet 5.5 5f8f909b65 fix(731-1): 일위대가표 줄 끝 ⋯ 단추 — 우클릭 · 길게 누름 없이도 위로 · 아래로 · 별칭 · 삭제
- 마우스 우클릭 · 길게 누름 삭제는 개인 · 마스터 층 모두 이미 되었음(재현 0) — 삭제 길이 눈에 안 보이는 것이 까닭
- 공용 표(ui_template_data_table)에 rowMenu 옵션 추가(첫 칸 오른쪽 ⋯ · 누르면 줄 누름 없이 메뉴만) · 일위대가표가 같은 메뉴를 연결
- 지킴 시험 test_ui_data_table 에 rowMenu 한 건

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 13:19:34 +09:00

137 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- 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 "&lt;b&gt;" in r["escaped"] and "a&amp;&lt;" 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="--dt-w:350px"' in w # 표 폭 = 112 + 98 + 140 (258-1 · css 변수)
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"]
def test_줄_끝_메뉴_단추_731(r):
"""rowMenu — show 참인 줄의 첫 칸에만 ⋯ 단추 · 없으면 단추 없음 · 줄 번호가 data-more 로."""
rows = r["rowMenu"].split("<tbody>")[1].split("</tbody>")[0].split("</tr>")[:3]
assert "data-more" not in rows[0]
for i in (1, 2):
assert rows[i].count("data-more") == 1
assert f'data-more="{i}"' in rows[i]
assert rows[i].split("</td>")[0].count("data-more") == 1 # 첫 칸 안
assert 'class="ui-icon-btn ui-icon-btn--ghost ui-data-table__more"' in rows[1]
assert "data-more" not in r["noRowMenu"]