Files
pluriwave/test/widgets/pluri_station_art_fallback_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

87 lines
3.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/l10n/gen/app_localizations.dart';
import 'package:pluriwave/widgets/pluri_icon.dart';
import 'package:pluriwave/widgets/pluri_station_art_fallback.dart';
/// Issue 6 (feedback-pruebas): the shared station-art fallback extracted
/// from `TarjetaEmisora`'s original `_fallbackArtFor`. The formula and asset
/// order are pinned exactly — `navegacion_auto_test.dart`'s
/// `indiceArtePara`/`artUriPara` tests mirror the SAME formula independently
/// (protected file, empty diff vs main) and must keep agreeing with this
/// widget without either suite importing the other.
void main() {
Widget host(Widget child) {
return MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(body: SizedBox(width: 60, height: 60, child: child)),
);
}
test('artFor reproduces the canonical aurora/cosmic/pulse/nova order '
'(same formula as navegacion_auto.dart\'s indiceArtePara)', () {
// Single-letter seeds whose codeUnit % 4 covers all 4 indices, mirroring
// navegacion_auto_test.dart's own fixture exactly: 'd'(100)->0 aurora,
// 'a'(97)->1 cosmic, 'b'(98)->2 pulse, 'c'(99)->3 nova.
expect(
PluriStationArtFallback.artFor('d'),
'assets/images/station_art_aurora.png',
);
expect(
PluriStationArtFallback.artFor('a'),
'assets/images/station_art_cosmic.png',
);
expect(
PluriStationArtFallback.artFor('b'),
'assets/images/station_art_pulse.png',
);
expect(
PluriStationArtFallback.artFor('c'),
'assets/images/station_art_nova.png',
);
});
test('artFor is deterministic for a given seed (same station always picks '
'the same art)', () {
const seed = 'uuid-1234-abcd-real-looking';
expect(
PluriStationArtFallback.artFor(seed),
PluriStationArtFallback.artFor(seed),
);
});
testWidgets(
'renders the deterministic station-art asset plus a centred player glyph',
(tester) async {
await tester.pumpWidget(
host(const PluriStationArtFallback(seed: 'd', iconSize: 22)),
);
await tester.pump();
// Scoped by asset-name prefix, not `find.byType(Image).first` — the
// player glyph (`PluriIcon`) ALSO renders via its own `Image.asset`
// internally, so a bare type match would be ambiguous.
final arte = tester
.widgetList<Image>(find.byType(Image))
.firstWhere(
(img) =>
img.image is AssetImage &&
(img.image as AssetImage).assetName.startsWith(
'assets/images/station_art_',
),
);
expect(
(arte.image as AssetImage).assetName,
'assets/images/station_art_aurora.png',
);
final icono = tester.widget<PluriIcon>(find.byType(PluriIcon));
expect(icono.glyph, PluriIconGlyph.player);
expect(icono.variant, PluriIconVariant.activeGlow);
expect(icono.size, 22);
},
);
}