@@ -117,6 +117,58 @@ test.describe('Workout Reload Persistence', () => {
117117 } ) ;
118118} ) ;
119119
120+ test . describe ( 'Back Button Timer Cleanup' , ( ) => {
121+ /**
122+ * Regression: pressing Back during a rest timer left the timer state in
123+ * IndexedDB. On the next workout load, the recovery code would fire the
124+ * notification and/or show "Time's Up!" immediately.
125+ */
126+ test ( 'stale timer from previous session does not fire on new workout start' , async ( { page } ) => {
127+ await page . addInitScript ( ( ) => {
128+ ( window as any ) . __vibrateCount = 0 ;
129+ Object . defineProperty ( navigator , 'vibrate' , {
130+ value : ( ) => { ( window as any ) . __vibrateCount ++ ; return true ; } ,
131+ writable : true ,
132+ configurable : true ,
133+ } ) ;
134+ } ) ;
135+
136+ await page . goto ( '/' ) ;
137+ await page . waitForSelector ( '#app' ) ;
138+ await page . click ( '#start-workout-btn' ) ;
139+ await page . waitForSelector ( '.workout-screen' ) ;
140+
141+ // Seed a stale timer (still has ~2 seconds remaining) — simulating what
142+ // the Back button leaves behind because it doesn't clear IndexedDB timer state.
143+ await page . evaluate ( async ( ) => {
144+ const { putTimerState } = await import ( '/src/db/database.ts' ) ;
145+ await putTimerState ( {
146+ expectedEndTime : Date . now ( ) + 2000 , // expires in 2 seconds
147+ durationMs : 90000 ,
148+ } ) ;
149+ } ) ;
150+
151+ // Navigate to home (simulating Back button navigation)
152+ await page . evaluate ( ( ) => { window . location . hash = 'home' ; } ) ;
153+ await page . waitForSelector ( '#start-workout-btn' ) ;
154+ await page . evaluate ( ( ) => { ( window as any ) . __vibrateCount = 0 ; } ) ;
155+
156+ // Start a new workout — stale timer should be cleared, not re-used
157+ await page . click ( '#start-workout-btn' ) ;
158+ await page . waitForSelector ( '.workout-screen' ) ;
159+
160+ // Wait long enough for the stale timer to expire (>2s)
161+ await page . waitForTimeout ( 2500 ) ;
162+
163+ // No notification should have fired from the stale timer
164+ const vibrateCount = await page . evaluate ( ( ) => ( window as any ) . __vibrateCount ) ;
165+ expect ( vibrateCount ) . toBe ( 0 ) ;
166+
167+ // No "Time's Up!" UI should have appeared
168+ await expect ( page . locator ( '[data-testid="timer-expired"]' ) ) . not . toBeAttached ( ) ;
169+ } ) ;
170+ } ) ;
171+
120172test . describe ( 'Cancel/Abandon Workout' , ( ) => {
121173 test . beforeEach ( async ( { page } ) => {
122174 await page . goto ( '/' ) ;
0 commit comments