52855e75c2
- New EstadoGrabacion owns the recording service, subscription, directory/size preferences and open-file actions - New EstadoBusqueda owns search, nearby stations, pagination and the min-bitrate filter - New orden_emisoras.dart with the OrdenEmisoras enum, shared sorter and list identity memoization so context.select comparisons work on derived lists - Large screens (inicio, buscar, favoritos, ajustes, reproductor) consume scoped selects/dedicated notifiers instead of root context.watch<EstadoRadio>, so audio buffer events no longer rebuild whole screens - Remove all 15 TODO(S4b) compat members from EstadoRadio; consumers use the dedicated providers. EstadoRadio drops from ~1121 to 753 lines, keeping playback/stations/favorites orchestration - 8 new tests including a rebuild-scoping probe (110 total green), flutter analyze clean
101 lines
3.7 KiB
Dart
101 lines
3.7 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:pluriwave/estado/estado_busqueda.dart';
|
|
import 'package:pluriwave/estado/estado_ecualizador.dart';
|
|
import 'package:pluriwave/estado/estado_grabacion.dart';
|
|
import 'package:pluriwave/estado/estado_radio.dart';
|
|
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
|
import 'package:pluriwave/modelos/preset_ecualizador.dart';
|
|
import 'package:pluriwave/pantallas/pantalla_inicio.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../helpers/fakes.dart';
|
|
|
|
/// S4-R5-A: changing the EQ preset must NOT rebuild PantallaInicio.
|
|
void main() {
|
|
setUp(() {
|
|
SharedPreferences.setMockInitialValues({});
|
|
});
|
|
|
|
testWidgets('cambiar el preset de EQ no marca PantallaInicio para rebuild', (
|
|
tester,
|
|
) async {
|
|
tester.view.physicalSize = const Size(1440, 3200);
|
|
tester.view.devicePixelRatio = 1.0;
|
|
addTearDown(tester.view.resetPhysicalSize);
|
|
addTearDown(tester.view.resetDevicePixelRatio);
|
|
|
|
final radio = FakeServicioRadio(
|
|
populares: [emisoraDemo(uuid: 'api-1', nombre: 'API Uno')],
|
|
popularesPorLlamada: [
|
|
[emisoraDemo(uuid: 'api-1', nombre: 'API Uno')],
|
|
[emisoraDemo(uuid: 'api-2', nombre: 'API Dos')],
|
|
],
|
|
);
|
|
final estado = EstadoRadio(
|
|
audio: FakeServicioAudio(),
|
|
favoritos: FakeServicioFavoritos(),
|
|
radio: radio,
|
|
servicioEcualizador: FakeServicioEcualizador(),
|
|
resolverArchivoCustom:
|
|
() async => File(
|
|
'${Directory.current.path}/test/fixtures/emisoras_custom_vacio.json',
|
|
),
|
|
iniciarAutomaticamente: false,
|
|
);
|
|
addTearDown(estado.dispose);
|
|
await tester.runAsync(estado.inicializar);
|
|
|
|
await tester.pumpWidget(
|
|
MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider<EstadoRadio>.value(value: estado),
|
|
ListenableProvider<EstadoEcualizador>.value(
|
|
value: estado.ecualizador,
|
|
),
|
|
ListenableProvider<EstadoBusqueda>.value(value: estado.busqueda),
|
|
ListenableProvider<EstadoGrabacion>.value(value: estado.grabacion),
|
|
],
|
|
child: MaterialApp(
|
|
locale: const Locale('es'),
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
home: const Scaffold(body: PantallaInicio()),
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 100));
|
|
|
|
// Provider defers dependent notification to the next build phase, so a
|
|
// dirty-flag probe cannot observe it synchronously. Instead, log every
|
|
// element rebuilt per frame and look for the screen in that log.
|
|
final registro = <String>[];
|
|
final debugPrintOriginal = debugPrint;
|
|
debugPrintRebuildDirtyWidgets = true;
|
|
debugPrint = (String? message, {int? wrapWidth}) {
|
|
registro.add(message ?? '');
|
|
};
|
|
addTearDown(() {
|
|
debugPrintRebuildDirtyWidgets = false;
|
|
debugPrint = debugPrintOriginal;
|
|
});
|
|
|
|
// EQ preset change: a different notifier — must NOT rebuild the screen.
|
|
await estado.ecualizador.cambiarPresetPrincipal(PresetEcualizador.rock);
|
|
await tester.pump();
|
|
expect(registro.any((linea) => linea.contains('PantallaInicio')), isFalse);
|
|
|
|
// Probe control: a real data change DOES rebuild the screen.
|
|
registro.clear();
|
|
await tester.runAsync(estado.cargarPopulares);
|
|
await tester.pump();
|
|
expect(registro.any((linea) => linea.contains('PantallaInicio')), isTrue);
|
|
debugPrintRebuildDirtyWidgets = false;
|
|
debugPrint = debugPrintOriginal;
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 100));
|
|
});
|
|
}
|