Spaces:
Running
Running
Download test_engine.cjs from Hugdrigo/impactlab-latam: direct link, hf CLI and curl.
- Browser
- Download file 7.38 kB
-
https://huggingface.co/spaces/Hugdrigo/impactlab-latam/resolve/main/test_engine.cjs
- Command line
-
hf download hf://spaces/Hugdrigo/impactlab-latam/test_engine.cjs
-
curl -L -o test_engine.cjs https://huggingface.co/spaces/Hugdrigo/impactlab-latam/resolve/main/test_engine.cjs
7.38 kB
| ; | |
| const {test}=require('node:test'); | |
| const assert=require('node:assert/strict'); | |
| const E=require('./engine.js'),D=require('./demo-data.js'); | |
| const opts={country:'CHL',controls:['ARG','PER','URY'],indicator:'SP.DYN.LE00.IN',start:2003,end:2024,breakYear:2016}; | |
| const approx=(actual,expected,tol=1e-6)=>assert.ok(Math.abs(actual-expected)<tol,`${actual} != ${expected}`); | |
| function rowsFromVectors(years,treated,donors){return years.flatMap((year,i)=>[{country:'TRT',indicator:'X',year,value:treated[i],source:'fixture'},...Object.entries(donors).map(([country,values])=>({country,year,indicator:'X',value:values[i],source:'fixture'}))]);} | |
| const Y=Array.from({length:12},(_,i)=>2000+i),fixture={country:'TRT',controls:['A','B'],indicator:'X',start:2000,end:2011,breakYear:2006}; | |
| const controlA=Y.map((_,i)=>20+i),controlB=Y.map((_,i)=>20+i),treated=Y.map((_,i)=>25+i+(i>=6?4:0)); | |
| const R=rowsFromVectors(Y,treated,{A:controlA,B:controlB}); | |
| test('Demo has all 15 economies and 8 indicators',()=>{assert.equal(new Set(D.records.map(r=>r.country)).size,15);assert.equal(new Set(D.records.map(r=>r.indicator)).size,8);assert.equal(D.records.length,15*25*8);}); | |
| test('Demo observations clearly synthetic',()=>assert.ok(D.records.every(r=>r.source==='synthetic-demo'))); | |
| test('Demo target shift produces nonzero DiD',()=>{const d=E.estimateDid(D.records,opts);assert.equal(d.ok,true);assert.ok(d.effect>0.5);}); | |
| test('Equal-weight DiD recovers a known 4-unit shift',()=>approx(E.estimateDid(R,fixture).effect,4)); | |
| test('DiD records correct pre-post years',()=>{const d=E.estimateDid(R,fixture);assert.equal(d.preYears,6);assert.equal(d.postYears,6);}); | |
| test('DiD treated mean change is baseline trend plus 4',()=>approx(E.estimateDid(R,fixture).treatedChange,10)); | |
| test('DiD control mean change tracks baseline slope',()=>approx(E.estimateDid(R,fixture).controlChange,6)); | |
| test('DiD rejects no donors',()=>assert.throws(()=>E.estimateDid(R,{...fixture,controls:[]}))); | |
| test('DiD rejects treated country among donors',()=>assert.throws(()=>E.estimateDid(R,{...fixture,controls:['TRT','A']}))); | |
| test('DiD rejects too short calendar windows',()=>assert.throws(()=>E.estimateDid(R,{...fixture,end:2005}))); | |
| test('DiD rejects insufficient pre periods',()=>assert.throws(()=>E.estimateDid(R,{...fixture,breakYear:2002}))); | |
| test('DiD rejects insufficient post periods',()=>assert.throws(()=>E.estimateDid(R,{...fixture,breakYear:2010}))); | |
| test('Paired years require all donors present',()=>{const x=R.map(v=>({...v}));x.find(v=>v.country==='B'&&v.year===2001).value=null;const d=E.estimateDid(x,fixture);assert.equal(d.preYears,5);}); | |
| test('Missing post data returns explicit missing estimate if below threshold',()=>{const x=R.filter(v=>v.year<2008||v.country!=='TRT');const d=E.estimateDid(x,fixture);assert.equal(d.ok,false);}); | |
| test('Parallel pre-trends yield slope gap approximately zero',()=>approx(E.pretrend(E.estimateDid(R,fixture)).slopeDifference,0)); | |
| test('Pre-trends computed over pre years only',()=>assert.equal(E.pretrend(E.estimateDid(R,fixture)).preDifferences.length,6)); | |
| test('Bootstrap is reproducible with same seed',()=>{const d=E.estimateDid(R,fixture);assert.deepEqual(E.bootstrapDid(d,100,9).interval,E.bootstrapDid(d,100,9).interval);}); | |
| test('Bootstrap covers known constant DiD 4',()=>{const d=E.estimateDid(R,fixture);const b=E.bootstrapDid(d,400,99);assert.ok(b.interval[0]<6&&b.interval[1]>2);}); | |
| test('Bootstrap does not claim causal uncertainty',()=>assert.match(E.bootstrapDid(E.estimateDid(R,fixture)).method,/not causal/i)); | |
| test('Simplex projection nonnegative and sums to one',()=>{const w=E.projectSimplex([2,-1,0.3]);assert.ok(w.every(x=>x>=0));approx(E.sum(w),1);}); | |
| test('Simplex projection handles equal vectors',()=>{const w=E.projectSimplex([0,0,0,0]);w.forEach(x=>approx(x,.25));}); | |
| test('Synthetic control recovers perfect equal donors pre-break',()=>{const s=E.syntheticControl(R,fixture);assert.equal(s.ok,true);approx(s.preRmse,5,.05);approx(s.postMeanGap,9,.05);}); | |
| test('Synthetic donor weights stay on convex simplex',()=>{const s=E.syntheticControl(D.records,opts);assert.ok(s.ok);assert.ok(s.weights.every(w=>w.weight>=0&&w.weight<=1));approx(E.sum(s.weights.map(w=>w.weight)),1,1e-6);}); | |
| test('Synthetic control requires two donors',()=>{const s=E.syntheticControl(R,{...fixture,controls:['A']});assert.equal(s.ok,false);}); | |
| test('Synthetic control requires five paired pre years',()=>{const sparse=R.filter(r=>r.year>=2002||r.country!=='TRT');const s=E.syntheticControl(sparse,fixture);assert.equal(s.ok,false);}); | |
| test('Synthetic fitting excludes post years from weights',()=>{const x=R.map(r=>({...r}));const y=R.map(r=>({...r}));y.forEach(r=>{if(r.year>=2006&&r.country==='TRT')r.value+=999});assert.deepEqual(E.syntheticControl(x,fixture).weights,E.syntheticControl(y,fixture).weights);}); | |
| test('Unit placebos produce a real and placebo assignments',()=>{const p=E.unitPlacebos(D.records,opts);assert.equal(p.length,4);assert.equal(p.filter(v=>v.treated).length,1);}); | |
| test('Time placebos only run before specified break',()=>{const p=E.timePlacebos(D.records,opts);assert.ok(p.length>0);assert.ok(p.every(v=>v.year<opts.breakYear));}); | |
| test('Coverage reflects intentionally missing demo years',()=>{const c=E.coverage(D.records,{...opts,indicator:'SE.SEC.ENRR',country:'BOL',controls:['ARG','PER']});assert.equal(c[0].missing,3);}); | |
| test('Coverage reports latest year',()=>assert.equal(E.coverage(D.records,opts)[0].latest,2024)); | |
| test('World Bank parser handles ISO3 and absent values',()=>{const payload=[{page:1},[{countryiso3code:'CHL',date:'2020',value:71.2},{countryiso3code:'ARG',date:'2020',value:null}]];const r=E.parseWorldBank(payload,'I');assert.deepEqual(r.map(v=>v.value),[71.2,null]);}); | |
| test('World Bank parser rejects invalid shapes',()=>assert.throws(()=>E.parseWorldBank({},'I'))); | |
| test('World Bank parser ignores invalid years',()=>assert.equal(E.parseWorldBank([{},[{countryiso3code:'ARG',date:'foo',value:4}]],'I').length,0)); | |
| test('Data validator drops invalid years and NaNs',()=>{const x=E.validateRows([{country:'A',indicator:'Y',year:2020,value:4},{country:'B',indicator:'Y',year:1800,value:3},{country:'C',indicator:'Y',year:2020,value:'foo'}]);assert.equal(x.length,1);}); | |
| test('Data validator de-duplicates years',()=>{const x=E.validateRows([{country:'A',indicator:'Y',year:2020,value:4},{country:'A',indicator:'Y',year:2020,value:5}]);assert.equal(x.length,1);assert.equal(x[0].value,4);}); | |
| test('Data validator retains null as missing',()=>assert.equal(E.validateRows([{country:'A',indicator:'Y',year:2020,value:null}])[0].value,null)); | |
| test('CSV formula values are quoted to preserve structure',()=>{const csv=E.toCSV([{name:'a,"b"',year:2020}],['name','year']);assert.match(csv,/"a,""b"""/);}); | |
| test('Year-by-year control mean uses all donors',()=>{const t=E.timeline(R,fixture);assert.equal(t.find(p=>p.year===2000).controls,20);}); | |
| test('Invalid options reject duplicate treated and donor',()=>assert.throws(()=>E.checkOptions({...fixture,controls:['TRT']}))); | |
| test('Every display indicator has a documented unit',()=>assert.ok(Object.values(E.indicators).every(x=>x.name&&x.unit&&x.domain))); | |
| test('CSV export neutralizes spreadsheet formulas in user supplied strings',()=>{const csv=E.toCSV([{value:'=HYPERLINK("https://x")'}],['value']);assert.ok(csv.includes("'"+"=HYPERLINK"));}); | |