Files
pluriwave/test/pantallas/ajustes/pantalla_ajustes_grabaciones_test.dart
FreeTLab d81fabbe27 refactor(iap): make esPremium a required constructor parameter
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.
2026-08-10 22:06:36 +02:00

132 lines
4.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/estado/estado_grabacion.dart';
import 'package:pluriwave/l10n/gen/app_localizations.dart';
import 'package:pluriwave/pantallas/ajustes/pantalla_ajustes_grabaciones.dart';
import 'package:pluriwave/widgets/pluri_push_scaffold.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../helpers/fakes_alarmas.dart';
/// Pre-existing project constraint (see `pantalla_ajustes_test.dart`):
/// PluriGlassSurface paints a background over ListTile's ink layer, which
/// Flutter flags as a warning-level assertion, not a correctness bug.
void _suppressListTileInkAssertion() {
final original = FlutterError.onError;
FlutterError.onError = (details) {
if (details.exceptionAsString().contains(
'ListTile background color or ink splashes may be invisible',
)) {
return;
}
original?.call(details);
};
addTearDown(() => FlutterError.onError = original);
}
/// WU3b task 3b.1: the GRABACIONES Y MÚSICA detail screen for "Grabaciones"
/// renders inside a [PluriPushScaffold] and its moved controls still respond
/// exactly as they did inside the old `_SeccionGrabaciones`.
void main() {
setUp(() {
SharedPreferences.setMockInitialValues({});
});
Widget buildScreen(EstadoGrabacion estado) {
return ListenableProvider<EstadoGrabacion>.value(
value: estado,
child: MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const PantallaAjustesGrabaciones(),
),
);
}
testWidgets('renders inside a PluriPushScaffold titled "Recordings"', (
tester,
) async {
_suppressListTileInkAssertion();
final estado = EstadoGrabacion(
esPremium: () => true,
servicio: FakeServicioGrabacionRadioInactiva(),
);
addTearDown(estado.dispose);
await tester.pumpWidget(buildScreen(estado));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(find.byType(PluriPushScaffold), findsOneWidget);
expect(find.text('Recordings'), findsOneWidget);
});
testWidgets('moved control still responds: restore default path clears the '
'configured directory', (tester) async {
_suppressListTileInkAssertion();
final estado = EstadoGrabacion(
esPremium: () => true,
servicio: FakeServicioGrabacionRadioInactiva(),
);
addTearDown(estado.dispose);
await estado.cambiarDirectorio('/tmp/custom-recordings');
expect(estado.directorioConfigurado, '/tmp/custom-recordings');
await tester.pumpWidget(buildScreen(estado));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
await tester.tap(find.byIcon(Icons.restore_rounded));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(estado.directorioConfigurado, isNull);
expect(
find.text('The default internal folder will be used'),
findsOneWidget,
);
// SnackBar's own dismiss Timer is not frame-scheduled — let it resolve
// before teardown (WU3a batch discovery) instead of leaving a pending
// Timer behind.
await tester.pump(const Duration(seconds: 5));
await tester.pumpAndSettle();
});
testWidgets(
'moved control still responds: editing the maximum recording size '
'persists it',
(tester) async {
_suppressListTileInkAssertion();
final estado = EstadoGrabacion(
esPremium: () => true,
servicio: FakeServicioGrabacionRadioInactiva(),
);
addTearDown(estado.dispose);
expect(estado.maxBytes, 500 * 1024 * 1024, reason: 'default, not 250');
await tester.pumpWidget(buildScreen(estado));
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
await tester.tap(find.text('Maximum recording size'));
await tester.pumpAndSettle();
await tester.enterText(find.byType(TextField), '250');
await tester.pumpAndSettle();
await tester.tap(find.text('Save quick access'));
await tester.pumpAndSettle();
expect(estado.maxBytes, 250 * 1024 * 1024);
expect(find.text('Recording limit updated to 250 MB'), findsOneWidget);
// SnackBar's own dismiss Timer is not frame-scheduled — let it resolve
// before teardown (WU3a batch discovery) instead of leaving a pending
// Timer behind.
await tester.pump(const Duration(seconds: 5));
await tester.pumpAndSettle();
},
);
}