Introduce multi-device EQ support allowing each audio output device (built-in speaker, wired, USB, individual Bluetooth by MAC) to have its own equalizer preset, combined with existing per-station presets for a full station×device matrix. - Add DispositivoAudio model and ServicioDispositivoAudio interface - Add Android platform channel (AudioDeviceCallback) for device detection - Add iOS AudioDevicesPlugin (AVAudioSession route tracking) - Extend ServicioEcualizador with device and matrix persistence keys - Implement 4-level resolution: matrix > station > device > global - Add advanced EQ settings section with feature toggle (off by default) - Extend export/import to v3 with backward compatibility - 184 tests passing, zero analyzer issues
83 lines
2.2 KiB
Dart
83 lines
2.2 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:pluriwave/modelos/dispositivo_audio.dart';
|
|
|
|
import '../helpers/fakes.dart';
|
|
|
|
void main() {
|
|
group('ServicioDispositivoAudio (abstract contract)', () {
|
|
late FakeServicioDispositivoAudio fake;
|
|
|
|
setUp(() {
|
|
fake = FakeServicioDispositivoAudio();
|
|
});
|
|
|
|
tearDown(() async {
|
|
await fake.dispose();
|
|
});
|
|
|
|
test('dispositivoActual is null initially', () {
|
|
expect(fake.dispositivoActual, isNull);
|
|
});
|
|
|
|
test(
|
|
'obtenerDispositivoActual returns current device after emit',
|
|
() async {
|
|
const device = DispositivoAudio(
|
|
id: 'builtin_speaker',
|
|
tipo: TipoDispositivo.altavozInterno,
|
|
nombre: 'Speaker',
|
|
);
|
|
fake.emitirDispositivo(device);
|
|
|
|
final result = await fake.obtenerDispositivoActual();
|
|
expect(result, equals(device));
|
|
},
|
|
);
|
|
|
|
test('onDispositivoCambiado stream emits when device changes', () async {
|
|
const deviceA = DispositivoAudio(
|
|
id: 'builtin_speaker',
|
|
tipo: TipoDispositivo.altavozInterno,
|
|
nombre: 'Speaker',
|
|
);
|
|
const deviceB = DispositivoAudio(
|
|
id: 'bt_a2dp:AA:BB:CC:DD:EE:FF',
|
|
tipo: TipoDispositivo.bluetoothA2dp,
|
|
nombre: 'BT Headphones',
|
|
);
|
|
|
|
final received = <DispositivoAudio>[];
|
|
final sub = fake.onDispositivoCambiado.listen(received.add);
|
|
|
|
fake.emitirDispositivo(deviceA);
|
|
fake.emitirDispositivo(deviceB);
|
|
|
|
await Future<void>.delayed(Duration.zero);
|
|
await sub.cancel();
|
|
|
|
expect(received, equals([deviceA, deviceB]));
|
|
});
|
|
|
|
test('dispositivoActual tracks last emitted device', () {
|
|
const device = DispositivoAudio(
|
|
id: 'wired_headset',
|
|
tipo: TipoDispositivo.auricularesCable,
|
|
nombre: 'Wired Headset',
|
|
);
|
|
fake.emitirDispositivo(device);
|
|
expect(fake.dispositivoActual, equals(device));
|
|
});
|
|
|
|
test(
|
|
'onDispositivoCambiado is a broadcast stream (multiple listeners)',
|
|
() {
|
|
expect(fake.onDispositivoCambiado.isBroadcast, isTrue);
|
|
},
|
|
);
|
|
|
|
test('dispose closes the stream without error', () async {
|
|
await expectLater(fake.dispose(), completes);
|
|
});
|
|
});
|
|
}
|