refactor(iap): make esPremium a required constructor parameter
EstadoAlarmas, EstadoGrabacion and EstadoRadio defaulted `esPremium` to `() => true`, so any construction site that forgot to wire entitlement compiled fine and silently ran ungated — failing OPEN to premium and disabling the paywall with no test able to catch it. The parameter is now required with no default. Production wiring in app.dart was already correct and is unchanged; the 184 pre-existing test call sites now pass `() => true` explicitly, which is exactly the old implicit default, so every assertion is untouched. EstadoRadio has no gate of its own but constructs EstadoGrabacion, so it inherits the same contract. The one test that existed to pin the old default is renamed to describe what it still covers (the premium path through iniciar() with no duracion); its assertions are unchanged.
This commit is contained in:
@@ -25,15 +25,15 @@ class EstadoAlarmas extends ChangeNotifier {
|
||||
// iap-freemium-unlock (Design ADR-3): entitlement query, mirroring
|
||||
// `EstadoGrabacion`'s `emisoraActual` callback-injection shape rather
|
||||
// than a direct `EstadoEntitlement` dependency (this notifier must stay
|
||||
// constructible with zero widget-tree/Provider context). Defaults to
|
||||
// "premium" (ungated) so every pre-existing test/call site that never
|
||||
// wires entitlement keeps its exact previous behavior — production
|
||||
// wiring in `app.dart` always passes the real callback.
|
||||
bool Function()? esPremium,
|
||||
// constructible with zero widget-tree/Provider context). REQUIRED on
|
||||
// purpose: an optional parameter with any default lets a forgotten
|
||||
// wiring compile and silently pick a tier, and no test can catch that.
|
||||
// Callers must state the entitlement source explicitly.
|
||||
required bool Function() esPremium,
|
||||
}) : servicio = servicio ?? ServicioAlarmas(prefs: prefs),
|
||||
android = android ?? ServicioAlarmasAndroid(),
|
||||
_prefs = prefs,
|
||||
_esPremium = esPremium ?? (() => true) {
|
||||
_esPremium = esPremium {
|
||||
// Decision 2.1 (snooze sync): the native layer reports its own snoozes
|
||||
// back through alarmFired/snoozed; record them here so the Flutter
|
||||
// config stays the single source of truth.
|
||||
|
||||
@@ -47,14 +47,15 @@ class EstadoGrabacion extends ChangeNotifier {
|
||||
Emisora? Function()? emisoraActual,
|
||||
void Function(String mensaje)? alError,
|
||||
// iap-freemium-unlock (Design ADR-3): entitlement query, mirroring
|
||||
// [_emisoraActual]'s callback-injection shape. Defaults to "premium"
|
||||
// (ungated) so every pre-existing test/call site keeps its exact
|
||||
// previous behavior — `app.dart` always wires the real callback.
|
||||
bool Function()? esPremium,
|
||||
// [_emisoraActual]'s callback-injection shape. REQUIRED on purpose: an
|
||||
// optional parameter with any default lets a forgotten wiring compile
|
||||
// and silently pick a tier, and no test can catch that. Callers must
|
||||
// state the entitlement source explicitly.
|
||||
required bool Function() esPremium,
|
||||
}) : servicio = servicio ?? ServicioGrabacionRadio(),
|
||||
_emisoraActual = emisoraActual ?? (() => null),
|
||||
_alError = alError,
|
||||
_esPremium = esPremium ?? (() => true) {
|
||||
_esPremium = esPremium {
|
||||
_suscripcion = this.servicio.estadoStream.listen((estado) {
|
||||
if (estado.tipo == EstadoGrabacionRadioTipo.error &&
|
||||
estado.error != null) {
|
||||
|
||||
@@ -49,8 +49,9 @@ class EstadoRadio extends ChangeNotifier {
|
||||
bool iniciarAutomaticamente = true,
|
||||
// iap-freemium-unlock (Design ADR-3): threaded straight through to the
|
||||
// internal `EstadoGrabacion` below — `EstadoRadio` itself has no gated
|
||||
// behavior of its own.
|
||||
bool Function()? esPremium,
|
||||
// behavior of its own, but it owns that notifier's construction, so it
|
||||
// inherits the same "required, never defaulted" entitlement contract.
|
||||
required bool Function() esPremium,
|
||||
}) : audio = audio ?? ServicioAudio(),
|
||||
favoritos = favoritos ?? ServicioFavoritos(),
|
||||
radio = radio ?? ServicioRadio(),
|
||||
|
||||
Reference in New Issue
Block a user