t
Some checks failed
BEND FIELD CI / release (push) Has been cancelled
BEND FIELD CI / production-bridge (push) Has been cancelled

This commit is contained in:
33333-33333 2026-08-01 22:31:04 +09:00
commit 9d70afb4cc
42 changed files with 1266 additions and 630 deletions

View file

@ -9,7 +9,7 @@ const {root,starterPuzzle,read,functionSource,loadBendPuzzle}=require('./helpers
const app=read('app.js'),catalog=require('../store-catalog.json');
const bindBoard=functionSource('bindBoard'),claimRequest=functionSource('requestBoardClaim'),removeClaim=functionSource('removeClaim'),claimPresentation=functionSource('applyClaimPresentationToBoard');
assert(!bindBoard.includes('pointerover'),'Hover still starts board ownership');
assert(bindBoard.includes("const endpointTarget=e.target.closest?.('.endpoint-hit'),gateTarget=e.target.closest?.('.gate-hit')")&&bindBoard.indexOf('!endpointTarget&&!gateTarget')<bindBoard.indexOf('ensureBoardClaimForInput(b)'),'Ownership is requested before a knob/endpoint operation starts');
assert(bindBoard.includes("boardTarget=e.target.closest?.('.board-input-surface')")&&bindBoard.includes('!endpointTarget&&!gateTarget&&!boardTarget')&&bindBoard.indexOf('!endpointTarget&&!gateTarget&&!boardTarget')<bindBoard.indexOf('ensureBoardClaimForInput(b)'),'Board cells and existing lines cannot enter the claimed input path');
assert(claimPresentation.includes("own?'プレイ中'"),'Own board badge is not labelled プレイ中');
assert(!claimRequest.includes('toast(')&&!removeClaim.includes('toast('),'Board ownership still emits bottom notifications');
assert(functionSource('applyCloudEnvelope').includes('applyPlayerEconomyEnvelope(result)'),'Clear push response does not update the local gem wallet');
@ -48,7 +48,7 @@ function solvedState(puzzle){return{paths:puzzle.solution.map(route=>({startGate
result=await request('/api/cloud/push',{method:'POST',headers:auth(alice),body:JSON.stringify({baseRevision:1,global:{nextId:1},metas:[],states:[{id:'B0',value:solvedState(puzzle)}]})});
assert.equal(result.response.status,200,JSON.stringify(result.body));assert.equal(result.body.clearEvents.length,1,'Clear was not authoritatively accepted');assert(result.body.player.earnedScore>0,'Clear response did not include earned gems');assert.equal(result.body.player.availableScore,result.body.player.earnedScore);
const reward=result.body.player.earnedScore,clearRevision=result.body.revision;
const polling=await request(`/api/realtime/poll?presenceId=${encodeURIComponent(presenceId)}&afterSequence=${connected.body.sequence||0}`,{headers:auth(alice)});assert.equal(polling.response.status,200);assert(polling.body.messages.some(message=>message.type==='claim-release'&&message.boardId==='B0'),'Clear did not release the プレイ中 claim');
const polling=await request(`/api/realtime/poll?presenceId=${encodeURIComponent(presenceId)}&afterSequence=${connected.body.sequence||0}`,{headers:auth(alice)});assert.equal(polling.response.status,200);assert(polling.body.messages.some(message=>message.type==='claim-release'&&message.boardId==='B0'),'Clear did not release the プレイ中 claim');assert(polling.body.messages.some(message=>message.type==='world-revision'&&message.revision===clearRevision&&message.boardIds.includes('B0')),'Clear did not announce its world revision in realtime');
let pull=await request('/api/cloud/pull?since=0',{headers:auth(bob)});assert.equal(pull.body.page.states.B0.solved,true,'Other player did not receive the clear');
const playerState=await request('/api/player/state',{headers:auth(alice)});assert.equal(playerState.body.player.earnedScore,reward,'Gem wallet did not persist the clear reward');
const stale=await request('/api/cloud/push',{method:'POST',headers:auth(bob),body:JSON.stringify({baseRevision:clearRevision,global:{nextId:1},metas:[],states:[{id:'B0',value:{paths:[],specialProgress:{crossings:[]},solved:false}}]})});assert.equal(stale.response.status,200,JSON.stringify(stale.body));