Add PantallaTutorialAyuda, a PageView-based carousel covering saved
stations/groups, per-station equalizer, recording, adaptive alarms,
Android Auto favorites, auto-reconnect, snooze duration, custom
stations, and a closing summary with a "watch it again" reminder.
ServicioTutorialAyuda persists a one-time seen flag so the carousel
shows once via mostrarSiProcede, independent of entry point; the
final page's CTA label depends on the primerArranque constructor
parameter ("Empezar a escuchar" vs "Cerrar").
Translate the new copy into all 13 supported locales and update
helpSubtitle to describe the new entry point.
241 lines
7.7 KiB
Dart
241 lines
7.7 KiB
Dart
import 'dart:async';
|
|
|
|
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_tutorial_ayuda.dart';
|
|
|
|
/// The 9-screen help/tutorial carousel (`PantallaTutorialAyuda`). Content
|
|
/// spec: mockup screens 5b..5h (reading order 1..9), each with an icon
|
|
/// badge, a headline, a body, a 9-dot progress indicator, a "Siguiente"
|
|
/// (Next) button, and -- on every page except the last -- a "Saltar"
|
|
/// (Skip) affordance. The last page's CTA reads "Empezar a escuchar" on a
|
|
/// first-launch entry, or "Cerrar" when reached manually from Ajustes
|
|
/// (`primerArranque` constructor param), and it drops "Saltar" entirely.
|
|
Widget _app({required bool primerArranque}) {
|
|
return MaterialApp(
|
|
locale: const Locale('es'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: PantallaTutorialAyuda(primerArranque: primerArranque),
|
|
);
|
|
}
|
|
|
|
/// The 9 expected headlines, in the mandated reading order (mockup ids
|
|
/// 5b, 5c, 5d, 5e, 5f, 5g, 5h1, 5h2, 5h).
|
|
List<String> _headlinesEsperados(AppLocalizations l10n) => [
|
|
l10n.tutorialPage1Headline,
|
|
l10n.tutorialPage2Headline,
|
|
l10n.tutorialPage3Headline,
|
|
l10n.tutorialPage4Headline,
|
|
l10n.tutorialPage5Headline,
|
|
l10n.tutorialPage6Headline,
|
|
l10n.tutorialPage7Headline,
|
|
l10n.tutorialPage8Headline,
|
|
l10n.tutorialPage9Headline,
|
|
];
|
|
|
|
void main() {
|
|
final l10n = lookupAppLocalizations(const Locale('es'));
|
|
|
|
testWidgets('renders exactly 9 pages, one dot per page', (tester) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
expect(pageView.controller!.hasClients, isTrue);
|
|
|
|
expect(
|
|
find.byType(PuntoIndicadorTutorial),
|
|
findsNWidgets(9),
|
|
reason: 'exactly 9 dots, one per page',
|
|
);
|
|
});
|
|
|
|
testWidgets(
|
|
'the 9 pages carry the right headlines, in the mandated reading order',
|
|
(tester) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
final controller = pageView.controller!;
|
|
final esperados = _headlinesEsperados(l10n);
|
|
|
|
for (var i = 0; i < esperados.length; i++) {
|
|
controller.jumpToPage(i);
|
|
await tester.pump();
|
|
expect(
|
|
find.text(esperados[i]),
|
|
findsOneWidget,
|
|
reason: 'page $i should show "${esperados[i]}"',
|
|
);
|
|
}
|
|
},
|
|
);
|
|
|
|
testWidgets('Saltar pops immediately from the first page', (tester) async {
|
|
final navigatorKey = GlobalKey<NavigatorState>();
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorKey: navigatorKey,
|
|
locale: const Locale('es'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: const Scaffold(body: Center(child: Text('home stand-in'))),
|
|
),
|
|
);
|
|
|
|
unawaited(
|
|
navigatorKey.currentState!.push(
|
|
MaterialPageRoute<void>(
|
|
builder: (_) => const PantallaTutorialAyuda(primerArranque: true),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
expect(find.byType(PantallaTutorialAyuda), findsOneWidget);
|
|
|
|
await tester.tap(find.text(l10n.tutorialSkipAction));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(PantallaTutorialAyuda), findsNothing);
|
|
expect(find.text('home stand-in'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets(
|
|
'Saltar pops immediately from a middle page, not only the first',
|
|
(tester) async {
|
|
final navigatorKey = GlobalKey<NavigatorState>();
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorKey: navigatorKey,
|
|
locale: const Locale('es'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: const Scaffold(body: Center(child: Text('home stand-in'))),
|
|
),
|
|
);
|
|
|
|
unawaited(
|
|
navigatorKey.currentState!.push(
|
|
MaterialPageRoute<void>(
|
|
builder: (_) => const PantallaTutorialAyuda(primerArranque: true),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(3);
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.text(l10n.tutorialSkipAction));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(PantallaTutorialAyuda), findsNothing);
|
|
expect(find.text('home stand-in'), findsOneWidget);
|
|
},
|
|
);
|
|
|
|
testWidgets('Siguiente advances from the first page to the second', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
expect(find.text(l10n.tutorialPage1Headline), findsOneWidget);
|
|
|
|
await tester.tap(find.text(l10n.tutorialNextAction));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text(l10n.tutorialPage2Headline), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Saltar is not offered on the last page', (tester) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(8);
|
|
await tester.pump();
|
|
|
|
expect(find.text(l10n.tutorialSkipAction), findsNothing);
|
|
});
|
|
|
|
testWidgets(
|
|
'last page CTA reads "Empezar a escuchar" when reached via first launch',
|
|
(tester) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(8);
|
|
await tester.pump();
|
|
|
|
expect(find.text(l10n.welcomeCtaLabel), findsOneWidget);
|
|
expect(find.text(l10n.closeAction), findsNothing);
|
|
},
|
|
);
|
|
|
|
testWidgets(
|
|
'last page CTA reads "Cerrar" when reached manually from Ajustes',
|
|
(tester) async {
|
|
await tester.pumpWidget(_app(primerArranque: false));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(8);
|
|
await tester.pump();
|
|
|
|
expect(find.text(l10n.closeAction), findsOneWidget);
|
|
expect(find.text(l10n.welcomeCtaLabel), findsNothing);
|
|
},
|
|
);
|
|
|
|
testWidgets('tapping the last page CTA pops the route', (tester) async {
|
|
final navigatorKey = GlobalKey<NavigatorState>();
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
navigatorKey: navigatorKey,
|
|
locale: const Locale('es'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: const Scaffold(body: Center(child: Text('home stand-in'))),
|
|
),
|
|
);
|
|
|
|
unawaited(
|
|
navigatorKey.currentState!.push(
|
|
MaterialPageRoute<void>(
|
|
builder: (_) => const PantallaTutorialAyuda(primerArranque: false),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(8);
|
|
await tester.pump();
|
|
|
|
await tester.tap(find.text(l10n.closeAction));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.byType(PantallaTutorialAyuda), findsNothing);
|
|
expect(find.text('home stand-in'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('the last page shows the "watch it again" reminder banner', (
|
|
tester,
|
|
) async {
|
|
await tester.pumpWidget(_app(primerArranque: true));
|
|
await tester.pump();
|
|
|
|
final pageView = tester.widget<PageView>(find.byType(PageView));
|
|
pageView.controller!.jumpToPage(8);
|
|
await tester.pump();
|
|
|
|
expect(find.text(l10n.tutorialPage9BannerBody), findsOneWidget);
|
|
});
|
|
}
|