bend_puzzle/test/stage34-smoke-test.js

40 lines
4 KiB
JavaScript
Raw Permalink Normal View History

2026-07-30 15:13:53 +09:00
'use strict';
const {app,assert,functionSource,loadAppLogic}=require('./helpers/app-source');
const AppLogic=loadAppLogic();
2026-07-31 12:54:46 +09:00
const placeSource=functionSource('placeChildAtFrontier'),expandSource=functionSource('expandMetaNow'),metaStateSource=functionSource('metaState'),ensureMetaStateSource=functionSource('ensureMetaState'),snapshotSource=functionSource('snapshotForStorage');
2026-07-30 15:13:53 +09:00
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}`);
2026-07-31 12:54:46 +09:00
assert(!metaStateSource.includes('normalizeState')&&!metaStateSource.includes('markStateDirty')&&ensureMetaStateSource.includes('normalizeState(state)'),'State reads are not pure or explicit state repair is not delegated to normalizeState');
assert(!functionSource('puzzleOf').includes('markMetaDirty')&&functionSource('repairPuzzleDifficulty').includes('markMetaDirty'),'Puzzle reads still dirty metadata or difficulty repair lacks an explicit command boundary');
2026-07-30 15:13:53 +09:00
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');