feat(alarmas): verify native registration after a successful save

android.programar() returning without throwing was treated as proof
the OS registered the alarm -- this is exactly the gap the reported
case fell through. guardarAlarma now cross-checks a fresh native
pending-alarm count against how many alarms Dart believes are
active-with-a-next-run right after a successful schedule call, and
records a failure for the just-saved alarm when the native count
falls short.

FakePuertoAlarmasAndroid.alarmasNativasPendientes now defaults to a
count derived from programar()/cancelar() calls (mirroring the real
native scheduler's own registry) instead of a frozen 0, while any
test that explicitly assigns the field keeps getting exactly that
value regardless of what programar/cancelar do afterward -- verified
against the full suite, no regressions.
This commit is contained in:
2026-07-31 21:26:41 +02:00
parent c107c0e18a
commit 7722f204ca
3 changed files with 136 additions and 4 deletions
+24 -1
View File
@@ -26,10 +26,27 @@ class FakePuertoAlarmasAndroid implements PuertoAlarmasAndroid {
bool puedeProgramarExactas = true;
bool notificacionesPermitidas = true;
bool puedeUsarPantallaCompleta = true;
int alarmasNativasPendientes = 0;
String fabricante = 'test';
int versionSdk = 35;
/// Ids [programar] most recently scheduled as active-with-a-next-run (kept
/// in sync with [cancelar] too), mirroring the real native scheduler's own
/// pending-alarm registry (fix/alarmas-fallos-silenciosos, item 3: "verify
/// the alarm is actually registered"). Backs [alarmasNativasPendientes]'s
/// DEFAULT so a test that never touches that field gets a value that
/// tracks reality instead of a frozen `0` -- a test that explicitly
/// assigns the field (many `pantalla_diagnostico_alarmas_test.dart` cases
/// do, to model a stale/corrupt native count on purpose) keeps getting
/// EXACTLY that value regardless of what programar/cancelar do afterward.
final _idsRegistradosNativamente = <String>{};
int? _alarmasNativasPendientesFijado;
int get alarmasNativasPendientes =>
_alarmasNativasPendientesFijado ?? _idsRegistradosNativamente.length;
set alarmasNativasPendientes(int valor) =>
_alarmasNativasPendientesFijado = valor;
/// Test-only failure switch (diagnostics screen, "intent not resolving"
/// coverage): when true, every `abrir*`/`solicitar*` system-screen action
/// below reports failure (as a real device does when a ROM lacks that
@@ -83,11 +100,17 @@ class FakePuertoAlarmasAndroid implements PuertoAlarmasAndroid {
throw StateError('fake programar failure');
}
programadas.add(alarma);
if (alarma.activa && alarma.proximaProgramable != null) {
_idsRegistradosNativamente.add(alarma.id);
} else {
_idsRegistradosNativamente.remove(alarma.id);
}
}
@override
Future<void> cancelar(String alarmaId) async {
canceladas.add(alarmaId);
_idsRegistradosNativamente.remove(alarmaId);
}
@override