@@ -599,6 +599,172 @@ void main() {
599599 expect (find.byIcon (Icons .close), findsOneWidget);
600600 }, timeout: const Timeout (Duration (seconds: 15 )));
601601
602+ testWidgets ('active alarm screen renders top-corner close button' ,
603+ (tester) async {
604+ await setLargeTestViewport (tester);
605+ now = DateTime .now ();
606+
607+ final schedule = buildSchedule (
608+ id: 's-active-close' ,
609+ scheduleTime: now.add (const Duration (minutes: 35 )),
610+ steps: const [
611+ PreparationStepWithTimeEntity (
612+ id: 'p1' ,
613+ preparationName: 'Prep' ,
614+ preparationTime: Duration (minutes: 10 ),
615+ nextPreparationId: null ,
616+ ),
617+ ],
618+ );
619+
620+ final router = GoRouter (
621+ initialLocation: '/alarmScreen' ,
622+ routes: [
623+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
624+ GoRoute (
625+ path: '/alarmScreen' ,
626+ builder: (_, __) => const AlarmScreen (),
627+ ),
628+ ],
629+ );
630+
631+ final earlyBundle = createEarlyStartUseCaseBundle ();
632+ final alarmBloc = ScheduleBloc .test (
633+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
634+ navigationService,
635+ NoopSaveTimedPreparationUseCase (),
636+ StubGetTimedPreparationSnapshotUseCase ({}),
637+ NoopClearTimedPreparationUseCase (),
638+ finishUseCase,
639+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
640+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
641+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
642+ nowProvider: () => now,
643+ );
644+ addTearDown (alarmBloc.close);
645+
646+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
647+ await pumpUntilFound (tester, find.byKey (const Key ('alarm_close_button' )));
648+
649+ expect (find.byKey (const Key ('alarm_close_button' )), findsOneWidget);
650+ alarmBloc.add (const ScheduleFinished (0 ));
651+ await tester.pump ();
652+ }, timeout: const Timeout (Duration (seconds: 15 )));
653+
654+ testWidgets (
655+ 'active alarm close button shows confirm dialog and stay keeps alarm' ,
656+ (tester) async {
657+ await setLargeTestViewport (tester);
658+ now = DateTime .now ();
659+
660+ final schedule = buildSchedule (
661+ id: 's-active-stay' ,
662+ scheduleTime: now.add (const Duration (minutes: 35 )),
663+ steps: const [
664+ PreparationStepWithTimeEntity (
665+ id: 'p1' ,
666+ preparationName: 'Prep' ,
667+ preparationTime: Duration (minutes: 10 ),
668+ nextPreparationId: null ,
669+ ),
670+ ],
671+ );
672+
673+ final router = GoRouter (
674+ initialLocation: '/alarmScreen' ,
675+ routes: [
676+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
677+ GoRoute (
678+ path: '/alarmScreen' ,
679+ builder: (_, __) => const AlarmScreen (),
680+ ),
681+ ],
682+ );
683+
684+ final earlyBundle = createEarlyStartUseCaseBundle ();
685+ final alarmBloc = ScheduleBloc .test (
686+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
687+ navigationService,
688+ NoopSaveTimedPreparationUseCase (),
689+ StubGetTimedPreparationSnapshotUseCase ({}),
690+ NoopClearTimedPreparationUseCase (),
691+ finishUseCase,
692+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
693+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
694+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
695+ nowProvider: () => now,
696+ );
697+ addTearDown (alarmBloc.close);
698+
699+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
700+ await tapAndPump (tester, find.byKey (const Key ('alarm_close_button' )));
701+ await pumpUntilFound (tester, find.byType (TwoActionDialog ));
702+
703+ await tapAndPump (tester, find.text ("I'll stay" ));
704+ await tester.pump (const Duration (milliseconds: 150 ));
705+
706+ expect (find.text ('HOME' ), findsNothing);
707+ expect (find.byType (AlarmScreen ), findsOneWidget);
708+ alarmBloc.add (const ScheduleFinished (0 ));
709+ await tester.pump ();
710+ }, timeout: const Timeout (Duration (seconds: 15 )));
711+
712+ testWidgets ('active alarm close button leave action navigates home' ,
713+ (tester) async {
714+ await setLargeTestViewport (tester);
715+ now = DateTime .now ();
716+
717+ final schedule = buildSchedule (
718+ id: 's-active-leave' ,
719+ scheduleTime: now.add (const Duration (minutes: 35 )),
720+ steps: const [
721+ PreparationStepWithTimeEntity (
722+ id: 'p1' ,
723+ preparationName: 'Prep' ,
724+ preparationTime: Duration (minutes: 10 ),
725+ nextPreparationId: null ,
726+ ),
727+ ],
728+ );
729+
730+ final router = GoRouter (
731+ initialLocation: '/alarmScreen' ,
732+ routes: [
733+ GoRoute (path: '/home' , builder: (_, __) => const Text ('HOME' )),
734+ GoRoute (
735+ path: '/alarmScreen' ,
736+ builder: (_, __) => const AlarmScreen (),
737+ ),
738+ ],
739+ );
740+
741+ final earlyBundle = createEarlyStartUseCaseBundle ();
742+ final alarmBloc = ScheduleBloc .test (
743+ StubGetNearestUpcomingScheduleUseCase (() => Stream .value (schedule)),
744+ navigationService,
745+ NoopSaveTimedPreparationUseCase (),
746+ StubGetTimedPreparationSnapshotUseCase ({}),
747+ NoopClearTimedPreparationUseCase (),
748+ finishUseCase,
749+ markEarlyStartSessionUseCase: earlyBundle.markUseCase,
750+ getEarlyStartSessionUseCase: earlyBundle.getUseCase,
751+ clearEarlyStartSessionUseCase: earlyBundle.clearUseCase,
752+ nowProvider: () => now,
753+ );
754+ addTearDown (alarmBloc.close);
755+
756+ await pumpWithRouter (tester, bloc: alarmBloc, router: router);
757+ await tapAndPump (tester, find.byKey (const Key ('alarm_close_button' )));
758+ await pumpUntilFound (tester, find.byType (TwoActionDialog ));
759+
760+ await tapAndPump (tester, find.text ("I'm leaving" ));
761+ await pumpUntilRouteText (tester, 'HOME' );
762+
763+ expect (find.text ('HOME' ), findsOneWidget);
764+ alarmBloc.add (const ScheduleFinished (0 ));
765+ await tester.pump ();
766+ }, timeout: const Timeout (Duration (seconds: 15 )));
767+
602768 testWidgets (
603769 'manual finish before leave time sends lateness 0 and navigates' ,
604770 (tester) async {
0 commit comments