guardarAlarma only recomputed proximaEjecucion for the alarm being saved; every other alarm kept whatever snapshot the last periodic recalculation left, which can be stale or already past-due. Since EstadoAlarmas.proximaAlarma just sorts by proximaProgramable, a stale sibling could wrongly outrank a freshly activated/created/edited alarm in the "Próxima alarma" panel until the next 1-minute tick. Extended the same full-list recalculation guardarVacaciones already did to guardarAlarma, eliminarAlarma, completarEjecucion, sincronizarEjecucionesNativas, saltarProxima and posponerEjecucionHasta, via a shared _recalcularLista helper.
75 lines
2.5 KiB
Dart
75 lines
2.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:pluriwave/modelos/alarma_musical.dart';
|
|
import 'package:pluriwave/servicios/servicio_alarmas.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// SharedPreferences spy: only the members ServicioAlarmas touches are
|
|
/// implemented; everything else throws via noSuchMethod.
|
|
class _PrefsEspia implements SharedPreferences {
|
|
final Map<String, Object> _datos = {};
|
|
|
|
@override
|
|
String? getString(String key) => _datos[key] as String?;
|
|
|
|
@override
|
|
Future<bool> setString(String key, String value) async {
|
|
_datos[key] = value;
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
|
|
}
|
|
|
|
void main() {
|
|
// Regression for: activating/creating/deleting/firing an alarm must never
|
|
// leave a sibling stuck with a stale (already past-due) proximaEjecucion
|
|
// snapshot, since EstadoAlarmas.proximaAlarma just sorts by
|
|
// proximaProgramable and a stale past value would incorrectly outrank a
|
|
// freshly computed future one.
|
|
test(
|
|
'guardarAlarma recalcula la proximaEjecucion de TODAS las alarmas, no solo la guardada',
|
|
() async {
|
|
final prefs = _PrefsEspia();
|
|
var reloj = DateTime(2026, 1, 1, 6, 0);
|
|
final servicio = ServicioAlarmas(prefs: prefs, reloj: () => reloj);
|
|
|
|
final a = servicio.crearAlarma(
|
|
nombre: 'A',
|
|
hora: 7,
|
|
minuto: 0,
|
|
tipoProgramacion: TipoProgramacionAlarma.diaria,
|
|
diasSemana: const [],
|
|
);
|
|
final configTrasA = await servicio.guardarAlarma(a);
|
|
final aGuardada = configTrasA.alarmas.single;
|
|
expect(aGuardada.proximaEjecucion, DateTime(2026, 1, 1, 7, 0));
|
|
|
|
// Time moves forward well past A's stored occurrence, simulating the
|
|
// periodic 1-minute refresh not having ticked yet.
|
|
reloj = DateTime(2026, 1, 2, 8, 0);
|
|
|
|
final b = servicio.crearAlarma(
|
|
nombre: 'B',
|
|
hora: 9,
|
|
minuto: 0,
|
|
tipoProgramacion: TipoProgramacionAlarma.diaria,
|
|
diasSemana: const [],
|
|
);
|
|
final configTrasB = await servicio.guardarAlarma(b);
|
|
|
|
final aTrasGuardarB = configTrasB.alarmas.firstWhere(
|
|
(alarma) => alarma.id == a.id,
|
|
);
|
|
expect(
|
|
aTrasGuardarB.proximaEjecucion!.isAfter(reloj),
|
|
isTrue,
|
|
reason:
|
|
'A debe recalcularse al guardar B, no quedar con el snapshot '
|
|
'viejo (ya vencido) que la haria ganar la comparacion de '
|
|
'"proxima alarma" por error',
|
|
);
|
|
},
|
|
);
|
|
}
|