Files
Aislo/resources/tester/test_est_quantity_workflow.py
T

130 lines
6.6 KiB
Python

from test_est_rea_parity import run
def test_quantity_apply_requires_one_detail_row_per_code():
result = run(
"math",
"""(()=>{
function apply(rows,items=[{Code:'r1',GN:7,TargetCode:'X'}]){
const handlers={};
globalThis.document={addEventListener:(name,fn)=>handlers[name]=fn};
const sheet={Code:'Q',rows:[],items,options:{}};
const state={quantitySheet:'Q',project:{quantitySheets:[sheet],tables:{EstMainDat:rows}}};
globalThis.EstApp={state,change:fn=>fn(),render:()=>{}};
EstQuantity.install();handlers.click({target:{closest:selector=>selector==='[data-quantity-apply]'?{}:null}});
return {rows,notice:state.notice||''};
}
return {duplicate:apply([{Code:'X',Level:0,GN:1},{Code:'X',Level:0,GN:2}]),
heading:apply([{Code:'X',Level:1,GN:1}]),
valid:apply([{Code:'X',Level:1,GN:1},{Code:'X',Level:0,GN:2}]),
partial:apply([{Code:'X',Level:0,GN:1}],[{Code:'r1',GN:7,TargetCode:'X'},{Code:'r2',GN:4,TargetCode:'missing'}]),
disconnected:apply([{Code:'X',Level:0,GN:1}],[{Code:'r1',GN:7,TargetCode:'',LinkCode:'X'}])};
})()""",
)
assert [r["GN"] for r in result["duplicate"]["rows"]] == [1, 2]
assert result["duplicate"]["notice"]
assert result["heading"]["rows"][0]["GN"] == 1
assert result["heading"]["notice"]
assert [r["GN"] for r in result["valid"]["rows"]] == [1, 7]
assert result["valid"]["notice"] == ""
assert result["partial"]["rows"][0]["GN"] == 1
assert result["partial"]["notice"]
assert result["disconnected"]["rows"][0]["GN"] == 1
assert result["disconnected"]["notice"]
def test_create_edit_apply_and_delete_quantity_sheet():
result = run(
"math",
"""(()=>{
const handlers={};let id=0;
globalThis.document={addEventListener:(name,fn)=>handlers[name]=fn};
globalThis.crypto={randomUUID:()=>String(++id)};globalThis.confirm=()=>true;
const state={quantitySheet:'manual',project:{quantitySheets:[],tables:{EstMainDat:[{Code:'X',Level:0,GN:1}]}}};
globalThis.EstApp={state,change:fn=>fn(),render:()=>{}};
EstQuantity.install();
const click=(selector,dataset={})=>handlers.click({target:{closest:s=>s===selector?{dataset}:null}});
const change=(dataset,value)=>handlers.change({target:{dataset,value}});
click('[data-quantity-new]');click('[data-quantity-add]');
change({quantityName:''},'Earthwork');
change({quantityItem:'Name',index:'0'},'excavation');
change({quantityTarget:'0'},'X');
change({quantityLine:'0'},'2*3 = ⟦결과⟧0⟦결과⟧');
const saved=JSON.parse(JSON.stringify(state.project));
click('[data-quantity-apply]');
const applied=state.project.tables.EstMainDat[0].GN;
const sheet=state.project.quantitySheets[0];
const computed=EstQuantity.calculate(sheet);
click('[data-quantity-delete-row]',{quantityDeleteRow:'0'});
const empty=[sheet.rows.length,sheet.items.length];
click('[data-quantity-delete-sheet]');
return {saved,applied,computed,empty,remaining:state.project.quantitySheets.length,selection:state.quantitySheet};
})()""",
)
assert result["saved"]["quantitySheets"][0]["Name"] == "Earthwork"
assert result["saved"]["quantitySheets"][0]["items"][0]["Name"] == "excavation"
assert result["computed"]["errors"] == []
assert result["computed"]["items"][0]["GN"] == 6
assert result["applied"] == 6
assert result["empty"] == [0, 0]
assert result["remaining"] == 0
assert result["selection"] == "manual"
def test_insert_and_move_quantity_rows_keeps_item_results_linked():
result = run(
"math",
"""(()=>{
const handlers={};let id=0;
globalThis.document={addEventListener:(name,fn)=>handlers[name]=fn};
globalThis.crypto={randomUUID:()=>String(++id)};
const state={quantitySheet:'manual',project:{quantitySheets:[],tables:{EstMainDat:[]}}};
globalThis.EstApp={state,change:fn=>fn(),render:()=>{}};EstQuantity.install();
const click=(selector,dataset={})=>handlers.click({target:{closest:s=>s===selector?{dataset}:null}});
click('[data-quantity-new]');click('[data-quantity-add]');click('[data-quantity-add]');
const sheet=state.project.quantitySheets[0];
sheet.rows[0].LineData='1+2 = \\x120\\x12';sheet.rows[1].LineData='4+5 = \\x120\\x12';
click('[data-quantity-add]',{index:'0'});
sheet.rows[1].LineData='6+7 = \\x120\\x12';
const before=EstQuantity.calculate(sheet).items.map(x=>x.GN);
click('[data-quantity-move]',{index:'2',quantityMove:'-1'});
const after=EstQuantity.calculate(sheet).items.map(x=>x.GN);
const order=sheet.rows.map(x=>x.LineData);
sheet.rows[0].LineData='A=2 = \\x120\\x12';sheet.rows[1].LineData='A*3 = \\x120\\x12';
const linked=EstQuantity.calculate(sheet);
click('[data-quantity-move]',{index:'1',quantityMove:'-1'});
const forward=EstQuantity.calculate(sheet);
return {before,after,order,linked,forward};
})()""",
)
assert result["before"] == result["after"] == [3, 9, 13]
assert result["order"][1].startswith("4+5")
assert result["linked"]["errors"] == []
assert result["linked"]["items"][1]["GN"] == 6
assert result["forward"]["errors"]
def test_manual_and_selected_sheet_totals_validate_before_application():
result = run(
"math",
"""(()=>{
const p=EstNative.empty();
p.tables.EstMainDat=[{Code:'X',Level:0,GN:1,MulCode:{binary:'YWJj'}}];
p.quantities=[{Code:'A',formula:'2',TargetCode:'X'},
{Code:'B',formula:'[A]*3',TargetCode:'X'}];
const manual=EstQuantity.totals(p,'manual');EstQuantity.applyTotals(p,manual);
const a=structuredClone(p.tables.EstMainDat[0]);
p.quantitySheets=[{Code:'Q',options:{},rows:[{LineData:'4+5 = \\x120\\x12',markers:['r1']}],
items:[{Code:'r1',GN:0,TargetCode:'X'}]}];
const sheet=EstQuantity.totals(p,'Q');EstQuantity.applyTotals(p,sheet);
let invalid='';p.quantities.push({Code:'C',formula:'1',TargetCode:'missing'});
try{EstQuantity.totals(p,'manual')}catch(e){invalid=e.message}
return {a,b:p.tables.EstMainDat[0],invalid};
})()""",
)
assert result["a"]["GN"] == 8
assert result["a"]["MulCode"] == {"binary": "YWJj"}
assert result["b"]["GN"] == 9
assert result["b"]["MulCode"] == {"binary": "YWJj"}
assert result["invalid"]