@@ -527,6 +527,172 @@ void main() {
527527 expect (find.text ('HOME_ROUTE' ), findsOneWidget);
528528 }, timeout: const Timeout (Duration (seconds: 15 )));
529529
530+ testWidgets ('active alarm screen renders top-corner close button' ,
531+ (tester) async {
532+ await setLargeTestViewport (tester);
533+ now = DateTime .now ();
534+
535+ final schedule = buildSchedule (
536+ id: 's-active-close' ,
537+ scheduleTime: now.add (const Duration (minutes: 35 )),
538+ steps: const [
539+ PreparationStepWithTimeEntity (
540+ id: 'p1' ,
541+ preparationName: 'Prep' ,
542+ preparationTime: Duration (minutes: 10 ),
543+ nextPreparationId: null ,
544+ ),
545+ ],
546+ );
547+
548+ final router = GoRouter (
549+ initialLocation: '/alarmScreen' ,
550+ routes: [
551+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
552+ GoRoute (
553+ path: '/alarmScreen' ,
554+ builder: (_, __) => const AlarmScreen (),
555+ ),
556+ ],
557+ );
558+
559+ final earlyBundle = createEarlyStartUseCaseBundle ();
560+ final alarmBloc = ScheduleBloc .test (
561+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
562+ navigationService,
563+ NoopSaveTimedPreparationUseCase (),
564+ StubGetTimedPreparationSnapshotUseCase ({}),
565+ NoopClearTimedPreparationUseCase (),
566+ finishUseCase,
567+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
568+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
569+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
570+ nowProvider: () => now,
571+ );
572+ addTearDown (alarmBloc.close);
573+
574+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
575+ await pumpUntilFound (tester, find.byKey (const Key ('alarm_close_button' )));
576+
577+ expect (find.byKey (const Key ('alarm_close_button' )), findsOneWidget);
578+ alarmBloc.add (const ScheduleFinished (0 ));
579+ await tester.pump ();
580+ }, timeout: const Timeout (Duration (seconds: 15 )));
581+
582+ testWidgets (
583+ 'active alarm close button shows confirm dialog and stay keeps alarm' ,
584+ (tester) async {
585+ await setLargeTestViewport (tester);
586+ now = DateTime .now ();
587+
588+ final schedule = buildSchedule (
589+ id: 's-active-stay' ,
590+ scheduleTime: now.add (const Duration (minutes: 35 )),
591+ steps: const [
592+ PreparationStepWithTimeEntity (
593+ id: 'p1' ,
594+ preparationName: 'Prep' ,
595+ preparationTime: Duration (minutes: 10 ),
596+ nextPreparationId: null ,
597+ ),
598+ ],
599+ );
600+
601+ final router = GoRouter (
602+ initialLocation: '/alarmScreen' ,
603+ routes: [
604+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
605+ GoRoute (
606+ path: '/alarmScreen' ,
607+ builder: (_, __) => const AlarmScreen (),
608+ ),
609+ ],
610+ );
611+
612+ final earlyBundle = createEarlyStartUseCaseBundle ();
613+ final alarmBloc = ScheduleBloc .test (
614+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
615+ navigationService,
616+ NoopSaveTimedPreparationUseCase (),
617+ StubGetTimedPreparationSnapshotUseCase ({}),
618+ NoopClearTimedPreparationUseCase (),
619+ finishUseCase,
620+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
621+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
622+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
623+ nowProvider: () => now,
624+ );
625+ addTearDown (alarmBloc.close);
626+
627+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
628+ await tapAndPump (tester, find.byKey (const Key ('alarm_close_button' )));
629+ await pumpUntilFound (tester, find.byType (TwoActionDialog ));
630+
631+ await tapAndPump (tester, find.text ("I'll stay" ));
632+ await tester.pump (const Duration (milliseconds: 150 ));
633+
634+ expect (find.text ('HOME' ), findsNothing);
635+ expect (find.byType (AlarmScreen ), findsOneWidget);
636+ alarmBloc.add (const ScheduleFinished (0 ));
637+ await tester.pump ();
638+ }, timeout: const Timeout (Duration (seconds: 15 )));
639+
640+ testWidgets ('active alarm close button leave action navigates home' ,
641+ (tester) async {
642+ await setLargeTestViewport (tester);
643+ now = DateTime .now ();
644+
645+ final schedule = buildSchedule (
646+ id: 's-active-leave' ,
647+ scheduleTime: now.add (const Duration (minutes: 35 )),
648+ steps: const [
649+ PreparationStepWithTimeEntity (
650+ id: 'p1' ,
651+ preparationName: 'Prep' ,
652+ preparationTime: Duration (minutes: 10 ),
653+ nextPreparationId: null ,
654+ ),
655+ ],
656+ );
657+
658+ final router = GoRouter (
659+ initialLocation: '/alarmScreen' ,
660+ routes: [
661+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
662+ GoRoute (
663+ path: '/alarmScreen' ,
664+ builder: (_, __) => const AlarmScreen (),
665+ ),
666+ ],
667+ );
668+
669+ final earlyBundle = createEarlyStartUseCaseBundle ();
670+ final alarmBloc = ScheduleBloc .test (
671+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
672+ navigationService,
673+ NoopSaveTimedPreparationUseCase (),
674+ StubGetTimedPreparationSnapshotUseCase ({}),
675+ NoopClearTimedPreparationUseCase (),
676+ finishUseCase,
677+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
678+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
679+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
680+ nowProvider: () => now,
681+ );
682+ addTearDown (alarmBloc.close);
683+
684+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
685+ await tapAndPump (tester, find.byKey (const Key ('alarm_close_button' )));
686+ await pumpUntilFound (tester, find.byType (TwoActionDialog ));
687+
688+ await tapAndPump (tester, find.text ("I'm leaving" ));
689+ await pumpUntilRouteText (tester, 'HOME' );
690+
691+ expect (find.text ('HOME' ), findsOneWidget);
692+ alarmBloc.add (const ScheduleFinished (0 ));
693+ await tester.pump ();
694+ }, timeout: const Timeout (Duration (seconds: 15 )));
695+
530696 testWidgets (
531697 'manual finish before leave time sends lateness 0 and navigates' ,
532698 (tester) async {
0 commit comments