Files
Aislo/resources/tester/test_est_quantity_sheets.py
T
eomsangdonandClaude Opus 5.5 507b5a5166 feat(est-test): 수량산출서 검색과 전체보기
- 원본처럼 이름·항목 명칭·규격에서 빈칸·|·괄호를 빼고 찾아 목록을 좁힘
- 고르기 줄을 산출서 모듈로 옮겨 700줄 제한 유지

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

157 lines
6.7 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.
"""EST 테스트 앱 수량산출서 복사·순서 이동과 ESTX 저장 거부."""
import json
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
MAIN = Path("C:/Dasansoft/Est Plus 2/Data/ProjectData/main.estx")
LOAD = """
const fs = require('fs'), vm = require('vm');
const ctx = vm.createContext({ structuredClone, console });
vm.runInContext(fs.readFileSync('tools/est-test/native-quantity-sheets.js', 'utf8'), ctx);
const run = (code) => vm.runInContext(code, ctx);
"""
def node(script: str, *args: str):
out = subprocess.check_output(["node", "-e", LOAD + script, *args], cwd=ROOT)
return json.loads(out.decode("utf-8"))
def test_copy_inserts_below_with_new_code_and_cleared_links():
result = node("""
ctx.project = { quantitySheets: [
{ Code: 'A', Name: '토공', items: [{ Code: 'r000000', TargetCode: 'D1', TargetKey: 'id:3', LinkCode: 'D1' }], rows: [{ LineData: 'x', markers: ['r000000'] }] },
{ Code: 'B', Name: '포장', items: [], rows: [] },
] };
const first = run("EstQuantitySheets.copy(project, 'A', 'u1')");
const second = run("EstQuantitySheets.copy(project, 'A', 'u1')");
const p = ctx.project;
process.stdout.write(JSON.stringify({
first, second, order: p.quantitySheets.map((s) => s.Code), name: p.quantitySheets[1].Name,
link: p.quantitySheets[1].items[0], original: p.quantitySheets[0].items[0].TargetCode,
rows: p.quantitySheets[1].rows[0].markers,
}));
""")
assert result == {
"first": "Qu1",
"second": "Qu1_2",
"order": ["A", "Qu1_2", "Qu1", "B"],
"name": "토공 복사본",
"link": {"Code": "r000000", "TargetCode": "", "TargetKey": ""},
"original": "D1",
"rows": ["r000000"],
}
def test_move_swaps_and_stops_at_edges():
result = node("""
ctx.project = { quantitySheets: [{ Code: 'A' }, { Code: 'B' }, { Code: 'C' }] };
const out = [run("EstQuantitySheets.move(project, 'B', -1)"), run("EstQuantitySheets.move(project, 'B', -1)"),
run("EstQuantitySheets.move(project, 'C', 1)")];
process.stdout.write(JSON.stringify({ out, order: ctx.project.quantitySheets.map((s) => s.Code) }));
""")
assert result == {"out": [True, False, False], "order": ["B", "A", "C"]}
def test_estx_export_refuses_reordered_sheets():
if not MAIN.exists():
pytest.skip("installed EST main sample unavailable")
result = node(
"""
const imp = require('./tools/est-test/import-estx.cjs'), ex = require('./tools/est-test/export-estx.cjs');
ctx.project = imp.importEstx(fs.readFileSync(process.argv[1]));
run("EstQuantitySheets.move(project, project.quantitySheets[0].Code, 1)");
let message = '';
try { ex.exportEstx(ctx.project); } catch (e) { message = e.message; }
process.stdout.write(JSON.stringify(message));
""",
str(MAIN),
)
assert result.startswith("수량산출서 순서 변경은 ESTX")
MARK = r"""(()=>{
const sheet={Code:'N1',options:{digits:2,roundMode:2},items:[{Code:'r000000',Name:'가'}],
rows:[{LineData:' \x0e잔토\x0e \x130.15\x13 2×3 = 6 \x15㎥\x15 그리고 \x125\x12',markers:['r000000']}]};
const shown=EstText.display(sheet.rows[0].LineData);
const at=shown.indexOf('6 ');
const out=[];
const t=(fn)=>{try{fn();out.push('ok');}catch(e){out.push(e.message.slice(0,6));}};
t(()=>EstQuantitySheets.mark(sheet,0,at,at+1,'r000001'));
const item=sheet.items.find(i=>i.Code==='r000001');
const markers=[...sheet.rows[0].markers];
const calc=EstQuantity.calculate(sheet).items.map(i=>[i.Code,i.GN]);
t(()=>EstQuantitySheets.mark(sheet,0,at+4,at+5,'r000002'));
t(()=>EstQuantitySheets.mark(sheet,0,0,3,'r000002'));
const inside=EstText.display(sheet.rows[0].LineData).indexOf('⟦결과⟧6')+5;
t(()=>EstQuantitySheets.free(sheet,0,inside));
const after=EstText.display(sheet.rows[0].LineData);
sheet.items[0].TargetCode='D1';
const last=after.lastIndexOf('⟦결과⟧')-1;
t(()=>EstQuantitySheets.free(sheet,0,last));
return {out,markers,item:[item.Name,item.Size,item.Unite],calc,
back:after===shown,items:sheet.items.map(i=>i.Code)};
})()"""
def test_mark_and_free_quantity_in_existing_line():
files = ["native-math.js", "native-formula.js", "native-text.js", "native-quantity.cjs"]
result = node(
f"""
for (const f of {json.dumps(files)})
vm.runInContext(fs.readFileSync('tools/est-test/' + f, 'utf8'), ctx, {{ filename: f }});
process.stdout.write(JSON.stringify(run({json.dumps(MARK)})));
"""
)
assert result["markers"] == ["r000001", "r000000"]
assert result["item"] == ["잔토", "0.15", "㎥"]
assert ["r000001", 6] in result["calc"]
assert result["back"] is True
assert result["items"] == ["r000000"]
assert [m[:2] for m in result["out"]] == ["ok", "이미", "산출", "ok", "내역"]
def test_estx_export_refuses_marker_edit():
if not MAIN.exists():
pytest.skip("installed EST main sample unavailable")
files = ["native-math.js", "native-formula.js", "native-text.js", "native-quantity.cjs"]
result = node(
f"""
for (const f of {json.dumps(files)})
vm.runInContext(fs.readFileSync('tools/est-test/' + f, 'utf8'), ctx, {{ filename: f }});
const imp = require('./tools/est-test/import-estx.cjs'), ex = require('./tools/est-test/export-estx.cjs');
ctx.project = imp.importEstx(fs.readFileSync(process.argv[1]));
run(`(() => {{
for (const s of project.quantitySheets)
for (let i = 0; i < s.rows.length; i++) {{
const code = s.rows[i].markers[0], item = s.items.find((x) => x.Code === code);
if (!code || !item || item.TargetCode || item.TargetKey) continue;
const t = EstText.display(s.rows[i].LineData);
return EstQuantitySheets.free(s, i, t.indexOf('⟦결과⟧') + 4);
}}
}})()`);
let message = '';
try {{ ex.exportEstx(ctx.project); }} catch (e) {{ message = e.message; }}
process.stdout.write(JSON.stringify(message));
""",
str(MAIN),
)
assert result.startswith("산출 줄의 수량 지정·해제는 ESTX")
def test_sheet_search_ignores_spaces_bars_and_brackets():
result = node("""
const sheet = { Code: 'N1', Name: '토 공(터파기)', items: [{ Name: '잔토|처리', Size: '0.7㎥' }] };
process.stdout.write(JSON.stringify([
run("EstQuantitySheets.matches(" + JSON.stringify(sheet) + ", '토공터파기')"),
run("EstQuantitySheets.matches(" + JSON.stringify(sheet) + ", '잔토 처리')"),
run("EstQuantitySheets.matches(" + JSON.stringify(sheet) + ", '포장')"),
run("EstQuantitySheets.matches(" + JSON.stringify(sheet) + ", '')"),
]));
""")
assert result == [True, True, False, True]