diff --git a/Flutter User Facing API.dart b/Flutter User Facing API.dart index 579572ed..03f509f2 100644 --- a/Flutter User Facing API.dart +++ b/Flutter User Facing API.dart @@ -10,7 +10,8 @@ abstract class BluetoothLowEnergyManager { Future enableRadio(); Future disableRadio(); - Future cancelTransaction(String transactionId); + Future cancelTransaction(String const transactionId = "t1"; +); Future setLogLevel(LogLevel logLevel); Future logLevel(); diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 070de610..68ab0201 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -21,6 +21,7 @@ class Characteristic extends InternalCharacteristic { Service service; ManagerForCharacteristic _manager; + TransactionIdGenerator _transactionIdGenerator; /// The UUID of this characteristic. String uuid; @@ -40,10 +41,15 @@ class Characteristic extends InternalCharacteristic { /// True if this characteristic can be monitored via indications. bool isIndicatable; - Characteristic.fromJson(Map jsonObject, Service service, - ManagerForCharacteristic manager) - : super(jsonObject[_CharacteristicMetadata.id]) { + Characteristic.fromJson( + Map jsonObject, + Service service, + ManagerForCharacteristic manager, { + TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE, + }) : super(jsonObject[_CharacteristicMetadata.id]) { _manager = manager; + _transactionIdGenerator = transactionIdGenerator; this.service = service; uuid = jsonObject[_CharacteristicMetadata.uuid]; isReadable = jsonObject[_CharacteristicMetadata.isReadable]; @@ -62,7 +68,7 @@ class Characteristic extends InternalCharacteristic { _manager.readCharacteristicForIdentifier( service.peripheral, this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes to the value of this characteristic. @@ -80,7 +86,7 @@ class Characteristic extends InternalCharacteristic { this, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a [Stream] of notifications/indications emitted by this @@ -95,7 +101,7 @@ class Characteristic extends InternalCharacteristic { _manager.monitorCharacteristicForIdentifier( service.peripheral, this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s of this characteristic. @@ -110,7 +116,7 @@ class Characteristic extends InternalCharacteristic { _manager.readDescriptorForCharacteristic( this, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes the [value] of a [Descriptor] identified by [descriptorUuid]. @@ -123,7 +129,7 @@ class Characteristic extends InternalCharacteristic { this, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/descriptor.dart b/lib/descriptor.dart index 5e2e265a..d44d6065 100644 --- a/lib/descriptor.dart +++ b/lib/descriptor.dart @@ -8,15 +8,17 @@ abstract class _DescriptorMetadata { class Descriptor extends InternalDescriptor { ManagerForDescriptor _manager; + TransactionIdGenerator _transactionIdGenerator; Characteristic characteristic; String uuid; - Descriptor.fromJson( - Map jsonObject, - Characteristic characteristic, - ManagerForDescriptor manager, - ) : super(jsonObject[_DescriptorMetadata.id]) { + Descriptor.fromJson(Map jsonObject, + Characteristic characteristic, ManagerForDescriptor manager, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) + : super(jsonObject[_DescriptorMetadata.id]) { _manager = manager; + _transactionIdGenerator = transactionIdGenerator; this.characteristic = characteristic; uuid = jsonObject[_DescriptorMetadata.uuid]; } @@ -24,30 +26,28 @@ class Descriptor extends InternalDescriptor { Future read({String transactionId}) => _manager.readDescriptorForIdentifier( this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); Future write(Uint8List value, {String transactionId}) => _manager.writeDescriptorForIdentifier( this, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override bool operator ==(Object other) => identical(this, other) || - other is Descriptor && - runtimeType == other.runtimeType && - _manager == other._manager && - characteristic == other.characteristic && - uuid == other.uuid; + other is Descriptor && + runtimeType == other.runtimeType && + _manager == other._manager && + characteristic == other.characteristic && + uuid == other.uuid; @override int get hashCode => - _manager.hashCode ^ - characteristic.hashCode ^ - uuid.hashCode; + _manager.hashCode ^ characteristic.hashCode ^ uuid.hashCode; } class DescriptorWithValue extends Descriptor with WithValue { diff --git a/lib/peripheral.dart b/lib/peripheral.dart index c8298878..e785eb22 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -16,14 +16,18 @@ abstract class _PeripheralMetadata { class Peripheral { static const int NO_MTU_NEGOTIATION = 0; ManagerForPeripheral _manager; + TransactionIdGenerator _transactionIdGenerator; String name; String identifier; - Peripheral.fromJson(Map json, ManagerForPeripheral manager) + Peripheral.fromJson(Map json, ManagerForPeripheral manager, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) : _manager = manager, name = json[_PeripheralMetadata.name], - identifier = json[_PeripheralMetadata.identifier]; + identifier = json[_PeripheralMetadata.identifier], + _transactionIdGenerator = transactionIdGenerator; /// Connects to the peripheral. /// @@ -82,7 +86,7 @@ class Peripheral { /// Optional [transactionId] could be used to cancel operation. Future discoverAllServicesAndCharacteristics({String transactionId}) => _manager.discoverAllServicesAndCharacteristics( - this, transactionId ?? TransactionIdGenerator.getNextId()); + this, transactionId ?? _transactionIdGenerator.getNextId()); /// Returns a list of [Service]s of this peripheral. /// @@ -103,7 +107,7 @@ class Peripheral { /// /// Optional [transactionId] could be used to cancel operation. Future rssi({String transactionId}) => - _manager.rssi(this, transactionId ?? TransactionIdGenerator.getNextId()); + _manager.rssi(this, transactionId ?? _transactionIdGenerator.getNextId()); /// Requests new MTU value for current connection and return the negotiation /// result on Android, reads MTU on iOS. @@ -118,7 +122,7 @@ class Peripheral { /// If MTU has been requested in [connect()] this method will end with [BleError]. Future requestMtu(int mtu, {String transactionId}) => _manager.requestMtu( - this, mtu, transactionId ?? TransactionIdGenerator.getNextId()); + this, mtu, transactionId ?? _transactionIdGenerator.getNextId()); /// Reads value of [Characteristic] matching specified UUIDs. /// @@ -135,7 +139,7 @@ class Peripheral { this, serviceUuid, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes value of [Characteristic] matching specified UUIDs. @@ -157,7 +161,7 @@ class Peripheral { characteristicUuid, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s for [Characteristic] matching specified UUIDs. @@ -191,7 +195,7 @@ class Peripheral { serviceUuid, characteristicUuid, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes value of [Descriptor] matching specified UUIDs. @@ -214,7 +218,7 @@ class Peripheral { characteristicUuid, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a stream of notifications/indications from [Characteristic] @@ -236,7 +240,7 @@ class Peripheral { this, serviceUuid, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/service.dart b/lib/service.dart index 2b00d663..064a45a6 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -11,18 +11,20 @@ class Service extends InternalService { Peripheral peripheral; ManagerForService _manager; + TransactionIdGenerator _transactionIdGenerator; /// The UUID of this service. String uuid; - Service.fromJson( - Map jsonObject, - Peripheral peripheral, - ManagerForService managerForService, - ) : super(jsonObject[_ServiceMetadata.id]) { + Service.fromJson(Map jsonObject, Peripheral peripheral, + ManagerForService managerForService, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) + : super(jsonObject[_ServiceMetadata.id]) { this.peripheral = peripheral; uuid = jsonObject[_ServiceMetadata.uuid]; _manager = managerForService; + _transactionIdGenerator = transactionIdGenerator; } /// Returns a list of [Characteristic]s of this service. @@ -51,7 +53,7 @@ class Service extends InternalService { characteristicUuid, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId()); + transactionId ?? _transactionIdGenerator.getNextId()); /// Reads the value of a [Characteristic] identified by [characteristicUuid]. /// @@ -67,7 +69,7 @@ class Service extends InternalService { peripheral, this, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a [Stream] of values emitted by a [Characteristic] identified by @@ -86,7 +88,7 @@ class Service extends InternalService { peripheral, this, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s of a [Characteristic] identified by @@ -114,7 +116,7 @@ class Service extends InternalService { this, characteristicUuid, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes the [value] of a [Descriptor] identified by [descriptorUuid] @@ -132,7 +134,7 @@ class Service extends InternalService { characteristicUuid, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 69a92814..ee1173d8 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -39,7 +39,7 @@ abstract class ManagerForPeripheral { String transactionId, ); - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId, diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 5234e89c..6e30c396 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -8,10 +8,12 @@ class InternalBleManager ManagerForCharacteristic, ManagerForDescriptor { FlutterBleLib _bleLib; + TransactionIdGenerator _transactionIdGenerator; - InternalBleManager() { + InternalBleManager({TransactionIdGenerator transactionIdGenerator = TransactionIdGenerator.INSTANCE}) { _bleLib = FlutterBleLib(); _bleLib.registerManager(this); + _transactionIdGenerator = transactionIdGenerator; } @override @@ -36,11 +38,11 @@ class InternalBleManager @override Future enableRadio({String transactionId}) => - _bleLib.enableRadio(transactionId ?? TransactionIdGenerator.getNextId()); + _bleLib.enableRadio(transactionId ?? _transactionIdGenerator.getNextId()); @override Future disableRadio({String transactionId}) => - _bleLib.disableRadio(transactionId ?? TransactionIdGenerator.getNextId()); + _bleLib.disableRadio(transactionId ?? _transactionIdGenerator.getNextId()); @override Future bluetoothState() => _bleLib.state(); @@ -172,7 +174,7 @@ class InternalBleManager } @override - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId) { return _bleLib.requestMtu(peripheral, mtu, transactionId); } diff --git a/lib/src/util/_transaction_id_generator.dart b/lib/src/util/_transaction_id_generator.dart index b5270479..5b7be416 100644 --- a/lib/src/util/_transaction_id_generator.dart +++ b/lib/src/util/_transaction_id_generator.dart @@ -1,8 +1,13 @@ -abstract class TransactionIdGenerator { +class TransactionIdGenerator { static int _id = 0; + static const TransactionIdGenerator INSTANCE = const TransactionIdGenerator._internal(); - static String getNextId() { + String getNextId() { _id++; return _id.toString(); } + + const TransactionIdGenerator._internal(); } + + diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart new file mode 100644 index 00000000..e5ce2c73 --- /dev/null +++ b/test/peripheral_test.dart @@ -0,0 +1,465 @@ +import 'dart:typed_data'; + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; + +class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} + +class ServiceMock extends Mock implements Service {} + +class CharacteristicMock extends Mock implements Characteristic {} + +class TransactionIdGeneratorMock extends Mock + implements TransactionIdGenerator {} + +class CharacteristicWithValueMock extends Mock + implements CharacteristicWithValue {} + +class DescriptorMock extends Mock implements Descriptor {} + +class DescriptorWithValueMock extends Mock implements DescriptorWithValue {} + +void main() { + const PERIPHERAL_NAME = 'Peripheral name'; + const PERIPHERAL_ID = 'peripheral id'; + const SERVICE_UUID = 's1'; + const CHARACTERISTIC_UUID = 'c1'; + const TRANSACTION_ID = 't1'; + const DESCRIPTOR_UUID = "d1"; + + ManagerForPeripheralMock managerForPeripheral; + TransactionIdGeneratorMock transactionIdGeneratorMock; + Peripheral peripheral; + + setUp(() { + Map json = {'name': PERIPHERAL_NAME, 'id': PERIPHERAL_ID}; + managerForPeripheral = ManagerForPeripheralMock(); + transactionIdGeneratorMock = TransactionIdGeneratorMock(); + peripheral = Peripheral.fromJson(json, managerForPeripheral, + transactionIdGenerator: transactionIdGeneratorMock); + }); + + group("Connection", () { + test('should pass defaut values to manager', () { + //when + peripheral.connect(); + + //then + verify(managerForPeripheral.connectToPeripheral(PERIPHERAL_ID, + isAutoConnect: false, + requestMtu: 0, + refreshGatt: false, + timeout: null)); + }); + + test('should pass given values to manager', () { + //given + var isAutoConnect = true; + var mtu = 33; + var refreshGatt = true; + var timeout = Duration(days: 4); + + //when + peripheral.connect( + isAutoConnect: isAutoConnect, + requestMtu: mtu, + refreshGatt: refreshGatt, + timeout: timeout); + + //then + verify(managerForPeripheral.connectToPeripheral(PERIPHERAL_ID, + isAutoConnect: isAutoConnect, + requestMtu: mtu, + refreshGatt: refreshGatt, + timeout: timeout)); + }); + + test("should emit on every connection state change", () { + //given + var states = [ + PeripheralConnectionState.disconnected, + PeripheralConnectionState.connecting, + PeripheralConnectionState.connected + ]; + when(managerForPeripheral.observePeripheralConnectionState(any, any, any)) + .thenAnswer((_) => Stream.fromIterable(states)); + + //when + Stream connectionStateStream = + peripheral.observeConnectionState(); + + //then + expect(connectionStateStream, emitsInOrder(states)); + }); + + test("should pass arguments to manager for observing connection state", () { + //given + var emitCurrentValue = true; + var completeOnDisconnect = true; + + //when + peripheral.observeConnectionState( + emitCurrentValue: emitCurrentValue, + completeOnDisconnect: completeOnDisconnect); + + //then + verify(managerForPeripheral.observePeripheralConnectionState( + PERIPHERAL_ID, emitCurrentValue, completeOnDisconnect)); + }); + + test('should call disconnect on manager with valid arguments', () { + //when + peripheral.disconnectOrCancelConnection(); + + //then + verify(managerForPeripheral + .disconnectOrCancelPeripheralConnection(PERIPHERAL_ID)); + }); + + [true, false].forEach((isConnected) { + test( + "returns isConneted information based on $isConnected returned by manager", + () async { + //given + when(managerForPeripheral.isPeripheralConnected(any)) + .thenAnswer((_) => Future.value(isConnected)); + + //when + bool peripheralIsConnected = await peripheral.isConnected(); + + //then + expect(peripheralIsConnected, isConnected); + }); + }); + }); + + group("Discovery", () { + test("use given transactionId", () async { + //when + await peripheral.discoverAllServicesAndCharacteristics( + transactionId: TRANSACTION_ID); + + //then + verify(managerForPeripheral.discoverAllServicesAndCharacteristics( + any, TRANSACTION_ID)); + }); + + test("use generated transactionId", () async { + //given + var ids = ["1", "5"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.discoverAllServicesAndCharacteristics(); + await peripheral.discoverAllServicesAndCharacteristics(); + + //then + verify( + managerForPeripheral.discoverAllServicesAndCharacteristics(any, '1')); + verify( + managerForPeripheral.discoverAllServicesAndCharacteristics(any, '5')); + }); + }); + + group("Services", () { + test("should return services", () async { + //given + List services = [ServiceMock(), ServiceMock()]; + when(managerForPeripheral.services(any)) + .thenAnswer((_) => Future.value(services)); + + //when + List fetchedServices = await peripheral.services(); + + //then + expect(fetchedServices, services); + }); + }); + + group("Characteristics", () { + test("should return characteristic for given service", () async { + //given + List characteristics = [ + CharacteristicMock(), + CharacteristicMock() + ]; + when(managerForPeripheral.characteristics(any, SERVICE_UUID)) + .thenAnswer((_) => Future.value(characteristics)); + + //when + List fetchedCharacteristic = + await peripheral.characteristics(SERVICE_UUID); + + //then + expect(fetchedCharacteristic, characteristics); + }); + + test("should return value of characteristic", () async { + //given + CharacteristicWithValue mockedCharacteristicWithValue = + CharacteristicWithValueMock(); + when(managerForPeripheral.readCharacteristicForDevice( + any, any, any, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); + + //when + CharacteristicWithValue characteristicWithValue = await peripheral + .readCharacteristic('s1', 'c1', transactionId: TRANSACTION_ID); + + //then + expect(characteristicWithValue, mockedCharacteristicWithValue); + }); + + test("should use autogenerated transactionId during reading operation", + () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.readCharacteristic('s1', 'c1'); + await peripheral.readCharacteristic('s1', 'c1'); + + //then + verify( + managerForPeripheral.readCharacteristicForDevice(any, any, any, '4')); + verify( + managerForPeripheral.readCharacteristicForDevice(any, any, any, '9')); + }); + + test("should write value to characteristic", () async { + //given + CharacteristicWithValue mockedCharacteristicWithValue = + CharacteristicWithValueMock(); + Uint8List value = Uint8List.fromList([1, 4, 9]); + const withResponse = false; + + when(managerForPeripheral.writeCharacteristicForDevice(any, SERVICE_UUID, + CHARACTERISTIC_UUID, value, withResponse, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); + + //when + CharacteristicWithValue characteristicWithValue = + await peripheral.writeCharacteristic( + SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, + transactionId: TRANSACTION_ID); + + //then + expect(characteristicWithValue, mockedCharacteristicWithValue); + }); + + test("should use autogenerated transactionId during writing operation", + () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.writeCharacteristic( + 's1', 'c1', Uint8List.fromList([1]), false); + await peripheral.writeCharacteristic( + 's1', 'c1', Uint8List.fromList([1]), false); + + //then + verify(managerForPeripheral.writeCharacteristicForDevice( + any, any, any, any, any, '4')); + verify(managerForPeripheral.writeCharacteristicForDevice( + any, any, any, any, any, '9')); + }); + + test("should return values of monitored characteristic", () { + //given + var emittedValues = [ + CharacteristicWithValueMock(), + CharacteristicWithValueMock(), + CharacteristicWithValueMock() + ]; + when(managerForPeripheral.monitorCharacteristicForDevice( + any, SERVICE_UUID, CHARACTERISTIC_UUID, TRANSACTION_ID)) + .thenAnswer((_) => Stream.fromIterable(emittedValues)); + + //when + Stream characteristicsStream = + peripheral.monitorCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, + transactionId: TRANSACTION_ID); + + //then + expect(characteristicsStream, emitsInOrder(emittedValues)); + }); + + test("should use autogenerated transactionId for monitoring operation", () { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + peripheral.monitorCharacteristic('s1', 'c1'); + peripheral.monitorCharacteristic('s1', 'c1'); + + //then + verify(managerForPeripheral.monitorCharacteristicForDevice( + any, any, any, '4')); + verify(managerForPeripheral.monitorCharacteristicForDevice( + any, any, any, '9')); + }); + }); + + group("Rssi", () { + test("use given transactionId", () async { + //given + const rssi = -23; + when(managerForPeripheral.rssi(any, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(rssi)); + + //when + int obtainedRssi = await peripheral.rssi(transactionId: TRANSACTION_ID); + + //then + verify(managerForPeripheral.rssi(any, TRANSACTION_ID)); + expect(obtainedRssi, rssi); + }); + + test("use generated transactionId", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.rssi(); + await peripheral.rssi(); + + //then + verify(managerForPeripheral.rssi(any, '4')); + verify(managerForPeripheral.rssi(any, '9')); + }); + }); + + group("MTU", () { + test("returns negotiated MTU", () async { + //given + const requestedMtu = 100; + const negotiatedMtu = 50; + when(managerForPeripheral.requestMtu(any, requestedMtu, any)) + .thenAnswer((_) => Future.value(negotiatedMtu)); + + //when + int obtainedMtu = await peripheral.requestMtu(requestedMtu); + + //then + expect(negotiatedMtu, obtainedMtu); + }); + + test("use generated transactionId", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.requestMtu(23); + await peripheral.requestMtu(45); + + //then + verify(managerForPeripheral.requestMtu(any, any, '4')); + verify(managerForPeripheral.requestMtu(any, any, '9')); + }); + }); + + group("Descriptor", () { + test("should return desriptors of characteristic", () async { + //given + List descriptors = [DescriptorMock(), DescriptorMock()]; + when(managerForPeripheral.descriptorsForPeripheral( + any, SERVICE_UUID, CHARACTERISTIC_UUID)) + .thenAnswer((_) => Future.value(descriptors)); + + //when + List fetchedDescriptors = await peripheral + .descriptorsForCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID); + + //then + expect(fetchedDescriptors, descriptors); + }); + + test("should return Descriptor value", () async { + //given + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + when(managerForPeripheral.readDescriptorForPeripheral(any, SERVICE_UUID, + CHARACTERISTIC_UUID, DESCRIPTOR_UUID, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(descriptorWithValue)); + + //when + DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral + .readDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, + transactionId: TRANSACTION_ID); + + //then + expect(obtainedDescriptorWithValue, descriptorWithValue); + }); + + test("should use autogenerated transactionId during reading operation", + () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.readDescriptor('s1', 'c1', 'd1'); + await peripheral.readDescriptor('s1', 'c1', 'd1'); + + //then + verify(managerForPeripheral.readDescriptorForPeripheral( + any, any, any, any, '4')); + verify(managerForPeripheral.readDescriptorForPeripheral( + any, any, any, any, '9')); + }); + + test("should write value to descriptor", () async { + //given + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + Uint8List value = Uint8List.fromList([1, 4, 9]); + + when(managerForPeripheral.writeDescriptorForPeripheral(any, SERVICE_UUID, + CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(descriptorWithValue)); + + //when + DescriptorWithValue obtainedDescriptorWithValue = + await peripheral.writeDescriptor( + SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, + transactionId: TRANSACTION_ID); + + //then + expect(obtainedDescriptorWithValue, descriptorWithValue); + }); + + test("should use autogenerated transactionId during writing operation", + () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.writeDescriptor( + 's1', 'c1', 'd1', Uint8List.fromList([1])); + await peripheral.writeDescriptor( + 's1', 'c1', 'd1', Uint8List.fromList([1])); + + //then + verify(managerForPeripheral.writeDescriptorForPeripheral( + any, any, any, any, any, '4')); + verify(managerForPeripheral.writeDescriptorForPeripheral( + any, any, any, any, any, '9')); + }); + }); +} diff --git a/test/scan_result.dart b/test/scan_result_test.dart similarity index 100% rename from test/scan_result.dart rename to test/scan_result_test.dart diff --git a/test/src/util/transcation_id_generator_test.dart b/test/src/util/transcation_id_generator_test.dart index efa66cd9..ac98eab2 100644 --- a/test/src/util/transcation_id_generator_test.dart +++ b/test/src/util/transcation_id_generator_test.dart @@ -2,14 +2,21 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; void main() { + + TransactionIdGenerator transactionIdGenerator; + + setUp((){ + transactionIdGenerator = TransactionIdGenerator.INSTANCE; + }); + test("should be able to generate an id", () { - expect(TransactionIdGenerator.getNextId(), isNotNull); + expect(transactionIdGenerator.getNextId(), isNotNull); }); test("should always return unique values", () { List generatedIds = []; for (var i = 0; i < 1000; i++) { - var generatedId = TransactionIdGenerator.getNextId(); + var generatedId = transactionIdGenerator.getNextId(); expect(generatedIds, isNot(contains(generatedId))); generatedIds.add(generatedId); }