Files
pluriwave/test/pantallas/pantalla_tutorial_ayuda_test.dart
FreeTLab 015a20a823 feat(tutorial): add 9-screen help/tutorial carousel
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.
2026-08-01 11:34:53 +02:00

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