39 lines
3.7 KiB
JavaScript
39 lines
3.7 KiB
JavaScript
|
|
'use strict';
|
||
|
|
const {app,assert,functionSource,loadAppLogic}=require('./helpers/app-source');
|
||
|
|
const AppLogic=loadAppLogic();
|
||
|
|
const placeSource=functionSource('placeChildAtFrontier'),expandSource=functionSource('expandMetaNow'),metaStateSource=functionSource('metaState'),snapshotSource=functionSource('snapshotForStorage');
|
||
|
|
for(const forbidden of ['ensureBoards','renderAll','updateHud','nextPaint','save(','rebuildOccupancy'])assert(!placeSource.includes(forbidden),`Child placement still performs ${forbidden}`);
|
||
|
|
assert((expandSource.match(/refreshWorldView\(/g)||[]).length===1,'Expansion does not use one presentation/persistence commit');
|
||
|
|
for(const forbidden of ['ensureBoards','renderAll','updateHud'])assert(!expandSource.includes(forbidden),`Expansion bypasses the shared view pipeline with ${forbidden}`);
|
||
|
|
assert(metaStateSource.includes('normalizeState(state)'),'Live state normalization is not delegated to normalizeState');
|
||
|
|
assert(snapshotSource.includes('metaRowsForStorage()')&&snapshotSource.includes('stateRowsForStorage()'),'Snapshot serialization bypasses shared row serializers');
|
||
|
|
assert(functionSource('pushCloudPending').includes('cloudRowsForStorage')&&functionSource('cloudRowsForStorage').includes('metaForStorage')&&functionSource('cloudRowsForStorage').includes('stateForStorage'),'Cloud serialization bypasses full-detail row serializers');
|
||
|
|
assert(functionSource('stateForStorage').includes('AppLogic.stateForStorage'),'State serialization is not delegated to the shared module');
|
||
|
|
assert(functionSource('collectConnectedLineComponent').includes('AppLogic.collectConnectedLineComponent'),'Connected-line traversal is not delegated to the shared module');
|
||
|
|
|
||
|
|
const data={
|
||
|
|
metas:{A:{id:'A',puzzle:{}},B:{id:'B',puzzle:{}}},
|
||
|
|
states:{A:{paths:[{startGate:0,endGate:1,cells:[[0,0],[0,1]]}]},B:{paths:[{startGate:0,endGate:1,cells:[[0,0],[1,0],[2,0]]}]}}
|
||
|
|
};
|
||
|
|
let matchingCalls=0;
|
||
|
|
const environment={
|
||
|
|
data,
|
||
|
|
metaState:id=>data.states[id],
|
||
|
|
matchingNeighborGate(meta,gate){
|
||
|
|
matchingCalls++;
|
||
|
|
if(meta.id==='A'&&gate===1)return{meta:data.metas.B,gateIndex:0};
|
||
|
|
if(meta.id==='B'&&gate===0)return{meta:data.metas.A,gateIndex:1};
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const componentCache=new Map(),lengthA=AppLogic.connectedLineLength(data.metas.A,0,componentCache,environment),callsAfterFirst=matchingCalls,lengthB=AppLogic.connectedLineLength(data.metas.B,0,componentCache,environment);
|
||
|
|
assert(lengthA===5&&lengthB===5,'Connected-line component length is incorrect');
|
||
|
|
assert(matchingCalls===callsAfterFirst,'Connected-line component was traversed again for a cached member');
|
||
|
|
const widthCache=new Map(),widthA=AppLogic.renderedConnectedLineWidth(data.metas.A,0,widthCache,environment,componentCache),callsAfterWidth=matchingCalls,widthB=AppLogic.renderedConnectedLineWidth(data.metas.B,0,widthCache,environment,componentCache);
|
||
|
|
assert(widthA===widthB&&matchingCalls===callsAfterWidth,'Connected-line width did not reuse the cached component');
|
||
|
|
|
||
|
|
const stateRow=AppLogic.stateForStorage({paths:[],specialProgress:{crossings:[]},solved:false,expanded:false,expansionRetryRound:7,solvedBy:null,scoreAwarded:0,scoreVersion:2,store:null,rev:5,transient:'remove'},{scoreVersion:2});
|
||
|
|
assert(stateRow.rev===5&&stateRow.expansionRetryRound===7&&!('transient' in stateRow),'State serializer lost expansion repair progress or leaked transient fields');
|
||
|
|
const emptyState=AppLogic.stateForStorage(null,{scoreVersion:3,normalizeState:()=>({paths:[],specialProgress:{crossings:[]},scoreVersion:3})});
|
||
|
|
assert(emptyState.scoreVersion===3&&Array.isArray(emptyState.paths),'State serializer fallback is invalid');
|
||
|
|
console.log('Stage 3/4 regression passed: batched expansion, shared traversal, normalization, serialization, and view pipeline');
|