Files
Aislo/resources/tester/test_est_sources.py
T
eomsangdonandClaude Opus 5.5 892285843d feat(est-test): 워드형 수량산출서 표 보존과 편집 도구
- 가져오기가 WPT 표를 버리던 결함 고침: 표 줄(칸·수량 표지·수식·세로병합) 보존, 문서 읽기 native-quantity-wpt.cjs 로 분리
- 표 셀 합·수량 지정·병합/분리·표 만들기·표 모양, 문단·그림·쪽 삽입/삭제·품명/규격 지정·공종명칭 입력·테두리선·산출근거 양식
- 수량 불러오기·수량목록보기·선택수량복사·내역서 수량붙여넣기(연결)
- ESTX 저장은 표 줄을 건너 문단만 맞춤, 표·서식 편집은 거부

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 18:35:50 +09:00

62 lines
2.5 KiB
Python

"""EST 테스트 앱 발췌근거(원본 barbtnColumn — 가격 출처 열 이름·보이기, 숨긴 출처는 단가 고르기에서 제외)."""
import json
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
FILES = [
"native-math.js",
"native-formula.js",
"native-machine.js",
"native-rows.js",
"native-text.js",
"native-quantity-wpt.cjs",
"native-quantity.cjs",
"native-wonga.js",
"native-sources.js",
"native-engine.js",
"native-model.js",
]
def run_js(code: str):
runner = f"""
const fs = require('fs'), vm = require('vm');
const ctx = vm.createContext({{ structuredClone, console }});
for (const f of {json.dumps(FILES)})
vm.runInContext(fs.readFileSync('tools/est-test/' + f, 'utf8'), ctx, {{ filename: f }});
process.stdout.write(JSON.stringify(vm.runInContext({json.dumps(code)}, ctx)));
"""
return json.loads(subprocess.check_output(["node", "-e", runner], cwd=ROOT).decode("utf-8"))
def test_hidden_source_leaves_price_choice_and_labels():
out = run_js(
r"""(() => {
const p = EstNative.empty();
p.options.SourceRefresh = false;
p.tables.StuffcDat = [{ Code: 'M1', Name: '철근', Cost1: 100, Cost2: 80, Cost3: 120, ValueIndex: 0 },
{ Code: 'M2', Name: '모래', Cost1: 100, Cost2: 80, Cost3: 120, ValueIndex: 2 }];
const tc = (q) => EstNative.calculate(q).tables.StuffcDat.map((r) => r.GC);
const before = tc(p);
const list = EstSources.get(p.options, 'StuffcDat');
list[1] = { caption: '물가자료', page: '120', visible: false };
list[2] = { caption: '유통물가', page: '', visible: false };
EstSources.set(p.options, 'StuffcDat', list);
const after = tc(p);
let dup = '';
try { EstSources.set(p.options, 'StuffcDat', list.map(() => ({ caption: '가격정보' }))); } catch (e) { dup = e.message; }
EstSources.set(p.options, 'LaborcDat', list.map(() => ({ caption: '같음' })));
return { before, after, dup, label: EstSources.label(p.options, 'StuffcDat', 'Cost2'),
other: EstSources.label(p.options, 'EstMainDat', 'Cost2'),
cols: EstSources.columns(p.options, 'StuffcDat', ['Code', 'Cost1', 'Cost2', 'Cost3', 'TC']) };
})()"""
)
assert out["before"] == [80, 120]
assert out["after"] == [100, 100]
assert out["dup"] == "같은 발췌근거가 있습니다."
assert out["label"] == "물가자료 (120)"
assert out["other"] == ""
assert out["cols"] == ["Code", "Cost1", "TC"]