fix(bienvenida): wire the welcome screen into the first-launch flow
This commit is contained in:
+21
-4
@@ -14,6 +14,7 @@ import 'l10n/gen/app_localizations.dart';
|
|||||||
import 'modelos/alarma_musical.dart';
|
import 'modelos/alarma_musical.dart';
|
||||||
import 'pantallas/pantalla_alarmas.dart';
|
import 'pantallas/pantalla_alarmas.dart';
|
||||||
import 'pantallas/pantalla_alarma_sonando.dart';
|
import 'pantallas/pantalla_alarma_sonando.dart';
|
||||||
|
import 'pantallas/pantalla_bienvenida.dart';
|
||||||
import 'pantallas/pantalla_inicio.dart';
|
import 'pantallas/pantalla_inicio.dart';
|
||||||
import 'pantallas/pantalla_buscar.dart';
|
import 'pantallas/pantalla_buscar.dart';
|
||||||
import 'pantallas/pantalla_favoritos.dart';
|
import 'pantallas/pantalla_favoritos.dart';
|
||||||
@@ -108,7 +109,10 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
|
|||||||
EstadoRadio? _estadoSuscrito;
|
EstadoRadio? _estadoSuscrito;
|
||||||
bool _alarmaInicialProcesada = false;
|
bool _alarmaInicialProcesada = false;
|
||||||
bool _alarmaSonandoActiva = false;
|
bool _alarmaSonandoActiva = false;
|
||||||
bool _onboardingInicialSolicitado = false;
|
// WU17b: renamed from `_onboardingInicialSolicitado` — this single guard
|
||||||
|
// now covers the whole first-launch sequence (welcome screen, then the
|
||||||
|
// pre-existing what's-new dialog), not only the dialog.
|
||||||
|
bool _flujoPrimerLanzamientoSolicitado = false;
|
||||||
String? _alarmaSonandoId;
|
String? _alarmaSonandoId;
|
||||||
Locale? _localeAlarmasConfigurado;
|
Locale? _localeAlarmasConfigurado;
|
||||||
|
|
||||||
@@ -191,9 +195,9 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
|
|||||||
_alarmaInicialProcesada = true;
|
_alarmaInicialProcesada = true;
|
||||||
unawaited(_procesarAlarmaInicial(alarmas));
|
unawaited(_procesarAlarmaInicial(alarmas));
|
||||||
}
|
}
|
||||||
if (!_onboardingInicialSolicitado) {
|
if (!_flujoPrimerLanzamientoSolicitado) {
|
||||||
_onboardingInicialSolicitado = true;
|
_flujoPrimerLanzamientoSolicitado = true;
|
||||||
unawaited(_mostrarOnboardingInicial());
|
unawaited(_mostrarFlujoPrimerLanzamiento());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,6 +282,19 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WU17b: runs the welcome screen's once-ever check BEFORE the recurring
|
||||||
|
// what's-new dialog, so the two never show at the same time. The welcome
|
||||||
|
// screen (PantallaBienvenida) is the genuine first-run surface; the
|
||||||
|
// pre-existing PluriOnboardingDialog is an unrelated "what's new"/help
|
||||||
|
// modal that keeps its own independent per-version due-or-not logic,
|
||||||
|
// completely unchanged by this sequencing.
|
||||||
|
Future<void> _mostrarFlujoPrimerLanzamiento() async {
|
||||||
|
if (mounted) {
|
||||||
|
await PantallaBienvenida.mostrarSiProcede(context);
|
||||||
|
}
|
||||||
|
await _mostrarOnboardingInicial();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _mostrarOnboardingInicial() async {
|
Future<void> _mostrarOnboardingInicial() async {
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 900));
|
await Future<void>.delayed(const Duration(milliseconds: 900));
|
||||||
if (!mounted || _alarmaSonandoActiva) return;
|
if (!mounted || _alarmaSonandoActiva) return;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
import '../estado/estado_navegacion.dart';
|
import '../estado/estado_navegacion.dart';
|
||||||
import '../l10n/gen/app_localizations.dart';
|
import '../l10n/gen/app_localizations.dart';
|
||||||
|
import '../servicios/servicio_bienvenida.dart';
|
||||||
import '../tema/pluriwave_theme.dart';
|
import '../tema/pluriwave_theme.dart';
|
||||||
|
|
||||||
/// WU17: first-run welcome surface (`onboarding-welcome` spec, mockup
|
/// WU17: first-run welcome surface (`onboarding-welcome` spec, mockup
|
||||||
@@ -14,13 +15,31 @@ import '../tema/pluriwave_theme.dart';
|
|||||||
///
|
///
|
||||||
/// A full-screen ROUTE, not a modal `Dialog` — deliberately distinct from
|
/// A full-screen ROUTE, not a modal `Dialog` — deliberately distinct from
|
||||||
/// the pre-existing `PluriOnboardingDialog` (an unrelated "what's new"
|
/// the pre-existing `PluriOnboardingDialog` (an unrelated "what's new"
|
||||||
/// help-content modal already shown from `app.dart`'s launch flow). This
|
/// help-content modal already shown from `app.dart`'s launch flow). Both
|
||||||
/// work unit's own task list and verify command scope to this screen in
|
/// surfaces coexist: [mostrarSiProcede] (WU17b) is what actually wires this
|
||||||
/// isolation; wiring it into the real first-launch flow (i.e. deciding
|
/// screen into the genuine first-launch flow, called from `app.dart` BEFORE
|
||||||
/// when `app.dart`/`main.dart` should push it) is not part of WU17.
|
/// `PluriOnboardingDialog.mostrarSiProcede` on every cold start, so the two
|
||||||
|
/// never race — the once-ever welcome resolves first, then the recurring
|
||||||
|
/// what's-new dialog runs its own unrelated per-version check exactly as
|
||||||
|
/// before.
|
||||||
class PantallaBienvenida extends StatelessWidget {
|
class PantallaBienvenida extends StatelessWidget {
|
||||||
const PantallaBienvenida({super.key});
|
const PantallaBienvenida({super.key});
|
||||||
|
|
||||||
|
static final ServicioBienvenida _servicio = ServicioBienvenida();
|
||||||
|
|
||||||
|
/// WU17b: shows this screen once, on the genuine first launch, then never
|
||||||
|
/// again. Mirrors `PluriOnboardingDialog.mostrarSiProcede`'s shape
|
||||||
|
/// (check-then-show-then-mark-seen) so both first-launch surfaces share
|
||||||
|
/// the same call convention from `app.dart`.
|
||||||
|
static Future<void> mostrarSiProcede(BuildContext context) async {
|
||||||
|
if (!await _servicio.debeMostrarBienvenida()) return;
|
||||||
|
if (!context.mounted) return;
|
||||||
|
await Navigator.of(
|
||||||
|
context,
|
||||||
|
).push(MaterialPageRoute<void>(builder: (_) => const PantallaBienvenida()));
|
||||||
|
await _servicio.marcarBienvenidaVista();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context);
|
final l10n = AppLocalizations.of(context);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
/// WU17b: persists whether the first-run welcome screen (`PantallaBienvenida`,
|
||||||
|
/// `onboarding-welcome` spec) has already been shown, so it renders once
|
||||||
|
/// rather than on every launch.
|
||||||
|
///
|
||||||
|
/// Same injectable-`SharedPreferences`, versioned-key convention as
|
||||||
|
/// `ServicioContenidoApp` (S3-R4) — but a plain one-time boolean flag, since
|
||||||
|
/// this welcome screen is a single first-impression surface, not something
|
||||||
|
/// that re-triggers per app version the way the "what's new" onboarding
|
||||||
|
/// dialog does.
|
||||||
|
class ServicioBienvenida {
|
||||||
|
ServicioBienvenida({SharedPreferences? prefs}) : _prefs = prefs;
|
||||||
|
|
||||||
|
static const _keyBienvenidaVista = 'pluri_bienvenida_vista_v1';
|
||||||
|
|
||||||
|
final SharedPreferences? _prefs;
|
||||||
|
|
||||||
|
/// Injected startup instance (S3-R4); getInstance() is only a fallback.
|
||||||
|
Future<SharedPreferences> _resolverPrefs() async =>
|
||||||
|
_prefs ?? SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
Future<bool> debeMostrarBienvenida() async {
|
||||||
|
final prefs = await _resolverPrefs();
|
||||||
|
return !(prefs.getBool(_keyBienvenidaVista) ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> marcarBienvenidaVista() async {
|
||||||
|
final prefs = await _resolverPrefs();
|
||||||
|
await prefs.setBool(_keyBienvenidaVista, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,11 @@
|
|||||||
> **WU15b was added mid-apply, not planned upfront** — WU15 shipped `PantallaGrabaciones` (the recordings library)
|
> **WU15b was added mid-apply, not planned upfront** — WU15 shipped `PantallaGrabaciones` (the recordings library)
|
||||||
> fully tested but reachable from nowhere in the app. WU15b (below, after WU15's section) is the coordinator-ruled fix
|
> fully tested but reachable from nowhere in the app. WU15b (below, after WU15's section) is the coordinator-ruled fix
|
||||||
> that wires it into Settings navigation. It is small and does not change the 18-commit delivery model's shape.
|
> that wires it into Settings navigation. It is small and does not change the 18-commit delivery model's shape.
|
||||||
|
> **WU17b was added mid-apply, not planned upfront — same shape as WU15b.** WU17 shipped `PantallaBienvenida` (the
|
||||||
|
> welcome screen) fully tested but reachable from nowhere in the app (`rg "PantallaBienvenida" lib/app.dart lib/main.dart`
|
||||||
|
> found nothing). WU17b (below, after WU17's section) wires it into the genuine first-launch flow and establishes how
|
||||||
|
> it coexists with the pre-existing, unrelated `PluriOnboardingDialog` ("what's new" modal). It is small and does not
|
||||||
|
> change the 18-commit delivery model's shape.
|
||||||
> Strict TDD is ON. Runner: `flutter test`. `flutter analyze` and a **scoped** `dart format` gate every commit.
|
> Strict TDD is ON. Runner: `flutter test`. `flutter analyze` and a **scoped** `dart format` gate every commit.
|
||||||
> **`flutter build` is never run.**
|
> **`flutter build` is never run.**
|
||||||
>
|
>
|
||||||
@@ -1058,6 +1063,61 @@ real capability living in the header, not decorative chrome).
|
|||||||
`lib/l10n/app_*.arb` or `lib/`.
|
`lib/l10n/app_*.arb` or `lib/`.
|
||||||
- [x] 17.7 Verify — all 3 scenario tests green; grep scan clean.
|
- [x] 17.7 Verify — all 3 scenario tests green; grep scan clean.
|
||||||
|
|
||||||
|
## WU17b — Wire the welcome screen into the first-launch flow
|
||||||
|
|
||||||
|
**Not in the original plan — added to close the WU17 gap noted above, same shape as WU15/WU15b.** WU17 built
|
||||||
|
`PantallaBienvenida` fully tested and committed, but left it unreachable from the app: `rg "PantallaBienvenida"
|
||||||
|
lib/app.dart lib/main.dart` found nothing. This work unit exists solely to fix that.
|
||||||
|
|
||||||
|
**Commit**: `fix(bienvenida): wire the welcome screen into the first-launch flow`
|
||||||
|
**Depends on**: WU17
|
||||||
|
**Spec refs**: `onboarding-welcome` — Full-Screen Welcome Route (reachability; the render/content/no-monetization/CTA
|
||||||
|
scenarios stay WU17's own, unmodified)
|
||||||
|
**Verify**: `flutter test test/servicios/servicio_bienvenida_test.dart test/pantallas/pantalla_bienvenida_primer_lanzamiento_test.dart test/pantallas/pantalla_bienvenida_test.dart test/widget_test.dart && flutter analyze && dart format --set-exit-if-changed $(git diff --cached --name-only --diff-filter=ACM HEAD -- '*.dart')`
|
||||||
|
**New tests**: `test/servicios/servicio_bienvenida_test.dart`, `test/pantallas/pantalla_bienvenida_primer_lanzamiento_test.dart`
|
||||||
|
**Modified tests**: none (WU17's own `pantalla_bienvenida_test.dart` re-run unmodified as a regression check)
|
||||||
|
|
||||||
|
**Coexistence ruling applied.** `PluriOnboardingDialog` (an unrelated, pre-existing "what's new"/help-content modal
|
||||||
|
loaded from markdown assets) is NOT deleted, merged, or replaced — first-launch welcome and a what's-new modal are
|
||||||
|
different things, confirmed by reading `assets/content/onboarding/en.md`: it is a detailed feature-reference
|
||||||
|
walkthrough plus per-version update notes, structurally different content from the welcome screen's 3-bullet
|
||||||
|
marketing intro. Both now run from `app.dart`'s `_PaginaPrincipalState`, in this order on every cold start: the
|
||||||
|
welcome screen's once-ever check resolves FIRST, then the pre-existing what's-new dialog's own independent
|
||||||
|
per-version due-or-not check runs exactly as it did before this WU. Sequencing (not two independent fire-and-forget
|
||||||
|
calls) is what prevents the two from ever racing onto the screen at the same time.
|
||||||
|
|
||||||
|
- [x] 17b.1 RED — `test/servicios/servicio_bienvenida_test.dart`: a new `ServicioBienvenida` (mirroring
|
||||||
|
`ServicioContenidoApp`'s injectable-`SharedPreferences`, versioned-key convention, S3-R4) is due before it has
|
||||||
|
ever been marked seen, is not due after `marcarBienvenidaVista()`, and respects a seen flag already persisted
|
||||||
|
by a prior launch (`SharedPreferences.setMockInitialValues`).
|
||||||
|
- [x] 17b.2 RED — `test/pantallas/pantalla_bienvenida_primer_lanzamiento_test.dart`: a new
|
||||||
|
`PantallaBienvenida.mostrarSiProcede(context)` static method (mirroring `PluriOnboardingDialog.mostrarSiProcede`'s
|
||||||
|
check-then-show-then-mark-seen shape) pushes the welcome screen on a first launch (no seen flag persisted), does
|
||||||
|
NOT push it when the seen flag is already persisted, and — in one continuous session — persists the flag after
|
||||||
|
being shown once so a later check in the same run skips it.
|
||||||
|
- [x] 17b.3 GREEN — created `lib/servicios/servicio_bienvenida.dart` (`ServicioBienvenida`, key
|
||||||
|
`pluri_bienvenida_vista_v1`, plain one-time boolean — no version comparison needed, unlike
|
||||||
|
`ServicioContenidoApp`, since this welcome is a single first-impression surface, not a per-version one).
|
||||||
|
- [x] 17b.4 GREEN — added the static `PantallaBienvenida.mostrarSiProcede(BuildContext)` method to the existing
|
||||||
|
`pantalla_bienvenida.dart` file (no new wrapper class needed — unlike `PluriOnboardingDialog`, there is only one
|
||||||
|
call shape here); updated the class doc comment to describe how it coexists with `PluriOnboardingDialog`.
|
||||||
|
- [x] 17b.5 GREEN — wired `app.dart`: imported `pantalla_bienvenida.dart`; renamed the existing
|
||||||
|
`_onboardingInicialSolicitado` guard flag to `_flujoPrimerLanzamientoSolicitado` (it now covers the combined
|
||||||
|
sequence, not only the dialog); added `_mostrarFlujoPrimerLanzamiento()`, which awaits
|
||||||
|
`PantallaBienvenida.mostrarSiProcede(context)` then calls the pre-existing, untouched
|
||||||
|
`_mostrarOnboardingInicial()` — replacing the single `unawaited(_mostrarOnboardingInicial())` call site with
|
||||||
|
`unawaited(_mostrarFlujoPrimerLanzamiento())`.
|
||||||
|
- [x] 17b.6 REFACTOR — confirmed `_mostrarOnboardingInicial()`'s own body (900ms delay, `_alarmaSonandoActiva` guard,
|
||||||
|
`PluriOnboardingDialog.mostrarSiProcede` call) is byte-for-byte unchanged — only its call site moved one level
|
||||||
|
deeper into the new sequencing method. No scenario in `PantallaBienvenida`'s own WU17 test file needed to
|
||||||
|
change (all 3 pass unmodified, confirming the CTA/content/no-monetization behavior is untouched).
|
||||||
|
- [x] 17b.7 Verify — scoped suite green: 13/13 (3 `servicio_bienvenida_test.dart` + 3
|
||||||
|
`pantalla_bienvenida_primer_lanzamiento_test.dart` + 3 `pantalla_bienvenida_test.dart` [byte-identical,
|
||||||
|
unmodified] + 4 `widget_test.dart`). `flutter analyze`: 1 issue, identical to baseline. Scoped `dart format`:
|
||||||
|
reformatted 1 of 5 touched files (whitespace-only string-literal wrapping), stable on re-run. Literal-encoding
|
||||||
|
scan: one console-rendering false positive on the pre-existing "días" string (verified byte-correct UTF-8 via a
|
||||||
|
direct file read with the encoding pinned), zero real corruption.
|
||||||
|
|
||||||
## WU18 — i18n batch (all 13 locales)
|
## WU18 — i18n batch (all 13 locales)
|
||||||
|
|
||||||
**Commit**: `feat(i18n): add redesign strings and translate Escuchar rename to 11 locales`
|
**Commit**: `feat(i18n): add redesign strings and translate Escuchar rename to 11 locales`
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
||||||
|
import 'package:pluriwave/pantallas/pantalla_bienvenida.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
/// WU17b: `PantallaBienvenida.mostrarSiProcede` wires the welcome screen
|
||||||
|
/// into the genuine first-launch flow. WU17 built and tested the screen
|
||||||
|
/// fully in isolation, but nothing in `lib/app.dart` or `lib/main.dart`
|
||||||
|
/// ever referenced it — it was unreachable. These tests pin the actual
|
||||||
|
/// gap: the screen must show on a genuine first launch and never again
|
||||||
|
/// once `ServicioBienvenida` has recorded it as seen.
|
||||||
|
Widget _appConDisparador(GlobalKey<NavigatorState> navigatorKey) {
|
||||||
|
return MaterialApp(
|
||||||
|
navigatorKey: navigatorKey,
|
||||||
|
locale: const Locale('es'),
|
||||||
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
|
home: Builder(
|
||||||
|
builder:
|
||||||
|
(context) => Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => PantallaBienvenida.mostrarSiProcede(context),
|
||||||
|
child: const Text('disparar'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'first launch (no seen flag persisted) shows the welcome screen',
|
||||||
|
(tester) async {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
await tester.pumpWidget(_appConDisparador(navigatorKey));
|
||||||
|
await tester.tap(find.text('disparar'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byType(PantallaBienvenida), findsOneWidget);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'second launch (seen flag already persisted) does not show it again',
|
||||||
|
(tester) async {
|
||||||
|
SharedPreferences.setMockInitialValues({
|
||||||
|
'pluri_bienvenida_vista_v1': true,
|
||||||
|
});
|
||||||
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
await tester.pumpWidget(_appConDisparador(navigatorKey));
|
||||||
|
await tester.tap(find.text('disparar'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byType(PantallaBienvenida), findsNothing);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets('showing it once persists the flag so a later check in the same '
|
||||||
|
'session skips it', (tester) async {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
await tester.pumpWidget(_appConDisparador(navigatorKey));
|
||||||
|
await tester.tap(find.text('disparar'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.byType(PantallaBienvenida), findsOneWidget);
|
||||||
|
|
||||||
|
// Dismiss it the same way the CTA does (a plain pop), simulating the
|
||||||
|
// welcome screen being resolved before the next check ever happens.
|
||||||
|
navigatorKey.currentState!.pop();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.text('disparar'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.byType(PantallaBienvenida), findsNothing);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pluriwave/servicios/servicio_bienvenida.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
/// WU17b: `ServicioBienvenida` decides whether the first-run welcome
|
||||||
|
/// screen (`PantallaBienvenida`) is still due — same injectable-prefs,
|
||||||
|
/// versioned-key convention as `ServicioContenidoApp` (S3-R4), but a plain
|
||||||
|
/// boolean flag since this welcome is a one-time, not per-version, surface.
|
||||||
|
void main() {
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('ServicioBienvenida', () {
|
||||||
|
test(
|
||||||
|
'debeMostrarBienvenida is true before it has ever been marked seen',
|
||||||
|
() async {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
final servicio = ServicioBienvenida();
|
||||||
|
|
||||||
|
expect(await servicio.debeMostrarBienvenida(), isTrue);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'debeMostrarBienvenida is false after marcarBienvenidaVista',
|
||||||
|
() async {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
final servicio = ServicioBienvenida();
|
||||||
|
|
||||||
|
await servicio.marcarBienvenidaVista();
|
||||||
|
|
||||||
|
expect(await servicio.debeMostrarBienvenida(), isFalse);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test('respects a seen flag already persisted by a prior launch', () async {
|
||||||
|
SharedPreferences.setMockInitialValues({
|
||||||
|
'pluri_bienvenida_vista_v1': true,
|
||||||
|
});
|
||||||
|
final servicio = ServicioBienvenida();
|
||||||
|
|
||||||
|
expect(await servicio.debeMostrarBienvenida(), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user