@@ -91,7 +91,8 @@ async function createSceneHarness(): Promise<InstanceType<GameSceneConstructor>
9191 scene . player = {
9292 inControl : true ,
9393 timePaused : false ,
94- getSnapshot : ( ) => ( { } ) ,
94+ canRetry : true ,
95+ getSnapshot : ( ) => ( { dead : false , state : "normal" } ) ,
9596 } ;
9697 scene . playerView = {
9798 render ( ) { } ,
@@ -142,6 +143,27 @@ describe("GameScene input edge lifecycle", () => {
142143 expect ( held . jumpPressed ) . toBeFalse ( ) ;
143144 } ) ;
144145
146+ test ( "pause pressed during a room transition is consumed without opening the pause menu" , async ( ) => {
147+ const scene = await createSceneHarness ( ) ;
148+ let openedPause = false ;
149+ scene . openPauseMenu = ( ) => {
150+ openedPause = true ;
151+ } ;
152+
153+ ( scene . onKeyDown as ( event : KeyboardEvent ) => void ) ( keyDown ( "KeyP" ) ) ;
154+ ( scene . onKeyDown as ( event : KeyboardEvent ) => void ) ( keyDown ( "KeyJ" ) ) ;
155+ scene . roomTransition = { } ;
156+ ( scene . update as ( time : number , delta : number ) => void ) ( 0 , 16 ) ;
157+
158+ expect ( openedPause ) . toBeFalse ( ) ;
159+ expect ( ( scene . actionPressed as ( action : string ) => boolean ) ( "pause" ) ) . toBeFalse ( ) ;
160+
161+ scene . roomTransition = null ;
162+ const input = ( scene . gatherStepInput as ( ) => ReturnType < PlayerControls [ "update" ] > ) ( ) ;
163+ expect ( input . jump ) . toBeTrue ( ) ;
164+ expect ( input . jumpPressed ) . toBeTrue ( ) ;
165+ } ) ;
166+
145167 test ( "freeze frames preserve dash press edges for the first resumed gameplay step" , async ( ) => {
146168 const scene = await createSceneHarness ( ) ;
147169
@@ -169,6 +191,50 @@ describe("GameScene input edge lifecycle", () => {
169191 expect ( input . jumpPressed ) . toBeTrue ( ) ;
170192 } ) ;
171193
194+ test ( "pause stays blocked through death and wipe until respawn starts" , async ( ) => {
195+ const scene = await createSceneHarness ( ) ;
196+ let openedPause = false ;
197+ scene . openPauseMenu = ( ) => {
198+ openedPause = true ;
199+ } ;
200+
201+ ( scene . onKeyDown as ( event : KeyboardEvent ) => void ) ( keyDown ( "KeyP" ) ) ;
202+ scene . deathRespawnSequence = {
203+ revealStarted : false ,
204+ respawnStarted : false ,
205+ } ;
206+ ( scene . update as ( time : number , delta : number ) => void ) ( 0 , 16 ) ;
207+
208+ expect ( openedPause ) . toBeFalse ( ) ;
209+ expect ( ( scene . actionPressed as ( action : string ) => boolean ) ( "pause" ) ) . toBeFalse ( ) ;
210+
211+ const player = scene . player as {
212+ timePaused : boolean ;
213+ getSnapshot : ( ) => { dead : boolean ; state : string } ;
214+ } ;
215+ scene . deathRespawnSequence = {
216+ revealStarted : true ,
217+ respawnStarted : true ,
218+ } ;
219+ player . timePaused = true ;
220+ player . getSnapshot = ( ) => ( { dead : false , state : "intro_respawn" } ) ;
221+
222+ ( scene . onKeyDown as ( event : KeyboardEvent ) => void ) ( keyDown ( "KeyP" ) ) ;
223+ ( scene . update as ( time : number , delta : number ) => void ) ( 0 , 16 ) ;
224+
225+ expect ( openedPause ) . toBeTrue ( ) ;
226+ expect ( ( scene . actionPressed as ( action : string ) => boolean ) ( "pause" ) ) . toBeFalse ( ) ;
227+ } ) ;
228+
229+ test ( "pause root disables retry when the player cannot retry" , async ( ) => {
230+ const scene = await createSceneHarness ( ) ;
231+ const player = scene . player as { canRetry : boolean } ;
232+ player . canRetry = false ;
233+
234+ const root = ( scene . createPauseRootMenu as ( ) => { items : Array < { label : string ; disabled ?: boolean } > } ) ( ) ;
235+ expect ( root . items . find ( ( item ) => item . label === "Retry" ) ?. disabled ) . toBeTrue ( ) ;
236+ } ) ;
237+
172238 test ( "unpause recovery consumes held input separately and clears raw press edges" , async ( ) => {
173239 const scene = await createSceneHarness ( ) ;
174240 let sampledHeld : { jump : boolean } | null = null ;
0 commit comments