import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:pluriwave/estado/estado_alarmas.dart'; import 'package:pluriwave/estado/estado_radio.dart'; import 'package:pluriwave/l10n/gen/app_localizations.dart'; import 'package:pluriwave/modelos/alarma_musical.dart'; import 'package:pluriwave/modelos/emisora.dart'; import 'package:pluriwave/pantallas/pantalla_alarma_sonando.dart'; import 'package:pluriwave/servicios/servicio_alarmas.dart'; import 'package:pluriwave/servicios/servicio_audio.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../helpers/fakes.dart'; import '../helpers/fakes_alarmas.dart'; class _Entorno { _Entorno({ required this.estadoAlarmas, required this.android, required this.audio, }); final EstadoAlarmas estadoAlarmas; final FakePuertoAlarmasAndroid android; final FakeServicioAudio audio; } Future<_Entorno> _montarPantalla( WidgetTester tester, { int snoozeMinutos = 5, }) async { tester.view.physicalSize = const Size(1440, 3200); tester.view.devicePixelRatio = 1.0; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); final audio = FakeServicioAudio(); audio.emitirEstado(EstadoReproduccion.reproduciendo); final radio = EstadoRadio( audio: audio, favoritos: FakeServicioFavoritos(), radio: FakeServicioRadio(), servicioEcualizador: FakeServicioEcualizador(), servicioGrabacion: FakeServicioGrabacionRadioInactiva(), iniciarAutomaticamente: false, ); addTearDown(radio.dispose); final android = FakePuertoAlarmasAndroid(); final ahora = DateTime(2026, 6, 11, 7, 0); final estadoAlarmas = EstadoAlarmas( servicio: ServicioAlarmas(reloj: () => ahora), android: android, iniciarAutomaticamente: false, ); addTearDown(estadoAlarmas.dispose); addTearDown(android.dispose); await estadoAlarmas.guardarAlarma( AlarmaMusical( id: 'ring1', nombre: 'Despertar', hora: 7, minuto: 30, tipoProgramacion: TipoProgramacionAlarma.diaria, diasSemana: const [], snoozeMinutos: snoozeMinutos, emisora: const Emisora( uuid: 'e1', nombre: 'Radio Uno', url: 'https://radio.example/stream', ), ), ); await tester.pumpWidget( MultiProvider( providers: [ ChangeNotifierProvider.value(value: radio), ChangeNotifierProvider.value(value: estadoAlarmas), ], child: MaterialApp( locale: const Locale('es'), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: const SizedBox.shrink(), ), ), ); final navigator = tester.state(find.byType(Navigator)); unawaited( navigator.push( MaterialPageRoute( builder: (_) => PantallaAlarmaSonando( alarma: estadoAlarmas.alarmas.single, audioPrearrancado: true, ), fullscreenDialog: true, ), ), ); await tester.pumpAndSettle(); return _Entorno(estadoAlarmas: estadoAlarmas, android: android, audio: audio); } void main() { final l10n = lookupAppLocalizations(const Locale('es')); setUp(() { SharedPreferences.setMockInitialValues({}); }); testWidgets( 'muestra botones de posponer 3/5/10 mas el personalizado (S2-R1-A/C)', (tester) async { await _montarPantalla(tester, snoozeMinutos: 7); expect(find.text(l10n.alarmSnoozeOptionLabel(3)), findsOneWidget); expect(find.text(l10n.alarmSnoozeOptionLabel(5)), findsOneWidget); expect(find.text(l10n.alarmSnoozeOptionLabel(7)), findsOneWidget); expect(find.text(l10n.alarmSnoozeOptionLabel(10)), findsOneWidget); expect(find.text(l10n.stopAlarmAction), findsOneWidget); }, ); testWidgets( 'no duplica el boton cuando snoozeMinutos coincide con una opcion fija', (tester) async { await _montarPantalla(tester, snoozeMinutos: 5); expect(find.text(l10n.alarmSnoozeOptionLabel(3)), findsOneWidget); expect(find.text(l10n.alarmSnoozeOptionLabel(5)), findsOneWidget); expect(find.text(l10n.alarmSnoozeOptionLabel(10)), findsOneWidget); }, ); testWidgets( 'posponer 5 min detiene el audio local, pospone y cierra (S2-R1-B)', (tester) async { final entorno = await _montarPantalla(tester, snoozeMinutos: 5); await tester.tap(find.text(l10n.alarmSnoozeOptionLabel(5))); await tester.pumpAndSettle(); final alarma = entorno.estadoAlarmas.alarmas.single; expect(alarma.snoozeHasta, DateTime(2026, 6, 11, 7, 35)); expect(entorno.audio.pausas, greaterThanOrEqualTo(1)); expect(find.byType(PantallaAlarmaSonando), findsNothing); // posponerAlarma oculta la notificacion nativa (mismo stop path que // el boton de detener) y reprograma con el snooze. expect(entorno.android.ocultadas, contains('ring1')); expect( entorno.android.programadas.last.snoozeHasta, DateTime(2026, 6, 11, 7, 35), ); }, ); }