EstadoAlarmas, EstadoGrabacion and EstadoRadio defaulted `esPremium` to `() => true`, so any construction site that forgot to wire entitlement compiled fine and silently ran ungated — failing OPEN to premium and disabling the paywall with no test able to catch it. The parameter is now required with no default. Production wiring in app.dart was already correct and is unchanged; the 184 pre-existing test call sites now pass `() => true` explicitly, which is exactly the old implicit default, so every assertion is untouched. EstadoRadio has no gate of its own but constructs EstadoGrabacion, so it inherits the same contract. The one test that existed to pin the old default is renamed to describe what it still covers (the premium path through iniciar() with no duracion); its assertions are unchanged.
118 lines
3.9 KiB
Dart
118 lines
3.9 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(
|
|
esPremium: () => true,
|
|
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',
|
|
);
|
|
});
|
|
}
|