Files
pluriwave/test/pantallas/pantalla_buscar_shimmer_test.dart
T
FreeTLab e5d461af53 fix(buscar): build the 2x2 "Explorar por" grid, add Novedades
Audit 3.2 (t4 lines 162-171): the prototype groups Países, Géneros,
Tendencias and the entirely-missing Novedades into one 2x2 entry-point
grid. The build had them as three unrelated always-visible widgets
(a Países ListTile, a Géneros FilterChip Wrap, a Tendencias ActionChip
strip) and no Novedades entry at all.

Replaces all three with a single grid section, capability-preserving:
Países still pushes PantallaPaises; Géneros and Tendencias now open
their exact existing content in a picker sheet instead of always-on-
screen (Géneros auto-closes on selection, matching this screen's other
single-choice filter sheets; Tendencias stays open, a browse list, not
a filter). Novedades re-triggers the existing discovery refresh, since
no distinct "new stations" feed exists anywhere in the domain.

New ARB key set (exploreByTitle/exploreTrendingTitle/
exploreTrendingSubtitle/exploreNewTitle/exploreNewSubtitle) translated
across all 13 locales with zero anti-copy allowlist entries needed.

Also fixes a pre-existing PluriEmptyState overflow this restructure
exposed (unrelated to the grid itself, confirmed via isolated repro):
wraps its Column in a SingleChildScrollView so a too-tall title/
subtitle scrolls instead of throwing a hard RenderFlex overflow.
2026-07-30 00:43:27 +02:00

93 lines
3.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/estado/estado_busqueda.dart';
import 'package:pluriwave/estado/estado_ecualizador.dart';
import 'package:pluriwave/estado/estado_grabacion.dart';
import 'package:pluriwave/estado/estado_radio.dart';
import 'package:pluriwave/l10n/gen/app_localizations.dart';
import 'package:pluriwave/pantallas/pantalla_buscar.dart';
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../helpers/fakes.dart';
/// S5-R6: the search loading state uses shimmer placeholders, not a bare
/// spinner, to stay consistent with the rest of the app.
///
/// WU6 correction: `PantallaBuscar` now also renders a discovery LANDING
/// state (task 6.5) that reads `EstadoRadio` directly, so any widget test
/// mounting it — this one included — must provide a full `EstadoRadio`
/// provider from the start, not just `EstadoBusqueda`. A non-empty query is
/// entered first so the screen leaves the landing state and reaches the
/// search-results branch this test actually targets.
///
/// Bugfix (surfaced while landing audit item 18's "Explorar por" grid):
/// on the FIRST pump here (landing state, empty `EstadoRadio`, default
/// narrow test viewport, no `_setLargeSurfaceSize`), `_gridEmisoras`
/// renders its empty-state branch — `PluriEmptyState`, in a fixed
/// `SizedBox(height: 260)`. That widget's own Column overflowed by 10px
/// at this width with real ARB copy (`pluri_premium_widgets.dart`,
/// fixed by wrapping it in a `SingleChildScrollView` — a no-op whenever
/// content already fits, which is every real device width). This test IS
/// the end-to-end regression guard for that fix: it renders the exact
/// scenario that surfaced it.
class _BusquedaCargando extends EstadoBusqueda {
_BusquedaCargando() : super(radio: FakeServicioRadio());
@override
bool get cargando => true;
}
void main() {
setUp(() {
SharedPreferences.setMockInitialValues({});
});
testWidgets('PantallaBuscar muestra shimmer mientras carga', (tester) async {
final busqueda = _BusquedaCargando();
addTearDown(busqueda.dispose);
final estado = EstadoRadio(
audio: FakeServicioAudio(),
favoritos: FakeServicioFavoritos(),
radio: FakeServicioRadio(),
servicioEcualizador: FakeServicioEcualizador(),
servicioGrabacion: FakeServicioGrabacionRadio(),
resolverArchivoCustom: () async => throw UnimplementedError(),
iniciarAutomaticamente: false,
);
addTearDown(estado.dispose);
await tester.pumpWidget(
MultiProvider(
providers: [
ChangeNotifierProvider<EstadoRadio>.value(value: estado),
ListenableProvider<EstadoEcualizador>.value(
value: estado.ecualizador,
),
ListenableProvider<EstadoGrabacion>.value(value: estado.grabacion),
// Overrides EstadoRadio's own (unused here) EstadoBusqueda with a
// fake pinned to cargando: true.
ListenableProvider<EstadoBusqueda>.value(value: busqueda),
],
child: MaterialApp(
locale: const Locale('es'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const Scaffold(body: PantallaBuscar()),
),
),
);
await tester.pump();
// Still the landing state — no query entered yet.
expect(find.byType(TarjetaEmisoraShimmer), findsNothing);
await tester.enterText(find.byType(SearchBar), 'jazz');
await tester.pump();
expect(find.byType(TarjetaEmisoraShimmer), findsWidgets);
expect(find.byType(CircularProgressIndicator), findsNothing);
});
}