343 lines
22 KiB
Python
343 lines
22 KiB
Python
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
from test_est_rea_parity import run
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def test_jdl_duplicate_sources_and_internal_codes_do_not_change_estimate_amounts():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const duplicate=structuredClone(empty);duplicate.name='duplicate';
|
|
duplicate.tables.StuffcDat=[{Code:'M1',Name:'first',TC:100},{Code:'M1',Name:'second',TC:200},{Code:'M1',Name:'third',TC:300}];
|
|
duplicate.tables.EstMainDat=[{Code:'M1',Name:'item',LinkIndex:5,GN:2,GU:200,GC:400,TC:400},{LinkIndex:54}];
|
|
const first=j.output(duplicate),loaded=j.read(first.bytes,empty);
|
|
const collision=structuredClone(empty);collision.name='collision';
|
|
collision.tables.EstiMateDat=[{Code:'LITERAL2',Name:'existing',GC:999,TC:999}];
|
|
collision.tables.EstMainDat=[{Code:'fixed',Name:'fixed',CalcIndex:1,GN:0,GC:80,TC:80},{LinkIndex:54}];
|
|
const second=j.output(collision),files=a.unpack(second.bytes),parts=j.parse('mainpart.txt',files.get('mainpart.txt'));
|
|
const sources=j.parse('w.txt',files.get('w.txt')),target=sources.find(r=>r.F_CODE===parts[0].F_CODE1);
|
|
process.stdout.write(JSON.stringify({duplicateTotal:loaded.tables.EstMainDat.at(-1).TC,
|
|
duplicateSources:j.parse('m.txt',a.unpack(first.bytes).get('m.txt')).length,
|
|
warning:first.warnings.some(x=>x.includes('중복')),fixedPrice:target.F_MPRICE,sourceCount:sources.length}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script], input=json.dumps(project).encode(), cwd=ROOT
|
|
)
|
|
)
|
|
assert result == {
|
|
"duplicateTotal": 400,
|
|
"duplicateSources": 3,
|
|
"warning": True,
|
|
"fixedPrice": 80,
|
|
"sourceCount": 2,
|
|
}
|
|
|
|
|
|
def test_jdl_duplicate_unit_codes_do_not_select_a_wrong_unit_group():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8')),p=structuredClone(empty);p.name='units';
|
|
p.tables.StuffcDat=[{Code:'M',Name:'material',TC:100}];
|
|
p.tables.HeadTitleDat=[{Code:'U',Name:'first',GC:200},{Code:'U',Name:'second',GC:300}];
|
|
p.tables.HeadMainDat=[{Index:1,Code:'U'},{Index:0,Code:'M',LinkIndex:5,GN:2,GU:100,GC:200}];
|
|
p.tables.EstMainDat=[{Code:'U',Name:'item',LinkIndex:103,GN:1,GU:300,GC:300,TC:300},{LinkIndex:54}];
|
|
const out=j.output(p),files=a.unpack(out.bytes),loaded=j.read(out.bytes,empty);
|
|
process.stdout.write(JSON.stringify({units:j.parse('unit.txt',files.get('unit.txt')).length,
|
|
total:loaded.tables.EstMainDat.at(-1).TC,warning:out.warnings.some(x=>x.includes('중복'))}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script], input=json.dumps(project).encode(), cwd=ROOT
|
|
)
|
|
)
|
|
assert result == {"units": 0, "total": 300, "warning": True}
|
|
|
|
|
|
def test_jdl_basic_tables_use_native_separators_encoding_and_preserve_direct_money():
|
|
p = run(
|
|
"math",
|
|
"""(()=>{
|
|
const p=EstNative.empty();p.name='JDL test';p.options.SourceRefresh=false;
|
|
p.tables.StuffcDat=[{PkID:1,Code:'M',Name:'material',InputTC:100,ValueIndex:4}];
|
|
p.tables.EstMainDat=[{PkID:1,Code:'M',Name:'material',LinkIndex:5,GN:10,GU:100},
|
|
{PkID:2,Code:'FIX',Name:'fixed',GN:0,GC:80,TC:80,CalcIndex:1},
|
|
{PkID:3,Code:'SKIP',Name:'excluded',GN:1,GC:999,TC:999,CalcIndex:3},{PkID:4,LinkIndex:54}];
|
|
p.tables.Wonga=[{Gubun:'G',Name:'material',BaseField:'GC'},{Gubun:'T',Name:'total',VSusic:'G'}];
|
|
return EstNative.calculate(p);
|
|
})()""",
|
|
)
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs');
|
|
const p=JSON.parse(fs.readFileSync(0,'utf8')),empty=structuredClone(p);for(const name of Object.keys(empty.tables))empty.tables[name]=[];
|
|
const out=j.output(p),files=a.unpack(out.bytes),next=j.read(out.bytes,empty);
|
|
const raw=files.get('mainpart.txt');
|
|
process.stdout.write(JSON.stringify({next,files:[...files.keys()],tabs:raw.includes(9),terminator:raw.includes(5),warnings:out.warnings}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(p, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert result["tabs"] and result["terminator"]
|
|
assert {"Global.ini", "Main.txt", "mainpart.txt", "CostAccount.txt"}.issubset(result["files"])
|
|
assert result["next"]["tables"]["EstMainDat"][-1]["TC"] == 1080
|
|
assert result["next"]["tables"]["Wonga"][-1]["Cost"] == 1080
|
|
assert result["next"]["options"]["AutoCalc"] is False
|
|
assert result["warnings"]
|
|
|
|
|
|
def test_unchanged_import_preserves_original_jdl_and_edited_work_is_not_silently_discarded():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const original=a.pack(new Map([['Global.ini',Buffer.from('[BASIC]\\r\\n')],
|
|
['Main.txt',Buffer.from('0\\tExample\\t02\\x05\\r\\n')],['extension.bin',Buffer.from([1,2,3,4])]]));
|
|
const p=j.markOriginal(s.calculate(j.read(original,empty)));p.id='0123456789abcdef01234567';
|
|
const unchanged=j.output(s.calculate(structuredClone(p)));
|
|
p.name='Changed';const changed=j.output(s.calculate(p)),files=a.unpack(changed.bytes);
|
|
process.stdout.write(JSON.stringify({unchanged:original.equals(unchanged.bytes),changed:!original.equals(changed.bytes),
|
|
name:files.get('Main.txt').toString().includes('Changed'),warning:changed.warnings.length>0}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert result == {"unchanged": True, "changed": True, "name": True, "warning": True}
|
|
|
|
|
|
def test_basic_jdl_unit_price_parts_import_with_recorded_costs_and_warn_for_special_parts():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const common={F_CODE:'U1',F_CODE1:'M1',F_DES:'material',F_QQTY:2,F_MPRICE:100,F_MCOST:200,F_LOADBM:'T',F_SAVEBM:'T',F_SPROPER:'0',F_KWAN:'0',F_CLASS:'0'};
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['m.txt',table('m.txt',[{F_CODE:'M1',F_DES:'material',F_MPRICE:100}])],
|
|
['unit.txt',table('unit.txt',[{F_CODE:'U1',F_DES:'unit',F_MPRICE:300}])],
|
|
['unitpart.txt',table('unitpart.txt',[{...common,F_SEQ:'1'},{...common,F_SEQ:'2',F_SPROPER:'1'}])]]);
|
|
const out=s.calculate(j.read(a.pack(files),empty));out.options.AutoCalc=true;out.options.SourceRefresh=true;
|
|
const recalculated=s.calculate(structuredClone(out));process.stdout.write(JSON.stringify({rows:out.tables.HeadMainDat,warnings:out.importWarnings,title:recalculated.tables.HeadTitleDat[0]}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
header, detail, remainder = result["rows"]
|
|
assert header["Index"] == 1 and header["TC"] == 300
|
|
assert detail["LinkIndex"] == 5 and detail["GN"] == 2 and detail["GC"] == 200
|
|
assert remainder["CalcIndex"] == 1 and remainder["GC"] == 100
|
|
assert result["title"]["TC"] == 300
|
|
assert any("특수 구성" in warning for warning in result["warnings"])
|
|
|
|
|
|
def test_basic_jdl_unit_price_parts_export_and_reimport():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs');
|
|
const p=JSON.parse(fs.readFileSync(0,'utf8'));p.name='unit';
|
|
p.tables.StuffcDat=[{Code:'M1',Name:'material',TC:100}];
|
|
p.tables.HeadTitleDat=[{Code:'U1',Name:'unit',GC:200,NC:0,JC:0,SC:0}];
|
|
p.tables.HeadMainDat=[{Index:1,Code:'U1',Name:'unit',GC:200,TC:200},
|
|
{Index:0,Code:'M1',Name:'material',LinkIndex:5,GN:2,GU:100,GC:200,TC:200}];
|
|
p.tables.EstMainDat=[{Code:'U1',Name:'unit',LinkIndex:103,GN:1,GU:200,GC:200,TC:200},{LinkIndex:54}];
|
|
const out=j.output(p),files=a.unpack(out.bytes),empty=structuredClone(p);for(const k of Object.keys(empty.tables))empty.tables[k]=[];
|
|
const q=j.read(out.bytes,empty);p.tables.HeadMainDat[1].CalcIndex=1;
|
|
const special=j.output(p),specialFiles=a.unpack(special.bytes);
|
|
process.stdout.write(JSON.stringify({unit:j.parse('unit.txt',files.get('unit.txt')),
|
|
parts:j.parse('unitpart.txt',files.get('unitpart.txt')),rows:q.tables.HeadMainDat,main:q.tables.EstMainDat,
|
|
specialUnits:j.parse('unit.txt',specialFiles.get('unit.txt')).length,specialWarnings:special.warnings.length}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert len(result["unit"]) == len(result["parts"]) == 1
|
|
assert result["parts"][0]["F_QQTY"] == 2 and result["parts"][0]["F_MCOST"] == 200
|
|
assert result["rows"][1]["LinkIndex"] == 5 and result["rows"][1]["GC"] == 200
|
|
assert result["main"][1]["LinkIndex"] == 103
|
|
assert result["specialUnits"] == 0 and result["specialWarnings"] > 0
|
|
|
|
|
|
def test_jdl_machine_saved_amount_is_editable_and_survives_recalculation():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['junit.txt',table('junit.txt',[{F_CODE:'J1',F_DES:'machine',F_MPRICE:100.25,F_LPRICE:50.12,F_EPRICE:25.03}])],
|
|
['jpart.txt',table('jpart.txt',[{F_CODE:'J1',F_SEQ:'1',F_CODE1:'M1'}])],
|
|
['gongjong.txt',table('gongjong.txt',[{F_CODE:'01',F_DES:'work'}])],
|
|
['mainpart.txt',table('mainpart.txt',[{F_CODE:'01',F_SEQ:'1',F_CODE1:'J1',F_DES:'machine',F_QQTY:2,F_MPRICE:100,F_LPRICE:50,F_EPRICE:25}])]]);
|
|
const original=a.pack(files),p=j.markOriginal(s.calculate(j.read(original,empty)));
|
|
const same=original.equals(j.output(s.calculate(structuredClone(p))).bytes);
|
|
p.tables.MachMainDat[1].GC=120.25;
|
|
p.options.AutoCalc=true;p.options.SourceRefresh=true;
|
|
const q=s.calculate(JSON.parse(JSON.stringify(p)));
|
|
process.stdout.write(JSON.stringify({same,rows:q.tables.MachMainDat,title:q.tables.MachTitleDat[0],
|
|
estimate:q.tables.EstMainDat[1],warnings:p.importWarnings,errors:q.calculation.errors}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert result["same"]
|
|
assert result["rows"][1]["CalcIndex"] == 1
|
|
assert abs(result["rows"][1]["TC"] - 195.4) < 1e-8
|
|
assert abs(result["title"]["TC"] - 195.4) < 1e-8
|
|
assert result["estimate"]["TC"] == 390
|
|
assert result["warnings"] and not result["errors"]
|
|
|
|
|
|
def test_jdl_machine_simple_detail_is_editable_and_mismatches_remain_summary():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['junit.txt',table('junit.txt',[{F_CODE:'J1',F_DES:'machine',F_MPRICE:100,F_LPRICE:20,F_EPRICE:10},
|
|
{F_CODE:'J2',F_DES:'mismatch',F_MPRICE:50},{F_CODE:'J3',F_DES:'quantity',F_MPRICE:50}])],
|
|
['jpart.txt',table('jpart.txt',[{F_CODE:'J1',F_SEQ:'1',F_CODE1:'M1',F_DES:'fuel',F_QQTY:1,F_MPRICE:60,F_EPRICE:10},
|
|
{F_CODE:'J1',F_SEQ:'2',F_CODE1:'L1',F_DES:'operator',F_QQTY:1,F_MPRICE:40,F_LPRICE:20},
|
|
{F_CODE:'J2',F_SEQ:'1',F_DES:'incomplete',F_QQTY:1,F_MPRICE:10},
|
|
{F_CODE:'J3',F_SEQ:'1',F_DES:'unknown quantity semantics',F_QQTY:2,F_MPRICE:50}])]]);
|
|
const p=j.read(a.pack(files),empty);p.options.AutoCalc=true;p.options.SourceRefresh=true;
|
|
p.tables.MachMainDat[1].GC=70;const q=s.calculate(p);
|
|
process.stdout.write(JSON.stringify({rows:q.tables.MachMainDat,titles:q.tables.MachTitleDat,errors:q.calculation.errors,warnings:p.importWarnings}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert [row["Name"] for row in result["rows"][:3]] == ["machine", "fuel", "operator"]
|
|
assert result["titles"][0]["TC"] == 140
|
|
assert result["titles"][1]["TC"] == 50
|
|
assert result["titles"][2]["TC"] == 50
|
|
assert "상세 산식 미변환" in result["rows"][-1]["Name"]
|
|
assert result["warnings"] and not result["errors"]
|
|
|
|
|
|
def test_jdl_cost_saved_amount_calculates_and_can_be_edited():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['danga.txt',table('danga.txt',[{F_CODE:'D1',F_DES:'cost',F_MPRICE:100.25,F_LPRICE:50.12,F_EPRICE:25.03,F_MEMO:'source'},{F_CODE:'D2',F_EPRICE:0.000000000001}])],
|
|
['gongjong.txt',table('gongjong.txt',[{F_CODE:'01',F_DES:'work'}])],
|
|
['mainpart.txt',table('mainpart.txt',[{F_CODE:'01',F_SEQ:'1',F_CODE1:'D1',F_DES:'cost',F_QQTY:2,F_MPRICE:100,F_LPRICE:50,F_EPRICE:25}])]]);
|
|
const p=j.read(a.pack(files),empty);p.tables.CostMainDat[1].LineData='120.25 = \\x12100.25\\x12';
|
|
p.options.AutoCalc=true;p.options.SourceRefresh=true;const q=s.calculate(JSON.parse(JSON.stringify(p)));
|
|
process.stdout.write(JSON.stringify({title:q.tables.CostTitleDat[0],tiny:q.tables.CostTitleDat[1],estimate:q.tables.EstMainDat[1],errors:q.calculation.errors,warnings:p.importWarnings}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert abs(result["title"]["TC"] - 195.4) < 1e-8
|
|
assert result["tiny"]["JC"] == 0.000000000001
|
|
assert result["estimate"]["TC"] == 390
|
|
assert result["warnings"] and not result["errors"]
|
|
|
|
|
|
def test_jdl_complete_unit_preserves_difference_from_saved_title():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['m.txt',table('m.txt',[{F_CODE:'M1',F_MPRICE:100}])],
|
|
['unit.txt',table('unit.txt',[{F_CODE:'U1',F_MPRICE:205.25},{F_CODE:'U2',F_LPRICE:30.12}])],
|
|
['unitpart.txt',table('unitpart.txt',[{F_CODE:'U1',F_CODE1:'M1',F_QQTY:2,F_MPRICE:100,F_MCOST:200}])]]);
|
|
const p=j.read(a.pack(files),empty);p.options.AutoCalc=true;p.options.SourceRefresh=true;
|
|
const q=s.calculate(p);process.stdout.write(JSON.stringify({rows:q.tables.HeadMainDat,titles:q.tables.HeadTitleDat}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert result["rows"][2]["GC"] == 5.25
|
|
assert [row["TC"] for row in result["titles"]] == [205.25, 30.12]
|
|
|
|
|
|
def test_jdl_unit_inconsistent_detail_keeps_recorded_amount_without_double_counting():
|
|
project = run("math", "EstNative.empty()")
|
|
script = """const fs=require('fs'),j=require('./tools/est-test/jdl.cjs'),a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json'),s=require('./tools/est-test/server.cjs');
|
|
const empty=JSON.parse(fs.readFileSync(0,'utf8'));
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
const files=new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['m.txt',table('m.txt',[{F_CODE:'M1',F_MPRICE:100}])],
|
|
['unit.txt',table('unit.txt',[{F_CODE:'U1',F_MPRICE:200}])],
|
|
['unitpart.txt',table('unitpart.txt',[{F_CODE:'U1',F_CODE1:'M1',F_QQTY:2,F_MPRICE:100,F_MCOST:0}])]]);
|
|
const p=j.read(a.pack(files),empty);p.options.AutoCalc=true;p.options.SourceRefresh=true;
|
|
const q=s.calculate(p);process.stdout.write(JSON.stringify({rows:q.tables.HeadMainDat,title:q.tables.HeadTitleDat[0],warnings:p.importWarnings}));"""
|
|
result = json.loads(
|
|
subprocess.check_output(
|
|
["node", "-e", script],
|
|
input=json.dumps(project, ensure_ascii=False).encode("utf-8"),
|
|
cwd=ROOT,
|
|
).decode("utf-8")
|
|
)
|
|
assert result["rows"][1]["CalcIndex"] == 1
|
|
assert result["rows"][2]["GC"] == 200
|
|
assert result["title"]["TC"] == 200
|
|
assert any("고정" in warning for warning in result["warnings"])
|
|
|
|
|
|
def test_edge_jdl_machine_amount_edit():
|
|
from playwright.sync_api import sync_playwright
|
|
import pytest
|
|
|
|
script = """const a=require('./tools/est-test/archive.cjs'),schema=require('./tools/est-test/jdl-schema.json');
|
|
const table=(name,rows)=>Buffer.from(rows.map(r=>schema[name].map(f=>r[f.name]??(f.kind===6?'0':'')).join('\\t')+'\\x05\\r\\n').join(''));
|
|
process.stdout.write(a.pack(new Map([['Global.ini',Buffer.from('[BASIC]')],['Main.txt',Buffer.from('0\\tSample\\t02\\x05\\r\\n')],
|
|
['junit.txt',table('junit.txt',[{F_CODE:'J1',F_DES:'machine',F_MPRICE:100,F_LPRICE:50,F_EPRICE:25}])],
|
|
['danga.txt',table('danga.txt',[{F_CODE:'D1',F_DES:'cost',F_MPRICE:100,F_LPRICE:50,F_EPRICE:25}])]])));"""
|
|
data = subprocess.check_output(["node", "-e", script], cwd=ROOT)
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(channel="msedge", headless=True)
|
|
page = browser.new_page()
|
|
try:
|
|
page.goto("http://100.65.141.15:5175", timeout=5000)
|
|
except Exception:
|
|
browser.close()
|
|
pytest.skip("EST server unavailable")
|
|
page.on("dialog", lambda dialog: dialog.accept())
|
|
page.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
page.locator("#jdl-file").set_input_files(
|
|
{"name": "sample.jdl", "mimeType": "application/zip", "buffer": data}
|
|
)
|
|
page.wait_for_function("() => EstApp.state.project.tables.MachMainDat.length === 2")
|
|
assert page.locator("#dialog").is_visible()
|
|
assert "상세 산식" in page.locator("#dialog-content").inner_text()
|
|
page.locator("#dialog").evaluate("(dialog) => dialog.close()")
|
|
page.evaluate("""() => {
|
|
EstApp.state.project.options.AutoCalc=true;
|
|
EstApp.navigate('MachMainDat','J1');
|
|
}""")
|
|
amount = page.locator('[data-table="MachMainDat"][data-row="1"][data-field="GC"]')
|
|
amount.fill("120")
|
|
amount.press("Tab")
|
|
page.wait_for_function("() => EstApp.state.project.tables.MachTitleDat[0].TC === 195")
|
|
assert page.evaluate("EstApp.state.project.tables.MachMainDat[1].TC") == 195
|
|
page.evaluate("EstApp.navigate('CostMainDat','D1')")
|
|
formula = page.locator('[data-table="CostMainDat"][data-row="1"][data-field="LineData"]')
|
|
formula.fill(formula.input_value().replace("100", "130.25", 1))
|
|
formula.press("Tab")
|
|
page.wait_for_function("() => EstApp.state.project.tables.CostTitleDat[0].TC === 205.25")
|
|
browser.close()
|