Files
hockey_new/tests/analytics_core.cjs
2026-09-27 00:47:30 +03:00

23 lines
4.1 KiB
JavaScript

// Run: node tests/analytics_core.cjs. No browser or third-party packages needed.
const assert=require('node:assert/strict'),vm=require('node:vm'),fs=require('node:fs'),path=require('node:path');
const window={addEventListener(){}};
vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../ui_builder/static/analytics.js'),'utf8'),{window,URL,Date});
const A=window.HockeyAnalytics;
let checks=0;
function test(name,fn){fn();checks++;console.log('PASS '+name);}
const player=(extra={})=>({side:'home',id:'a',name:'Иван Иванов',khl_id:'1',role:'skater',birth_date:'2000-09-27',career_statistics:{available:true,games:498,goals:149,assists:181,points:330},...extra});
test('missing cells and non-finite values never become zero',()=>{for(const x of [null,undefined,'',' ','-','—','NaN','Infinity',false])assert.equal(A.number(x),null);assert.equal(A.number('0'),0);assert.equal(A.number('12,5'),12.5);});
test('per game divides additive counts only',()=>{const m=A.METRICS.skater.find(m=>m.key==='points');assert.equal(A.valueFor({games:10,points:25},m,true),2.5);assert.equal(A.valueFor({games:0,points:25},m,true),null);assert.equal(A.valueFor({games:10,points:25},m,false),25);});
test('games percentages and goalie GAA retain units',()=>{for(const [role,key,n]of [['skater','games',40],['skater','shot_pct',12.5],['goalkeeper','save_pct',92.3],['goalkeeper','goals_against_average',2.1]]){const m=A.METRICS[role].find(m=>m.key===key);assert.equal(A.valueFor({games:40,[key]:n},m,true),n);}});
test('unknown and unavailable do not imply zero; negative plus/minus stays signed',()=>{const m=A.METRICS.skater.find(m=>m.key==='plus_minus');assert.equal(A.valueFor({games:10,plus_minus:-12},m,true),-1.2);assert.equal(A.valueFor({available:false,games:10,plus_minus:0},m,false),null);});
test('near milestones are factual and limited by threshold',()=>{const hints=A.makeHints([player()],5);assert.equal(hints.length,2);assert.equal(hints[0].key,'goals');assert.equal(hints[0].remaining,1);assert.equal(hints[1].target,500);assert.equal(A.makeHints([player()],1).length,1);});
test('exact milestone differs from a future milestone',()=>{const h=A.makeHints([player({career_statistics:{games:500}})],5);assert.equal(h[0].remaining,0);assert.equal(h[0].target,500);});
test('unknown fractional negative unmatched statistics produce no milestones',()=>{for(const value of [null,'',-1,0,49.5])assert.equal(A.makeHints([player({career_statistics:{games:value}})],5).length,0);assert.equal(A.makeHints([player({khl_id:''})],5).length,0);});
test('goalie milestones use games wins shutouts',()=>{const h=A.makeHints([player({role:'goalkeeper',career_statistics:{games:498,wins:149,shutouts:29,goals:149}})],5);assert.equal(h.length,3);assert.ok(!h.some(h=>h.key==='goals'));});
test('birthday on match date uses that date rather than wall clock',()=>{const h=A.makeBirthdays([player()],'2026-09-27',0);assert.equal(h.length,1);assert.equal(h[0].age,26);assert.equal(h[0].days,0);});
test('birthdays before and after match preserve direction and anniversary age',()=>{const hs=A.makeBirthdays([player({birth_date:'1999-09-24'}),player({id:'b',birth_date:'2001-09-30'})],'2026-09-27',7);assert.equal(hs[0].days,-3);assert.equal(hs[0].age,27);assert.equal(hs[1].days,3);assert.equal(hs[1].age,25);});
test('December and January crossing gives correct year and age',()=>{const h=A.makeBirthdays([player({birth_date:'2000-01-02'})],'2026-12-29',7)[0];assert.equal(h.days,4);assert.equal(h.age,27);assert.equal(h.date,'2027-01-02');const p=A.makeBirthdays([player({birth_date:'2000-12-30'})],'2027-01-02',7)[0];assert.equal(p.days,-3);assert.equal(p.age,26);});
test('leap day stays February 29 without invented substitute date',()=>{const p=player({birth_date:'2000-02-29'});assert.equal(A.makeBirthdays([p],'2027-02-28',7).length,0);assert.equal(A.makeBirthdays([p],'2028-02-28',7)[0].days,1);});
test('missing invalid future birthdays and missing game date are skipped',()=>{for(const d of ['',null,'2000-02-31','2100-09-27','2026-09-27'])assert.equal(A.makeBirthdays([player({birth_date:d})],'2026-09-27',7).length,0);assert.equal(A.makeBirthdays([player()],'',7).length,0);});
console.log(JSON.stringify({ok:true,checks}));