@stoprocent/noble 1.9.2-16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.editorconfig +11 -0
  2. package/.eslintrc.js +25 -0
  3. package/.github/FUNDING.yml +2 -0
  4. package/.github/workflows/fediverse-action.yml +16 -0
  5. package/.github/workflows/nodepackage.yml +77 -0
  6. package/.github/workflows/npm-publish.yml +26 -0
  7. package/.github/workflows/prebuild.yml +65 -0
  8. package/.nycrc.json +4 -0
  9. package/CHANGELOG.md +119 -0
  10. package/LICENSE +20 -0
  11. package/MAINTAINERS.md +1 -0
  12. package/README.md +833 -0
  13. package/assets/noble-logo.png +0 -0
  14. package/assets/noble-logo.svg +13 -0
  15. package/binding.gyp +19 -0
  16. package/codecov.yml +5 -0
  17. package/examples/advertisement-discovery.js +65 -0
  18. package/examples/cache-gatt-discovery.js +198 -0
  19. package/examples/cache-gatt-reconnect.js +164 -0
  20. package/examples/echo.js +104 -0
  21. package/examples/enter-exit.js +78 -0
  22. package/examples/peripheral-explorer-async.js +133 -0
  23. package/examples/peripheral-explorer.js +225 -0
  24. package/examples/pizza/README.md +15 -0
  25. package/examples/pizza/central.js +194 -0
  26. package/examples/pizza/pizza.js +60 -0
  27. package/index.d.ts +203 -0
  28. package/index.js +6 -0
  29. package/lib/characteristic.js +161 -0
  30. package/lib/characteristics.json +449 -0
  31. package/lib/descriptor.js +72 -0
  32. package/lib/descriptors.json +47 -0
  33. package/lib/distributed/bindings.js +326 -0
  34. package/lib/hci-socket/acl-stream.js +60 -0
  35. package/lib/hci-socket/bindings.js +788 -0
  36. package/lib/hci-socket/crypto.js +74 -0
  37. package/lib/hci-socket/gap.js +432 -0
  38. package/lib/hci-socket/gatt.js +809 -0
  39. package/lib/hci-socket/hci-status.json +71 -0
  40. package/lib/hci-socket/hci.js +1264 -0
  41. package/lib/hci-socket/signaling.js +76 -0
  42. package/lib/hci-socket/smp.js +140 -0
  43. package/lib/hci-uart/bindings.js +569 -0
  44. package/lib/hci-uart/hci-serial-parser.js +70 -0
  45. package/lib/hci-uart/hci.js +1336 -0
  46. package/lib/mac/binding.gyp +26 -0
  47. package/lib/mac/bindings.js +11 -0
  48. package/lib/mac/src/ble_manager.h +41 -0
  49. package/lib/mac/src/ble_manager.mm +435 -0
  50. package/lib/mac/src/callbacks.cc +222 -0
  51. package/lib/mac/src/callbacks.h +84 -0
  52. package/lib/mac/src/napi_objc.h +12 -0
  53. package/lib/mac/src/napi_objc.mm +50 -0
  54. package/lib/mac/src/noble_mac.h +34 -0
  55. package/lib/mac/src/noble_mac.mm +264 -0
  56. package/lib/mac/src/objc_cpp.h +26 -0
  57. package/lib/mac/src/objc_cpp.mm +126 -0
  58. package/lib/mac/src/peripheral.h +23 -0
  59. package/lib/manufacture.js +48 -0
  60. package/lib/noble.js +593 -0
  61. package/lib/peripheral.js +219 -0
  62. package/lib/resolve-bindings-web.js +9 -0
  63. package/lib/resolve-bindings.js +44 -0
  64. package/lib/service.js +72 -0
  65. package/lib/services.json +92 -0
  66. package/lib/webbluetooth/bindings.js +368 -0
  67. package/lib/websocket/bindings.js +321 -0
  68. package/lib/win/binding.gyp +23 -0
  69. package/lib/win/bindings.js +11 -0
  70. package/lib/win/src/ble_manager.cc +802 -0
  71. package/lib/win/src/ble_manager.h +77 -0
  72. package/lib/win/src/callbacks.cc +274 -0
  73. package/lib/win/src/callbacks.h +33 -0
  74. package/lib/win/src/napi_winrt.cc +76 -0
  75. package/lib/win/src/napi_winrt.h +12 -0
  76. package/lib/win/src/noble_winrt.cc +308 -0
  77. package/lib/win/src/noble_winrt.h +34 -0
  78. package/lib/win/src/notify_map.cc +62 -0
  79. package/lib/win/src/notify_map.h +50 -0
  80. package/lib/win/src/peripheral.h +23 -0
  81. package/lib/win/src/peripheral_winrt.cc +296 -0
  82. package/lib/win/src/peripheral_winrt.h +82 -0
  83. package/lib/win/src/radio_watcher.cc +125 -0
  84. package/lib/win/src/radio_watcher.h +61 -0
  85. package/lib/win/src/winrt_cpp.cc +82 -0
  86. package/lib/win/src/winrt_cpp.h +11 -0
  87. package/lib/win/src/winrt_guid.cc +12 -0
  88. package/lib/win/src/winrt_guid.h +13 -0
  89. package/misc/nrf52840dk.hex +6921 -0
  90. package/misc/prj.conf +43 -0
  91. package/package.json +96 -0
  92. package/test/lib/characteristic.test.js +791 -0
  93. package/test/lib/descriptor.test.js +249 -0
  94. package/test/lib/distributed/bindings.test.js +918 -0
  95. package/test/lib/hci-socket/acl-stream.test.js +188 -0
  96. package/test/lib/hci-socket/bindings.test.js +1756 -0
  97. package/test/lib/hci-socket/crypto.test.js +55 -0
  98. package/test/lib/hci-socket/gap.test.js +1089 -0
  99. package/test/lib/hci-socket/gatt.test.js +2392 -0
  100. package/test/lib/hci-socket/hci.test.js +1891 -0
  101. package/test/lib/hci-socket/signaling.test.js +94 -0
  102. package/test/lib/hci-socket/smp.test.js +268 -0
  103. package/test/lib/manufacture.test.js +77 -0
  104. package/test/lib/peripheral.test.js +623 -0
  105. package/test/lib/resolve-bindings.test.js +102 -0
  106. package/test/lib/service.test.js +195 -0
  107. package/test/lib/webbluetooth/bindings.test.js +190 -0
  108. package/test/lib/websocket/bindings.test.js +456 -0
  109. package/test/noble.test.js +1565 -0
  110. package/test.js +131 -0
  111. package/with-bindings.js +5 -0
  112. package/ws-slave.js +404 -0
@@ -0,0 +1,623 @@
1
+ const should = require('should');
2
+ const sinon = require('sinon');
3
+ const { fake, assert } = sinon;
4
+
5
+ const Peripheral = require('../../lib/peripheral');
6
+
7
+ describe('peripheral', () => {
8
+ let mockNoble = null;
9
+ const mockId = 'mock-id';
10
+ const mockAddress = 'mock-address';
11
+ const mockAddressType = 'mock-address-type';
12
+ const mockConnectable = 'mock-connectable';
13
+ const mockAdvertisement = 'mock-advertisement';
14
+ const mockRssi = 'mock-rssi';
15
+ const mockHandle = 'mock-handle';
16
+ const mockData = 'mock-data';
17
+
18
+ let peripheral = null;
19
+
20
+ beforeEach(() => {
21
+ mockNoble = {};
22
+ peripheral = new Peripheral(mockNoble, mockId, mockAddress, mockAddressType, mockConnectable, mockAdvertisement, mockRssi);
23
+ });
24
+
25
+ it('should have a id', () => {
26
+ should(peripheral.id).equal(mockId);
27
+ });
28
+
29
+ it('should have an address', () => {
30
+ should(peripheral.address).equal(mockAddress);
31
+ });
32
+
33
+ it('should have an address type', () => {
34
+ should(peripheral.addressType).equal(mockAddressType);
35
+ });
36
+
37
+ it('should have connectable', () => {
38
+ should(peripheral.connectable).equal(mockConnectable);
39
+ });
40
+
41
+ it('should have advertisement', () => {
42
+ should(peripheral.advertisement).equal(mockAdvertisement);
43
+ });
44
+
45
+ it('should have rssi', () => {
46
+ should(peripheral.rssi).equal(mockRssi);
47
+ });
48
+
49
+ describe('toString', () => {
50
+ it('should be id, address, address type, connectable, advertisement, rssi, state', () => {
51
+ should(peripheral.toString()).equal('{"id":"mock-id","address":"mock-address","addressType":"mock-address-type","connectable":"mock-connectable","advertisement":"mock-advertisement","rssi":"mock-rssi","mtu":null,"state":"disconnected"}');
52
+ });
53
+ });
54
+
55
+ describe('connect', () => {
56
+ beforeEach(() => {
57
+ mockNoble.connect = sinon.spy();
58
+ });
59
+
60
+ afterEach(() => {
61
+ sinon.reset();
62
+ });
63
+
64
+ it('should delegate to noble', () => {
65
+ peripheral.connect();
66
+
67
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, undefined);
68
+ });
69
+
70
+ it('should callback', () => {
71
+ const callback = sinon.spy();
72
+
73
+ peripheral.connect(callback);
74
+ peripheral.emit('connect', 'error');
75
+
76
+ assert.calledOnceWithExactly(callback, 'error');
77
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, undefined);
78
+ });
79
+
80
+ it('with options, no callback', () => {
81
+ const options = { options: true };
82
+
83
+ peripheral.connect(options);
84
+ peripheral.emit('connect');
85
+
86
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, options);
87
+ });
88
+
89
+ it('both options and callback', () => {
90
+ const options = { options: true };
91
+ const callback = fake.returns(null);
92
+
93
+ peripheral.connect(options, callback);
94
+ peripheral.emit('connect');
95
+
96
+ assert.calledOnceWithExactly(callback, undefined);
97
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, options);
98
+ });
99
+ });
100
+
101
+ describe('connectAsync', () => {
102
+ beforeEach(() => {
103
+ mockNoble.connect = sinon.spy();
104
+ });
105
+
106
+ afterEach(() => {
107
+ sinon.reset();
108
+ });
109
+
110
+ it('should resolve', async () => {
111
+ const promise = peripheral.connectAsync();
112
+ peripheral.emit('connect');
113
+
114
+ should(promise).resolvedWith(undefined);
115
+ });
116
+
117
+ it('should reject on error', async () => {
118
+ const promise = peripheral.connectAsync();
119
+ peripheral.emit('connect', new Error('error'));
120
+
121
+ should(promise).rejectedWith('error');
122
+ });
123
+
124
+ it('should delegate to noble', async () => {
125
+ const promise = peripheral.connectAsync();
126
+ peripheral.emit('connect');
127
+
128
+ should(promise).resolvedWith(undefined);
129
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, undefined);
130
+ });
131
+
132
+ it('with options', async () => {
133
+ const options = { options: true };
134
+
135
+ const promise = peripheral.connectAsync(options);
136
+ peripheral.emit('connect');
137
+
138
+ should(promise).resolvedWith(undefined);
139
+ assert.calledOnceWithExactly(mockNoble.connect, mockId, options);
140
+ });
141
+ });
142
+
143
+ describe('cancelConnect', () => {
144
+ beforeEach(() => {
145
+ mockNoble.connect = sinon.spy();
146
+ mockNoble.cancelConnect = sinon.spy();
147
+ });
148
+
149
+ afterEach(() => {
150
+ sinon.reset();
151
+ });
152
+
153
+ it('not connecting, should resolve', async () => {
154
+ await peripheral.cancelConnect();
155
+
156
+ assert.notCalled(mockNoble.cancelConnect);
157
+ });
158
+
159
+ it('connecting, should emit connect with error', async () => {
160
+ const options = { options: true };
161
+ const connectCallback = sinon.spy();
162
+
163
+ peripheral.connect(connectCallback);
164
+ peripheral.cancelConnect(options);
165
+
166
+ assert.calledOnceWithMatch(connectCallback, sinon.match({ message: 'connection canceled!' }));
167
+ assert.calledOnceWithExactly(mockNoble.cancelConnect, mockId, options);
168
+ });
169
+ });
170
+
171
+ describe('disconnect', () => {
172
+ beforeEach(() => {
173
+ mockNoble.disconnect = sinon.spy();
174
+ });
175
+
176
+ afterEach(() => {
177
+ sinon.reset();
178
+ });
179
+
180
+ it('should delegate to noble', () => {
181
+ peripheral.disconnect();
182
+ assert.calledOnceWithExactly(mockNoble.disconnect, mockId);
183
+ });
184
+
185
+ it('should callback', () => {
186
+ const callback = sinon.spy();
187
+
188
+ peripheral.disconnect(callback);
189
+ peripheral.emit('disconnect');
190
+
191
+ assert.calledOnceWithExactly(callback, null);
192
+ assert.calledOnceWithExactly(mockNoble.disconnect, mockId);
193
+ });
194
+ });
195
+
196
+ describe('disconnectAsync', () => {
197
+ beforeEach(() => {
198
+ mockNoble.disconnect = sinon.spy();
199
+ });
200
+
201
+ afterEach(() => {
202
+ sinon.reset();
203
+ });
204
+
205
+ it('should delegate to noble', () => {
206
+ const promise = peripheral.disconnectAsync();
207
+ peripheral.emit('disconnect');
208
+
209
+ should(promise).resolvedWith(undefined);
210
+ assert.calledOnceWithExactly(mockNoble.disconnect, mockId);
211
+ });
212
+ });
213
+
214
+ describe('updateRssi', () => {
215
+ beforeEach(() => {
216
+ mockNoble.updateRssi = sinon.spy();
217
+ });
218
+
219
+ afterEach(() => {
220
+ sinon.reset();
221
+ });
222
+
223
+ it('should delegate to noble', () => {
224
+ peripheral.updateRssi();
225
+ assert.calledOnceWithExactly(mockNoble.updateRssi, mockId);
226
+ });
227
+
228
+ it('should callback', () => {
229
+ const callback = sinon.spy();
230
+
231
+ peripheral.updateRssi(callback);
232
+ peripheral.emit('rssiUpdate', 'new-rssi');
233
+
234
+ assert.calledOnceWithExactly(callback, null, 'new-rssi');
235
+ assert.calledOnceWithExactly(mockNoble.updateRssi, mockId);
236
+ });
237
+ });
238
+
239
+ describe('updateRssiAsync', () => {
240
+ beforeEach(() => {
241
+ mockNoble.updateRssi = sinon.spy();
242
+ });
243
+
244
+ afterEach(() => {
245
+ sinon.reset();
246
+ });
247
+
248
+ it('should resolve with rssi', async () => {
249
+ const promise = peripheral.updateRssiAsync();
250
+ peripheral.emit('rssiUpdate', 'new-rssi');
251
+ should(promise).resolvedWith('new-rssi');
252
+ });
253
+ });
254
+
255
+ describe('discoverServices', () => {
256
+ beforeEach(() => {
257
+ mockNoble.discoverServices = sinon.spy();
258
+ });
259
+
260
+ afterEach(() => {
261
+ sinon.reset();
262
+ });
263
+
264
+ it('should delegate to noble', () => {
265
+ peripheral.discoverServices();
266
+ assert.calledOnceWithExactly(mockNoble.discoverServices, mockId, undefined);
267
+ });
268
+
269
+ it('should delegate to noble, service uuids', () => {
270
+ const mockServiceUuids = [];
271
+ peripheral.discoverServices(mockServiceUuids);
272
+ assert.calledOnceWithExactly(mockNoble.discoverServices, mockId, mockServiceUuids);
273
+ });
274
+
275
+ it('should callback', () => {
276
+ const callback = sinon.spy();
277
+ peripheral.discoverServices('uuids', callback);
278
+ peripheral.emit('servicesDiscover', 'services');
279
+
280
+ assert.alwaysCalledWithExactly(callback, null, 'services');
281
+ assert.calledOnceWithExactly(mockNoble.discoverServices, mockId, 'uuids');
282
+ });
283
+ });
284
+
285
+ describe('discoverServicesAsync', () => {
286
+ beforeEach(() => {
287
+ mockNoble.discoverServices = sinon.spy();
288
+ });
289
+
290
+ afterEach(() => {
291
+ sinon.reset();
292
+ });
293
+
294
+ it('should resolve with services', async () => {
295
+ const mockServices = 'discoveredServices';
296
+
297
+ const promise = peripheral.discoverServicesAsync('uuids');
298
+ peripheral.emit('servicesDiscover', mockServices);
299
+
300
+ should(promise).resolvedWith(mockServices);
301
+ assert.calledOnceWithExactly(mockNoble.discoverServices, mockId, 'uuids');
302
+ });
303
+ });
304
+
305
+ describe('discoverSomeServicesAndCharacteristics', () => {
306
+ const mockServiceUuids = [];
307
+ const mockCharacteristicUuids = [];
308
+ let mockServices = null;
309
+
310
+ beforeEach(() => {
311
+ peripheral.discoverServices = sinon.stub();
312
+
313
+ mockServices = [
314
+ {
315
+ uuid: '1',
316
+ discoverCharacteristics: sinon.spy()
317
+ },
318
+ {
319
+ uuid: '2',
320
+ discoverCharacteristics: sinon.spy()
321
+ }
322
+ ];
323
+ });
324
+
325
+ afterEach(() => {
326
+ sinon.reset();
327
+ });
328
+
329
+ it('should call discoverServices', () => {
330
+ peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids);
331
+ peripheral.discoverServices.callArg(1, null, mockServices);
332
+
333
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
334
+ });
335
+
336
+ it('should call discoverCharacteristics on each service discovered', () => {
337
+ peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids);
338
+ peripheral.discoverServices.callArg(1, null, mockServices);
339
+
340
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
341
+ assert.calledOnceWithMatch(mockServices[0].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
342
+ assert.calledOnceWithMatch(mockServices[1].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
343
+ });
344
+
345
+ it('should callback', () => {
346
+ const callback = sinon.spy();
347
+
348
+ peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids, callback);
349
+ peripheral.discoverServices.callArg(1, null, mockServices);
350
+
351
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
352
+ assert.calledOnceWithMatch(mockServices[0].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
353
+ assert.calledOnceWithMatch(mockServices[1].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
354
+
355
+ mockServices[0].discoverCharacteristics.callArg(1, null, mockCharacteristicUuids);
356
+ mockServices[1].discoverCharacteristics.callArg(1, null, mockCharacteristicUuids);
357
+
358
+ assert.calledOnceWithExactly(callback, null, mockServices, mockCharacteristicUuids);
359
+ });
360
+
361
+ it('should callback with the services and characteristics discovered', () => {
362
+ const callback = sinon.spy();
363
+
364
+ peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids, callback);
365
+ peripheral.discoverServices.callArg(1, null, mockServices);
366
+
367
+ const mockCharacteristic1 = { uuid: '1' };
368
+ const mockCharacteristic2 = { uuid: '2' };
369
+ const mockCharacteristic3 = { uuid: '3' };
370
+
371
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
372
+ assert.calledOnceWithMatch(mockServices[0].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
373
+ assert.calledOnceWithMatch(mockServices[1].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
374
+
375
+ mockServices[0].discoverCharacteristics.callArg(1, null, [mockCharacteristic1]);
376
+ mockServices[1].discoverCharacteristics.callArg(1, null, [mockCharacteristic2, mockCharacteristic3]);
377
+
378
+ assert.calledOnceWithExactly(callback, null, mockServices, [mockCharacteristic1, mockCharacteristic2, mockCharacteristic3]);
379
+ });
380
+ });
381
+
382
+ describe('discoverSomeServicesAndCharacteristicsAsync', () => {
383
+ const mockServiceUuids = [];
384
+ const mockCharacteristicUuids = [];
385
+ let mockServices = null;
386
+
387
+ beforeEach(() => {
388
+ peripheral.discoverServices = sinon.stub();
389
+
390
+ mockServices = [
391
+ {
392
+ uuid: '1',
393
+ discoverCharacteristics: sinon.spy()
394
+ },
395
+ {
396
+ uuid: '2',
397
+ discoverCharacteristics: sinon.spy()
398
+ }
399
+ ];
400
+ });
401
+
402
+ afterEach(() => {
403
+ sinon.reset();
404
+ });
405
+
406
+ it('should call discoverServices', async () => {
407
+ const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids);
408
+ peripheral.discoverServices.callArg(1, null, mockServices);
409
+
410
+ should(promise).resolvedWith([]);
411
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
412
+ });
413
+
414
+ it('should call discoverCharacteristics on each service discovered', () => {
415
+ const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids, mockCharacteristicUuids);
416
+ peripheral.discoverServices.callArg(1, null, mockServices);
417
+
418
+ should(promise).resolvedWith([]);
419
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
420
+ assert.calledOnceWithMatch(mockServices[0].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
421
+ assert.calledOnceWithMatch(mockServices[1].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
422
+ });
423
+
424
+ it('should reject on error', async () => {
425
+ const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids, mockCharacteristicUuids);
426
+ peripheral.discoverServices.callArg(1, 'error', null);
427
+
428
+ should(promise).rejectedWith('error');
429
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
430
+ assert.notCalled(mockServices[0].discoverCharacteristics);
431
+ });
432
+
433
+ it('should resolve with the services and characteristics discovered', async () => {
434
+ const callback = sinon.spy();
435
+
436
+ const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids, mockCharacteristicUuids, callback);
437
+ peripheral.discoverServices.callArg(1, null, mockServices);
438
+
439
+ const mockCharacteristic1 = { uuid: '1' };
440
+ const mockCharacteristic2 = { uuid: '2' };
441
+ const mockCharacteristic3 = { uuid: '3' };
442
+
443
+ assert.calledOnceWithMatch(peripheral.discoverServices, mockServiceUuids, sinon.match.func);
444
+ assert.calledOnceWithMatch(mockServices[0].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
445
+ assert.calledOnceWithMatch(mockServices[1].discoverCharacteristics, mockCharacteristicUuids, sinon.match.func);
446
+
447
+ mockServices[0].discoverCharacteristics.callArg(1, null, [mockCharacteristic1]);
448
+ mockServices[1].discoverCharacteristics.callArg(1, null, [mockCharacteristic2, mockCharacteristic3]);
449
+
450
+ should(promise).resolvedWith([mockCharacteristic1, mockCharacteristic2, mockCharacteristic3]);
451
+ });
452
+ });
453
+
454
+ describe('discoverAllServicesAndCharacteristics', () => {
455
+ beforeEach(() => {
456
+ peripheral.discoverSomeServicesAndCharacteristics = sinon.stub();
457
+ });
458
+
459
+ afterEach(() => {
460
+ sinon.reset();
461
+ });
462
+
463
+ it('should call discoverSomeServicesAndCharacteristics', () => {
464
+ const callback = sinon.spy();
465
+ peripheral.discoverAllServicesAndCharacteristics(callback);
466
+ assert.calledOnceWithExactly(peripheral.discoverSomeServicesAndCharacteristics, [], [], callback);
467
+ });
468
+ });
469
+
470
+ describe('discoverAllServicesAndCharacteristicsAsync', () => {
471
+ beforeEach(() => {
472
+ peripheral.discoverSomeServicesAndCharacteristics = sinon.stub();
473
+ });
474
+
475
+ afterEach(() => {
476
+ sinon.reset();
477
+ });
478
+
479
+ it('should call discoverSomeServicesAndCharacteristics', async () => {
480
+ const promise = peripheral.discoverAllServicesAndCharacteristicsAsync();
481
+ peripheral.discoverSomeServicesAndCharacteristics.callArg(2, null);
482
+ should(promise).resolvedWith([]);
483
+ });
484
+ });
485
+
486
+ describe('readHandle', () => {
487
+ beforeEach(() => {
488
+ mockNoble.readHandle = sinon.spy();
489
+ });
490
+
491
+ afterEach(() => {
492
+ sinon.reset();
493
+ });
494
+
495
+ it('should delegate to noble', () => {
496
+ peripheral.readHandle(mockHandle);
497
+ assert.calledOnceWithExactly(mockNoble.readHandle, mockId, mockHandle);
498
+ });
499
+
500
+ it('should callback', () => {
501
+ const callback = sinon.spy();
502
+
503
+ peripheral.readHandle(mockHandle, callback);
504
+ peripheral.emit(`handleRead${mockHandle}`);
505
+
506
+ assert.calledOnceWithExactly(callback, null, undefined);
507
+ assert.calledOnceWithExactly(mockNoble.readHandle, mockId, mockHandle);
508
+ });
509
+
510
+ it('should callback with data', () => {
511
+ const callback = sinon.spy();
512
+
513
+ peripheral.readHandle(mockHandle, callback);
514
+ peripheral.emit(`handleRead${mockHandle}`, mockData);
515
+
516
+ assert.calledOnceWithExactly(callback, null, mockData);
517
+ assert.calledOnceWithExactly(mockNoble.readHandle, mockId, mockHandle);
518
+ });
519
+ });
520
+
521
+ describe('readHandleAsync', () => {
522
+ beforeEach(() => {
523
+ mockNoble.readHandle = sinon.spy();
524
+ });
525
+
526
+ afterEach(() => {
527
+ sinon.reset();
528
+ });
529
+
530
+ it('should delegate to noble', async () => {
531
+ const promise = peripheral.readHandleAsync(mockHandle);
532
+ peripheral.emit(`handleRead${mockHandle}`);
533
+
534
+ should(promise).resolvedWith(undefined);
535
+ assert.calledOnceWithExactly(mockNoble.readHandle, mockId, mockHandle);
536
+ });
537
+
538
+ it('should resolve with data', async () => {
539
+ const promise = peripheral.readHandleAsync(mockHandle);
540
+ peripheral.emit(`handleRead${mockHandle}`, mockData);
541
+
542
+ should(promise).resolvedWith(mockData);
543
+ assert.calledOnceWithExactly(mockNoble.readHandle, mockId, mockHandle);
544
+ });
545
+ });
546
+
547
+ describe('writeHandle', () => {
548
+ beforeEach(() => {
549
+ mockNoble.writeHandle = sinon.spy();
550
+ });
551
+
552
+ afterEach(() => {
553
+ sinon.reset();
554
+ });
555
+
556
+ it('should only accept data as a buffer', () => {
557
+ const mockData = {};
558
+ should(() => peripheral.writeHandle(mockHandle, mockData)).throw('data must be a Buffer');
559
+ assert.notCalled(mockNoble.writeHandle);
560
+ });
561
+
562
+ it('should delegate to noble, withoutResponse false', () => {
563
+ const mockData = Buffer.alloc(0);
564
+ peripheral.writeHandle(mockHandle, mockData, false);
565
+
566
+ assert.alwaysCalledWithExactly(mockNoble.writeHandle, mockId, mockHandle, mockData, false);
567
+ });
568
+
569
+ it('should delegate to noble, withoutResponse true', () => {
570
+ const mockData = Buffer.alloc(0);
571
+ peripheral.writeHandle(mockHandle, mockData, true);
572
+
573
+ assert.alwaysCalledWithExactly(mockNoble.writeHandle, mockId, mockHandle, mockData, true);
574
+ });
575
+
576
+ it('should callback', () => {
577
+ const mockData = Buffer.alloc(0);
578
+ const callback = sinon.spy();
579
+
580
+ peripheral.writeHandle(mockHandle, mockData, false, callback);
581
+ peripheral.emit(`handleWrite${mockHandle}`);
582
+
583
+ assert.calledOnceWithExactly(callback, null);
584
+ assert.alwaysCalledWithExactly(mockNoble.writeHandle, mockId, mockHandle, mockData, false);
585
+ });
586
+ });
587
+
588
+ describe('writeHandleAsync', () => {
589
+ beforeEach(() => {
590
+ mockNoble.writeHandle = sinon.spy();
591
+ });
592
+
593
+ afterEach(() => {
594
+ sinon.reset();
595
+ });
596
+
597
+ it('should only accept data as a buffer', async () => {
598
+ const mockData = {};
599
+ const promise = peripheral.writeHandleAsync(mockHandle, mockData);
600
+
601
+ should(promise).rejectedWith('data must be a Buffer');
602
+ assert.notCalled(mockNoble.writeHandle);
603
+ });
604
+
605
+ it('should delegate to noble, withoutResponse false', async () => {
606
+ const mockData = Buffer.alloc(0);
607
+ const promise = peripheral.writeHandleAsync(mockHandle, mockData, false);
608
+ peripheral.emit(`handleWrite${mockHandle}`);
609
+
610
+ should(promise).resolvedWith(null);
611
+ assert.alwaysCalledWithExactly(mockNoble.writeHandle, mockId, mockHandle, mockData, false);
612
+ });
613
+
614
+ it('should delegate to noble, withoutResponse true', async () => {
615
+ const mockData = Buffer.alloc(0);
616
+ const promise = peripheral.writeHandleAsync(mockHandle, mockData, true);
617
+ peripheral.emit(`handleWrite${mockHandle}`);
618
+
619
+ should(promise).resolvedWith(null);
620
+ assert.alwaysCalledWithExactly(mockNoble.writeHandle, mockId, mockHandle, mockData, true);
621
+ });
622
+ });
623
+ });