Files
pluriwave/test/widgets/tarjeta_emisora_thumbnail_test.dart
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

117 lines
3.8 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/widgets/pluri_station_art_fallback.dart';
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../helpers/fakes.dart';
/// S6 (Tier 1 visual fidelity): the prototype's station thumbnail is a
/// plain 44-48px square, radius 11/12, with NO ring or glow (t4 lines 84
/// `44px/radius 11`, 175 `46px/radius 12`, 227 `48px/radius 12`, 302
/// `48px/radius 12`, 614 `44px/radius 12`). The compact row variant used to
/// paint a 58x58 circle with a `SweepGradient` ring and a 22-blur glow
/// behind a 50x50 `ClipRRect(18)`.
void main() {
setUp(() {
SharedPreferences.setMockInitialValues({});
});
Widget host(Widget child) {
final estado = EstadoRadio(
audio: FakeServicioAudio(),
favoritos: FakeServicioFavoritos(),
radio: FakeServicioRadio(),
servicioEcualizador: FakeServicioEcualizador(),
iniciarAutomaticamente: false,
);
addTearDown(estado.dispose);
return ChangeNotifierProvider<EstadoRadio>.value(
value: estado,
child: MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(body: Center(child: child)),
),
);
}
bool isRingContainer(Widget w) =>
w is Container &&
w.decoration is BoxDecoration &&
(w.decoration as BoxDecoration).shape == BoxShape.circle &&
(w.decoration as BoxDecoration).gradient is SweepGradient;
testWidgets('esCompacta (row) thumbnail is a 48x48 square, radius 12, no '
'ring/glow', (tester) async {
await tester.pumpWidget(
host(
SizedBox(
width: 320,
child: TarjetaEmisora(
emisora: emisoraDemo(uuid: 'row', nombre: 'Row FM'),
esCompacta: true,
),
),
),
);
await tester.pump();
expect(find.byWidgetPredicate(isRingContainer), findsNothing);
// Not `.first` — the outer PluriGlassSurface also renders its own
// ClipRRect (radius 14, the row surface radius from S4), so the
// thumbnail's own clip must be found by its distinct radius instead of
// tree order.
final thumbnailClip = find.byWidgetPredicate(
(w) => w is ClipRRect && w.borderRadius == BorderRadius.circular(12),
);
expect(thumbnailClip, findsOneWidget);
expect(tester.getSize(thumbnailClip), const Size(48, 48));
});
testWidgets(
'issue 6 (feedback-pruebas): a station with no favicon renders via the '
'shared PluriStationArtFallback (extracted from this exact fallback)',
(tester) async {
await tester.pumpWidget(
host(
TarjetaEmisora(
emisora: emisoraDemo(uuid: 'sin-arte', nombre: 'Sin Arte'),
esCompacta: true,
),
),
);
await tester.pump();
expect(find.byType(PluriStationArtFallback), findsOneWidget);
},
);
testWidgets('esCompacta shimmer placeholder is a square block, not a '
'circle', (tester) async {
await tester.pumpWidget(
host(const TarjetaEmisoraShimmer(esCompacta: true)),
);
await tester.pump();
expect(find.byWidgetPredicate(isRingContainer), findsNothing);
final circles = tester
.widgetList<Container>(find.byType(Container))
.where(
(c) =>
c.decoration is BoxDecoration &&
(c.decoration as BoxDecoration).shape == BoxShape.circle,
);
expect(
circles,
isEmpty,
reason: 'the real thumbnail is square now — its shimmer must match',
);
});
}