Files
pluriwave/test/servicios/servicio_alarmas_proxima_test.dart
Javier Bautista Fernández 28b663bbe7
Build & Deploy PluriWave / Análisis de código (push) Successful in 37s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m33s
fix(alarm): recalculate every alarm on each mutation, not just the touched one
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.
2026-07-02 15:21:58 +02:00

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',
);
},
);
}