Files
pluriwave/test/helpers/fakes.dart
Javier Bautista Fernández d579a0e107 feat: Implement startup retry mechanism for custom stations and equalizer persistence
- Added state management for startup retry and custom station handling in `EstadoRadio`.
- Created tasks for implementing strict TDD with RED tests for HTTP failure retries and EQ persistence.
- Developed verification report to ensure compliance with TDD practices.
- Introduced fake services for testing, including `FakeServicioAudio`, `FakeServicioFavoritos`, and `FakeServicioRadio`.
- Implemented widget tests for `PantallaInicio` and `PantallaFavoritos` to validate UI behavior with custom stations.
- Enhanced `ServicioRadio` to support host rotation and retry logic for API calls.
- Established a new configuration file to enforce project constraints and testing rules.
2026-04-27 17:34:04 +02:00

214 lines
6.1 KiB
Dart

import 'dart:async';
import 'package:pluriwave/modelos/emisora.dart';
import 'package:pluriwave/modelos/preset_ecualizador.dart';
import 'package:pluriwave/servicios/servicio_audio.dart';
import 'package:pluriwave/servicios/servicio_ecualizador.dart';
import 'package:pluriwave/servicios/servicio_favoritos.dart';
import 'package:pluriwave/servicios/servicio_radio.dart';
class FakeServicioAudio extends ServicioAudio {
FakeServicioAudio({this.ecualizadorActivo = true}) {
_estadoController.add(EstadoReproduccion.detenido);
}
final bool ecualizadorActivo;
final _estadoController = StreamController<EstadoReproduccion>.broadcast();
final List<PresetEcualizador> presetsAplicados = [];
final List<Emisora> emisorasReproducidas = [];
Emisora? _emisoraActual;
@override
Emisora? get emisoraActual => _emisoraActual;
@override
bool get ecualizadorDisponible => ecualizadorActivo;
@override
Stream<EstadoReproduccion> get estadoStream => _estadoController.stream;
@override
Future<void> reproducir(Emisora emisora) async {
_emisoraActual = emisora;
emisorasReproducidas.add(emisora);
_estadoController.add(EstadoReproduccion.reproduciendo);
}
@override
Future<void> detener() async {
_emisoraActual = null;
_estadoController.add(EstadoReproduccion.detenido);
}
@override
Future<void> aplicarPreset(PresetEcualizador preset) async {
presetsAplicados.add(preset);
}
@override
Future<void> setBanda(int index, double db) async {}
@override
Future<void> dispose() async {
await _estadoController.close();
}
}
class FakeServicioFavoritos extends ServicioFavoritos {
final Map<String, Emisora> _favoritos = {};
int toggleCalls = 0;
@override
Future<List<Emisora>> obtenerTodos() async => _favoritos.values.toList();
@override
Future<void> agregar(Emisora emisora) async {
_favoritos[emisora.uuid] = emisora;
}
@override
Future<void> eliminar(String uuid) async {
_favoritos.remove(uuid);
}
@override
Future<bool> esFavorito(String uuid) async => _favoritos.containsKey(uuid);
@override
Future<bool> toggleFavorito(Emisora emisora) async {
toggleCalls += 1;
if (_favoritos.containsKey(emisora.uuid)) {
_favoritos.remove(emisora.uuid);
return false;
}
_favoritos[emisora.uuid] = emisora;
return true;
}
}
class FakeServicioRadio extends ServicioRadio {
FakeServicioRadio({
List<Emisora>? populares,
List<Emisora>? tendencias,
List<Emisora>? busqueda,
List<List<Emisora>>? popularesPorLlamada,
List<List<Emisora>>? tendenciasPorLlamada,
List<Object>? erroresPopularesPorLlamada,
List<Object>? erroresTendenciasPorLlamada,
}) : _populares = populares ?? [],
_tendencias = tendencias ?? [],
_busqueda = busqueda ?? [],
_popularesPorLlamada = popularesPorLlamada ?? const [],
_tendenciasPorLlamada = tendenciasPorLlamada ?? const [],
_erroresPopularesPorLlamada = erroresPopularesPorLlamada ?? const [],
_erroresTendenciasPorLlamada = erroresTendenciasPorLlamada ?? const [];
final List<Emisora> _populares;
final List<Emisora> _tendencias;
final List<Emisora> _busqueda;
final List<List<Emisora>> _popularesPorLlamada;
final List<List<Emisora>> _tendenciasPorLlamada;
final List<Object> _erroresPopularesPorLlamada;
final List<Object> _erroresTendenciasPorLlamada;
int obtenerPopularesCalls = 0;
int obtenerTendenciasCalls = 0;
int registrarClickCalls = 0;
String? ultimoUuidClick;
Exception _normalizarError(Object error) =>
error is Exception ? error : Exception(error.toString());
@override
Future<List<Emisora>> obtenerPopulares({int limit = 30}) async {
final llamada = obtenerPopularesCalls++;
if (llamada < _erroresPopularesPorLlamada.length) {
throw _normalizarError(_erroresPopularesPorLlamada[llamada]);
}
final data = llamada < _popularesPorLlamada.length
? _popularesPorLlamada[llamada]
: _populares;
return data.take(limit).toList();
}
@override
Future<List<Emisora>> obtenerTendencias({int limit = 20}) async {
final llamada = obtenerTendenciasCalls++;
if (llamada < _erroresTendenciasPorLlamada.length) {
throw _normalizarError(_erroresTendenciasPorLlamada[llamada]);
}
final data = llamada < _tendenciasPorLlamada.length
? _tendenciasPorLlamada[llamada]
: _tendencias;
return data.take(limit).toList();
}
@override
Future<List<Emisora>> buscar({
String? nombre,
String? pais,
String? idioma,
String? tag,
int limit = 30,
}) async {
return _busqueda.take(limit).toList();
}
@override
Future<void> registrarClick(String uuid) async {
registrarClickCalls += 1;
ultimoUuidClick = uuid;
}
}
class FakeServicioEcualizador extends ServicioEcualizador {
FakeServicioEcualizador({
PresetEcualizador? principal,
Map<String, PresetEcualizador>? porEmisora,
}) : _config = ConfiguracionEcualizador(
principal: principal ?? PresetEcualizador.flat,
porEmisora: porEmisora ?? {},
);
ConfiguracionEcualizador _config;
@override
Future<ConfiguracionEcualizador> cargar() async => _config;
@override
Future<void> guardarPrincipal(PresetEcualizador preset) async {
_config = ConfiguracionEcualizador(
principal: preset,
porEmisora: _config.porEmisora,
);
}
@override
Future<void> guardarPorEmisora(String uuid, PresetEcualizador preset) async {
final mapa = Map<String, PresetEcualizador>.from(_config.porEmisora);
mapa[uuid] = preset;
_config = ConfiguracionEcualizador(
principal: _config.principal,
porEmisora: mapa,
);
}
@override
Future<void> eliminarPorEmisora(String uuid) async {
final mapa = Map<String, PresetEcualizador>.from(_config.porEmisora);
mapa.remove(uuid);
_config = ConfiguracionEcualizador(
principal: _config.principal,
porEmisora: mapa,
);
}
}
Emisora emisoraDemo({
required String uuid,
required String nombre,
String url = 'https://stream.demo/radio',
}) {
return Emisora(uuid: uuid, nombre: nombre, url: url);
}