"""EST 테스트 앱 정렬·데이타 위치정리·호표 정리(원본 BarSort·TFRMTABLESORT·popTitleSort).""" 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-engine.js", "native-row-match.js", "native-escalation.js", "native-progress.js", "native-business.js", "native-review.js", "native-resources.js", "native-schedule.js", "native-model.js", "native-verify.js", "native-tidy.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 }}); ctx.source = JSON.parse(fs.readFileSync('tools/est-test/sample.json', 'utf8')); 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_sort_base_groups_by_gangub_and_drops_blank(): result = run_js( """(() => { const p = { tables: { StuffcDat: [ { Index: 1, Code: 'M3', Name: '철근', Gangub: 0 }, { Index: 2, Code: 'M1', Name: '레미콘', Gangub: 1 }, { Index: 3, Code: 'M2', Name: '거푸집', Gangub: 0 }, { Index: 0, Code: 'M9', Name: '번호없음' }, { Index: 4 } ] } }; const dropped = EstTidy.sortBase(p, 'StuffcDat'); const s = { tables: { SilJukDat: [{ Index: 1, Code: 'S2', Name: '가' }, { Index: 2, Code: 'S1', Name: '나' }] } }; EstTidy.sortBase(s, 'SilJukDat', true); let bad = ''; try { EstTidy.sortBase(p, 'HeadMainDat'); } catch (e) { bad = e.message.slice(0, 4); } return { order: p.tables.StuffcDat.map((r) => [r.Code, r.Index]), dropped, code: s.tables.SilJukDat.map((r) => r.Code), bad }; })()""" ) assert result == { "order": [["M2", 1], ["M3", 2], ["M1", 3]], "dropped": 2, "code": ["S1", "S2"], "bad": "자재·노", } def test_arrange_groups_and_number_heads_keep_totals(): result = run_js( """(() => { const calc = (x) => EstNative.calculate(EstModel.validate(x)); const p = calc(structuredClone(source)); const total = p.calculation.total; const n = EstTidy.arrange(p, 'HeadMainDat', false, 10); const heads = [...EstNative.groups(p.tables.HeadMainDat).values()].map((g) => g.rows[0]); const sorted = heads.every((h, i) => i === 0 || String(heads[i - 1].Name) <= String(h.Name)); const numbers = heads.map((h) => h.Index); const titles = p.tables.HeadTitleDat.filter((t) => heads.some((h) => h.Code === t.Code)).every((t) => t.Index === heads.find((h) => h.Code === t.Code).Index); EstTidy.numberHeads(p, 'HeadMainDat', 1); const after = calc(p); return { n: n === heads.length, sorted, first: numbers[0], step: numbers[1] - numbers[0], titles, renum: [...EstNative.groups(p.tables.HeadMainDat).values()].map((g) => g.rows[0].Index).join() === heads.map((_, i) => i + 1).join(), total: after.calculation.total === total, errors: after.calculation.errors.length }; })()""" ) assert result == { "n": True, "sorted": True, "first": 10, "step": 1, "titles": True, "renum": True, "total": True, "errors": 0, }