Dart half of bt-device-identity. EstadoEcualizador now caches each device's platform-reported name in memory so the settings screen shows the device's own Bluetooth name instead of its raw id when no custom rename exists, and skips auto-creating preset entries for the composite-placeholder sentinel. Enabling multi-device EQ triggers the Bluetooth permission request through the new channel contract. A flag-guarded one-time migration purges only entries keyed by the exact literal placeholder id from the three per-device preference maps, since those collided entries cannot be attributed to a device. Work unit 2/2 of bt-device-identity (Dart state + migration).
77 lines
2.4 KiB
Dart
77 lines
2.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:pluriwave/modelos/dispositivo_audio.dart';
|
|
import 'package:pluriwave/servicios/servicio_dispositivo_audio.dart';
|
|
|
|
import '../helpers/fakes.dart';
|
|
|
|
/// Null (toggle-off) implementation that returns empty data without errors.
|
|
/// Represents the behavior when `eqMultiDeviceEnabled` is false.
|
|
class NullServicioDispositivoAudio extends ServicioDispositivoAudio {
|
|
@override
|
|
DispositivoAudio? get dispositivoActual => null;
|
|
|
|
@override
|
|
Stream<DispositivoAudio> get onDispositivoCambiado => const Stream.empty();
|
|
|
|
@override
|
|
Future<DispositivoAudio> obtenerDispositivoActual() async {
|
|
return const DispositivoAudio(
|
|
id: 'builtin_speaker',
|
|
tipo: TipoDispositivo.altavozInterno,
|
|
nombre: 'Speaker',
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> solicitarPermisoBluetooth() async => true;
|
|
|
|
@override
|
|
Future<void> dispose() async {}
|
|
}
|
|
|
|
void main() {
|
|
group('Toggle-off path: NullServicioDispositivoAudio', () {
|
|
late NullServicioDispositivoAudio servicio;
|
|
|
|
setUp(() {
|
|
servicio = NullServicioDispositivoAudio();
|
|
});
|
|
|
|
test('dispositivoActual is always null', () {
|
|
expect(servicio.dispositivoActual, isNull);
|
|
});
|
|
|
|
test('onDispositivoCambiado emits no events', () async {
|
|
final received = <DispositivoAudio>[];
|
|
final sub = servicio.onDispositivoCambiado.listen(received.add);
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
await sub.cancel();
|
|
expect(received, isEmpty);
|
|
});
|
|
|
|
test('obtenerDispositivoActual returns fallback builtin_speaker', () async {
|
|
final device = await servicio.obtenerDispositivoActual();
|
|
expect(device.id, 'builtin_speaker');
|
|
expect(device.tipo, TipoDispositivo.altavozInterno);
|
|
});
|
|
|
|
test('dispose completes without error', () async {
|
|
await expectLater(servicio.dispose(), completes);
|
|
});
|
|
|
|
test('no platform channel code is invoked (fake, not real)', () async {
|
|
// Verify that FakeServicioDispositivoAudio also produces no events
|
|
// when no emitirDispositivo is called — simulating toggle-off behavior.
|
|
final fake = FakeServicioDispositivoAudio();
|
|
final received = <DispositivoAudio>[];
|
|
final sub = fake.onDispositivoCambiado.listen(received.add);
|
|
await Future<void>.delayed(const Duration(milliseconds: 10));
|
|
await sub.cancel();
|
|
expect(received, isEmpty);
|
|
await fake.dispose();
|
|
});
|
|
});
|
|
}
|