Item 23 / audit 4.3, 12.4 (t4:226-232, 616-619): Favoritos and Grabaciones rows were full glass cards / ListTiles with two stacked buttons and no artwork slot. Replace with flat, background-less rows via a new shared FilaEmisoraPlana widget (square art, name+meta, a circular play affordance) plus a bespoke Grabaciones row (44x12 placeholder art -- recordings carry no per-station favicon, so this is a themed fallback, not invented artwork). Favoritos keeps "Move to list" / "Remove from favorites" behind an overflow menu (same underlying methods, unchanged) instead of two always-visible buttons, since dropping either would be a functional regression the prototype's own row doesn't have to solve for. Also 12.1 (t4:610): the Grabaciones header action is folder_open, not a generic gear.
147 lines
4.6 KiB
Dart
147 lines
4.6 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/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('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);
|
|
},
|
|
);
|
|
}
|