import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:universal_ble/universal_ble.dart'; import 'universal_ble_test_mock.dart'; String serviceId = "180a"; String characteristicId = "202a"; String mockDeviceId = "mock_id"; BleCharacteristic mockBleCharacteristic = BleCharacteristic.withMetaData( deviceId: mockDeviceId, serviceId: serviceId, uuid: characteristicId, properties: CharacteristicProperty.values, descriptors: [], ); BleService mockBleService = BleService(serviceId, [mockBleCharacteristic]); void main() { late UniversalBlePlatform platform; setUp(() { platform = _UniversalBleMock(); UniversalBle.setInstance(platform); }); group('BleCharacteristic Tests', () { test("DiscoverServices test", () async { debugPrint("Discovering services"); List services = await UniversalBle.discoverServices(mockDeviceId); expect(services.length, 1); BleService service = services.first; expect(BleUuidParser.compareStrings(service.uuid, serviceId), true); expect(service.characteristics.length, 1); BleCharacteristic characteristic = service.characteristics.first; expect( BleUuidParser.compareStrings(characteristic.uuid, characteristicId), true, ); expect(characteristic.metaData?.deviceId, mockDeviceId); expect( BleUuidParser.compareStrings( characteristic.metaData!.serviceId, serviceId, ), true, ); }); test("Subscription Test", () async { BleCharacteristic characteristic = mockBleCharacteristic; debugPrint("Subscribing to char"); await characteristic.notifications.subscribe(); bool gotEvent = false; var subscription = characteristic.notifications.listen((data) { debugPrint("Received CharValue: $data"); gotEvent = true; }); await Future.delayed(Duration(seconds: 1)); await characteristic.notifications.unsubscribe(); debugPrint("Unsubscribed from char"); subscription.cancel(); expect(gotEvent, true); }); }); test("Write/Read Value Test", () async { BleCharacteristic characteristic = mockBleCharacteristic; Uint8List charValue = Uint8List.fromList([0x01, 0x02]); await characteristic.write(charValue); debugPrint("Write Succeed"); var readResult = await characteristic.read(); debugPrint("Read Succeed"); expect(readResult, charValue); }); } class _UniversalBleMock extends UniversalBlePlatformMock { Timer? notifierTimer; Uint8List? charValue; @override Future> discoverServices( String deviceId, bool withDescriptors) async { return [mockBleService]; } @override Future setNotifiable(String deviceId, String service, String characteristic, BleInputProperty bleInputProperty) async { if (bleInputProperty == BleInputProperty.disabled) { notifierTimer?.cancel(); notifierTimer = null; return; } notifierTimer ??= Timer.periodic(Duration(milliseconds: 500), (timer) { updateCharacteristicValue( deviceId, characteristic, Uint8List.fromList([1, 2, 3]), DateTime.now().millisecondsSinceEpoch, ); }); } @override Future writeValue( String deviceId, String service, String characteristic, Uint8List value, BleOutputProperty bleOutputProperty) async { charValue = value; } @override Future readValue( String deviceId, String service, String characteristic, {Duration? timeout}) async { return charValue ?? Uint8List(0); } @override Future requestPermissions({bool withAndroidFineLocation = false}) { throw UnimplementedError(); } @override Future readRssi(String deviceId) async { return -50; // Mock RSSI value } }