Files
pluriwave/test/widgets/fila_emisora_plana_test.dart
T
FreeTLab d1a911e587 fix(widgets): share station-art fallback across every surface
TarjetaEmisora had the only good fallback for a station with no artwork --
a deterministic pick from 4 bundled illustrations with a gradient/glyph
last resort. FilaEmisoraPlana's flat rows, the Escuchar hero, the "Tus
emisoras" grid cell, the mini player and the full player each had their
own, separate, flat primaryContainer square instead.

Extract the good fallback into PluriStationArtFallback and use it from
every one of those call sites. The selection formula (asset order,
codeUnits-sum modulo) is preserved exactly, since navegacion_auto.dart
mirrors the same formula independently for Android Auto's own drawable
rotation.
2026-07-30 18:54:31 +02:00

174 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/estado/estado_radio.dart';
import 'package:pluriwave/l10n/gen/app_localizations.dart';
import 'package:pluriwave/tema/pluriwave_tokens.dart';
import 'package:pluriwave/widgets/fila_emisora_plana.dart';
import 'package:pluriwave/widgets/pluri_station_art_fallback.dart';
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
import 'package:provider/provider.dart';
import '../helpers/fakes.dart';
import '../helpers/fakes_alarmas.dart';
EstadoRadio _estado() => EstadoRadio(
audio: FakeServicioAudio(),
favoritos: FakeServicioFavoritos(),
radio: FakeServicioRadio(),
servicioEcualizador: FakeServicioEcualizador(),
servicioGrabacion: FakeServicioGrabacionRadioInactiva(),
iniciarAutomaticamente: false,
);
Widget _host(EstadoRadio estado, Widget child) {
return ChangeNotifierProvider<EstadoRadio>.value(
value: estado,
child: MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(body: child),
),
);
}
/// Item 23 / audit 4.3 + 6.5 (t4:226-232, 302-306): the shared flat row
/// backing Favoritos and search results.
void main() {
testWidgets(
'renders a flat, background-less row -- no TarjetaEmisora underneath',
(tester) async {
final estado = _estado();
addTearDown(estado.dispose);
final emisora = emisoraDemo(uuid: 'a', nombre: 'Station A');
await tester.pumpWidget(
_host(estado, FilaEmisoraPlana(emisora: emisora, meta: 'Rock - Spain')),
);
await tester.pump();
expect(find.text('Station A'), findsOneWidget);
expect(find.text('Rock - Spain'), findsOneWidget);
expect(
find.byType(TarjetaEmisora),
findsNothing,
reason: 'a flat row does not reuse the full glass card',
);
},
);
testWidgets('the thumbnail is 48x48 with a 12 radius (t4:226, t4:302)', (
tester,
) async {
final estado = _estado();
addTearDown(estado.dispose);
final emisora = emisoraDemo(uuid: 'a', nombre: 'Station A');
await tester.pumpWidget(
_host(estado, FilaEmisoraPlana(emisora: emisora, meta: '')),
);
await tester.pump();
final arte = find.byKey(const ValueKey('fila-emisora-plana-arte'));
expect(tester.getSize(arte), const Size(48, 48));
final clip = tester.widget<ClipRRect>(arte);
expect(
(clip.borderRadius as BorderRadius).topLeft,
const Radius.circular(12),
);
});
testWidgets(
'issue 6 (feedback-pruebas): a station with no favicon shows the shared '
'PluriStationArtFallback, not a flat coloured square',
(tester) async {
final estado = _estado();
addTearDown(estado.dispose);
final emisora = emisoraDemo(uuid: 'sin-arte', nombre: 'Sin Arte');
await tester.pumpWidget(
_host(estado, FilaEmisoraPlana(emisora: emisora, meta: '')),
);
await tester.pump();
expect(
find.descendant(
of: find.byKey(const ValueKey('fila-emisora-plana-arte')),
matching: find.byType(PluriStationArtFallback),
),
findsOneWidget,
reason:
'issue 6: the flat row must reach the shared fallback, not its '
'own flat primaryContainer square',
);
},
);
testWidgets('omits the meta line entirely when empty (no stray gap)', (
tester,
) async {
final estado = _estado();
addTearDown(estado.dispose);
final emisora = emisoraDemo(uuid: 'a', nombre: 'Station A');
await tester.pumpWidget(
_host(estado, FilaEmisoraPlana(emisora: emisora, meta: '')),
);
await tester.pump();
expect(find.text('Station A'), findsOneWidget);
// Only the title Text should exist in the info column -- no empty
// second Text node.
expect(find.text(''), findsNothing);
});
testWidgets('BotonReproducirCircular is 44x44, brand-teal-tinted background, '
'22px play_arrow icon (t4:230, t4:305)', (tester) async {
var tapped = false;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: BotonReproducirCircular(onPressed: () => tapped = true),
),
),
);
await tester.pump();
final boton = find.byKey(const ValueKey('boton-reproducir-circular'));
final material = tester.widget<Material>(boton);
expect(material.color, PluriWaveTokens.brand.withValues(alpha: 0.14));
expect(material.shape, const CircleBorder());
final icon = tester.widget<Icon>(find.byIcon(Icons.play_arrow_rounded));
expect(icon.size, 22);
expect(icon.color, PluriWaveTokens.brand);
await tester.tap(find.byIcon(Icons.play_arrow_rounded));
expect(tapped, isTrue);
});
testWidgets(
'BotonFavoritoEmisora toggles favourite status and shows a snackbar '
'(t4:304)',
(tester) async {
final estado = _estado();
addTearDown(estado.dispose);
final emisora = emisoraDemo(uuid: 'a', nombre: 'Station A');
await tester.pumpWidget(
_host(estado, BotonFavoritoEmisora(emisora: emisora)),
);
await tester.pump();
expect(find.byIcon(Icons.favorite_outline_rounded), findsOneWidget);
await tester.tap(find.byIcon(Icons.favorite_outline_rounded));
await tester.pump();
await tester.pump();
expect(find.byIcon(Icons.favorite_rounded), findsOneWidget);
expect(await estado.esFavorito('a'), isTrue);
},
);
}