igneum/tools/site-redesign/tests/data-tests.cjs
igneum-labs 045102b81a site-redesign: the full-site redesign on our content, 22 pages served
The package's design system, layouts and interactions on our tokens and self-hosted fonts (site/site.css section 10),
our facts, numbers, records and live services on every page. The home page: the GPU hero (site/hero-scene.js, continuous
while in view, labelled as drawn), the live DAG panel on scenes/feed.js and live-dag.js 2.0.2, three reasons, the
economics split, the download row with the OS marks, the ledger line. The miner page: the download layout, platform
tabs stamped from the live download index with sha256, the steps, the card table, the fee section (the one source of
/dev-fee), the FAQ. The wallet page in the package's wallet-hero layout, the window slot ready for the wallet redesign.
The secondary pages rendered by the build from one source each: /claims and /randomx from the litepaper's sections,
/dev-fee from the miner's fee section, /provenance from docs/provenance.md through the scrub, /journey from
journey.json; /benchmarks rewrites to /miners, /connect redirects to /metamask. The generated pages (bench, bench
table, ledger) restyled onto the page hero and the docs layout with a section filter. The footer's secondary links point
at the real pages. The copy pass on every served page (docs/plans/site-copy-pass.md). The package's data tests and the
hero loop test in the gate (tools/site-redesign). No sample data is served; the package's review chrome is not.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 10:30:18 +00:00

36 lines
3.9 KiB
JavaScript

/* Pure unit tests: no network or browser dependencies. */
const fs=require('node:fs'),vm=require('node:vm'),assert=require('node:assert/strict');
const path=require('node:path');
vm.runInThisContext(fs.readFileSync(path.join(__dirname,'../engine.js'),'utf8'));
const {Demo,validateReply,MINE}=IgneumSiteEngine;const results=[];
function check(name,fn){try{fn();results.push({name,pass:true});}catch(e){results.push({name,pass:false,error:e.message});}}
const now=Date.now(),demo=new Demo(now),reply=demo.snapshot(now);
const edit=fn=>{const r=JSON.parse(JSON.stringify(reply));fn(r);return r;};
check('Seeded demo obeys observer contract',()=>assert.equal(validateReply(reply).ok,true));
check('All hashes unique',()=>assert.equal(new Set(reply.blocks.map(b=>b.hash)).size,reply.blocks.length));
check('Parent links are never self-links',()=>assert(reply.blocks.every(b=>!b.parents.includes(b.hash))));
check('Parents precede children',()=>{const byHash=new Map(reply.blocks.map(b=>[b.hash,b]));assert(reply.blocks.every(b=>b.parents.every(h=>!byHash.has(h)||byHash.get(h).ts<=b.ts)));});
check('Included, excluded, selected remain separate',()=>{assert(reply.blocks.some(b=>b.color==='red'));assert(reply.blocks.some(b=>b.color==='blue'&&!b.chain));});
check('Proving completion does not implicitly become final',()=>{const x=demo.trigger('mine');demo.trigger('proof');assert(x.proven);assert(!x.final);assert(!x.locked);});
check('Own block uses the tracked demo vote key',()=>assert.equal(demo.trigger('mine').miner,MINE));
check('Checkpoint effect needs an explicit simulated checkpoint',()=>{const x=demo.trigger('lock');assert(demo.snapshot().finality.checkpoints.some(c=>c.state==='locked'&&c.blue_score===x.blue_score));});
check('Validation does not age or promote observer proof',()=>{const r=edit(r=>{r.blocks[0].ts=now-1e8;r.blocks[0].shards=[{state:'planned'}];r.blocks[0].proven=false;r.blocks[0].final=false;r.blocks[0].locked=false;});const out=validateReply(r);assert.equal(out.blocks[0].shards[0].state,'planned');assert.equal(out.blocks[0].final,false);});
check('Observer false finality remains false',()=>assert.equal(validateReply(edit(r=>{r.blocks[0].chain=true;r.blocks[0].proven=true;r.blocks[0].final=false;})).blocks[0].final,false));
check('Payload is defensively cloned',()=>{const v=validateReply(reply);v.blocks[0].hash='changed';assert.notEqual(reply.blocks[0].hash,'changed');});
function reject(name, mutate) { check(name, function(){ assert.throws(function(){validateReply(edit(mutate));});}); }
reject('HTML hashes rejected', r => { r.blocks[0].hash='<img onerror=1>'; });
reject('Repeated hashes rejected', r => { r.blocks.push(r.blocks[0]); });
reject('Invalid parent rejected', r => { r.blocks[0].parents=['javascript:bad']; });
reject('Self parent rejected', r => { r.blocks[0].parents=[r.blocks[0].hash]; });
reject('Future time rejected', r => { r.blocks[0].ts=now+1e8; });
reject('Seconds are not silently read as milliseconds', r => { r.blocks[0].ts=now/1000; });
reject('Unknown proof state rejected', r => { r.blocks[0].shards=[{state:'jackpot'}]; });
reject('String proof flag rejected', r => { r.blocks[0].proven='true'; });
reject('String finality flag rejected', r => { r.blocks[0].final='false'; });
reject('Invalid inclusion rejected', r => { r.blocks[0].color='winning'; });
reject('Negative observer age rejected', r => { r.state.age_s=-1; });
reject('Invalid checkpoint fraction rejected', r => { r.finality.checkpoints[0].fraction_total=2; });
check('Empty observer window accepted',()=>assert.equal(validateReply({ok:true,state:{stale:false,age_s:0},blocks:[]}).blocks.length,0));
check('Demo retained history is bounded',()=>{for(let i=0;i<1000;i++)demo.create(now+i*2000,false,false);demo.update(now+2000000);assert(demo.blocks.length<=161);assert(demo.cps.length<=12);});
console.log(JSON.stringify({passed:results.filter(x=>x.pass).length,total:results.length,results},null,2));
if(results.some(x=>!x.pass))process.exitCode=1;