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.
175 lines
5.5 KiB
Dart
175 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(
|
|
esPremium: () => true,
|
|
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);
|
|
},
|
|
);
|
|
}
|