@stoprocent/noble 1.19.1 → 2.0.1

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 (97) hide show
  1. package/README.md +393 -650
  2. package/examples/advertisement-discovery.js +57 -48
  3. package/examples/connect-address.js +59 -34
  4. package/examples/echo.js +59 -69
  5. package/examples/enter-exit.js +55 -49
  6. package/examples/multiple-bindings.js +53 -0
  7. package/examples/peripheral-explorer-async.js +39 -21
  8. package/examples/peripheral-explorer.ts +52 -0
  9. package/index.d.ts +249 -209
  10. package/index.js +4 -1
  11. package/jest.config.js +4 -0
  12. package/lib/characteristic.js +153 -127
  13. package/lib/{win/src/callbacks.h → common/include/Emit.h} +17 -14
  14. package/lib/common/include/Peripheral.h +31 -0
  15. package/lib/common/include/ThreadSafeCallback.h +95 -0
  16. package/lib/{win/src/callbacks.cc → common/src/Emit.cc} +111 -68
  17. package/lib/descriptor.js +57 -54
  18. package/lib/hci-socket/acl-stream.js +2 -4
  19. package/lib/hci-socket/bindings.js +96 -73
  20. package/lib/hci-socket/gap.js +2 -3
  21. package/lib/hci-socket/gatt.js +2 -5
  22. package/lib/hci-socket/hci.js +19 -7
  23. package/lib/hci-socket/signaling.js +2 -3
  24. package/lib/hci-socket/smp.js +2 -3
  25. package/lib/hci-socket/vs.js +1 -0
  26. package/lib/mac/binding.gyp +5 -7
  27. package/lib/mac/bindings.js +1 -3
  28. package/lib/mac/src/ble_manager.h +1 -8
  29. package/lib/mac/src/ble_manager.mm +87 -44
  30. package/lib/mac/src/napi_objc.h +1 -0
  31. package/lib/mac/src/napi_objc.mm +0 -6
  32. package/lib/mac/src/noble_mac.h +5 -3
  33. package/lib/mac/src/noble_mac.mm +99 -57
  34. package/lib/mac/src/objc_cpp.h +3 -2
  35. package/lib/mac/src/objc_cpp.mm +0 -6
  36. package/lib/noble.js +583 -488
  37. package/lib/peripheral.js +171 -174
  38. package/lib/resolve-bindings.js +37 -30
  39. package/lib/service.js +58 -55
  40. package/lib/win/binding.gyp +4 -11
  41. package/lib/win/bindings.js +1 -3
  42. package/lib/win/src/ble_manager.cc +291 -166
  43. package/lib/win/src/ble_manager.h +11 -13
  44. package/lib/win/src/napi_winrt.cc +1 -7
  45. package/lib/win/src/napi_winrt.h +1 -1
  46. package/lib/win/src/noble_winrt.cc +88 -61
  47. package/lib/win/src/noble_winrt.h +5 -3
  48. package/lib/win/src/notify_map.cc +0 -7
  49. package/lib/win/src/notify_map.h +1 -8
  50. package/lib/win/src/peripheral_winrt.cc +29 -11
  51. package/lib/win/src/peripheral_winrt.h +1 -1
  52. package/lib/win/src/radio_watcher.cc +79 -69
  53. package/lib/win/src/radio_watcher.h +30 -11
  54. package/lib/win/src/winrt_cpp.cc +1 -1
  55. package/lib/win/src/winrt_cpp.h +3 -0
  56. package/package.json +14 -17
  57. package/prebuilds/darwin-x64+arm64/@stoprocent+noble.node +0 -0
  58. package/prebuilds/win32-ia32/@stoprocent+noble.node +0 -0
  59. package/prebuilds/win32-x64/@stoprocent+noble.node +0 -0
  60. package/test/lib/characteristic.test.js +202 -322
  61. package/test/lib/descriptor.test.js +62 -95
  62. package/test/lib/hci-socket/acl-stream.test.js +112 -108
  63. package/test/lib/hci-socket/bindings.test.js +576 -365
  64. package/test/lib/hci-socket/hci.test.js +442 -473
  65. package/test/lib/hci-socket/signaling.test.js +45 -48
  66. package/test/lib/hci-socket/smp.test.js +144 -142
  67. package/test/lib/hci-socket/vs.test.js +193 -18
  68. package/test/lib/peripheral.test.js +492 -322
  69. package/test/lib/resolve-bindings.test.js +207 -82
  70. package/test/lib/service.test.js +79 -88
  71. package/test/noble.test.js +426 -1088
  72. package/.editorconfig +0 -11
  73. package/.nycrc.json +0 -4
  74. package/codecov.yml +0 -5
  75. package/examples/cache-gatt-discovery.js +0 -198
  76. package/examples/cache-gatt-reconnect.js +0 -164
  77. package/examples/ext-advertisement-discovery.js +0 -65
  78. package/examples/peripheral-explorer.js +0 -225
  79. package/examples/pizza/central.js +0 -194
  80. package/examples/pizza/pizza.js +0 -60
  81. package/examples/test/test.custom.js +0 -131
  82. package/examples/uart-bind-params.js +0 -28
  83. package/lib/distributed/bindings.js +0 -326
  84. package/lib/mac/src/callbacks.cc +0 -222
  85. package/lib/mac/src/callbacks.h +0 -84
  86. package/lib/mac/src/peripheral.h +0 -23
  87. package/lib/resolve-bindings-web.js +0 -9
  88. package/lib/webbluetooth/bindings.js +0 -368
  89. package/lib/websocket/bindings.js +0 -321
  90. package/lib/win/src/peripheral.h +0 -23
  91. package/test/lib/distributed/bindings.test.js +0 -918
  92. package/test/lib/webbluetooth/bindings.test.js +0 -190
  93. package/test/lib/websocket/bindings.test.js +0 -456
  94. package/test/mocha.setup.js +0 -0
  95. package/with-bindings.js +0 -5
  96. package/with-custom-binding.js +0 -6
  97. package/ws-slave.js +0 -404
@@ -1,8 +1,3 @@
1
- const should = require('should');
2
- const sinon = require('sinon');
3
-
4
- const { assert } = sinon;
5
-
6
1
  const Noble = require('../lib/noble');
7
2
  const Peripheral = require('../lib/peripheral');
8
3
  const Service = require('../lib/service');
@@ -18,73 +13,43 @@ describe('noble', () => {
18
13
 
19
14
  beforeEach(() => {
20
15
  mockBindings = {
21
- init: () => {},
22
- on: () => {}
16
+ start: jest.fn(),
17
+ on: jest.fn(),
18
+ startScanning: jest.fn(),
19
+ stopScanning: jest.fn(),
20
+ connect: jest.fn(),
21
+ disconnect: jest.fn(),
22
+ updateRssi: jest.fn(),
23
+ discoverServices: jest.fn(),
24
+ discoverIncludedServices: jest.fn(),
25
+ discoverCharacteristics: jest.fn(),
26
+ read: jest.fn(),
27
+ write: jest.fn(),
28
+ broadcast: jest.fn(),
29
+ notify: jest.fn(),
30
+ discoverDescriptors: jest.fn(),
31
+ readValue: jest.fn(),
32
+ writeValue: jest.fn(),
33
+ readHandle: jest.fn(),
34
+ writeHandle: jest.fn(),
35
+ reset: jest.fn(),
36
+ setScanParameters: jest.fn(),
37
+ cancelConnect: jest.fn(),
38
+ addressToId: jest.fn()
23
39
  };
24
40
 
25
41
  noble = new Noble(mockBindings);
42
+ noble.removeAllListeners('warning');
43
+ noble._peripherals = new Map();
26
44
  });
27
45
 
28
- describe('startScanning', () => {
29
- beforeEach(() => {
30
- mockBindings.startScanning = sinon.spy();
31
- });
32
-
33
- afterEach(() => {
34
- sinon.reset();
35
- });
36
-
37
- it('should emit warning due to serviceUuids', () => {
38
- const callback = sinon.spy();
39
- const eventCallback = sinon.spy();
40
- const expectedAllowDuplicates = true;
41
- noble.on('warning', eventCallback);
42
-
43
- noble.startScanning(callback, expectedAllowDuplicates);
44
- noble.emit('stateChange', 'poweredOn');
45
- // Check for single callback
46
- noble.emit('stateChange', 'poweredOn');
47
- noble.emit('scanStart');
48
- // Check for single callback
49
- noble.emit('scanStart');
50
-
51
- assert.calledOnceWithExactly(
52
- mockBindings.startScanning,
53
- callback,
54
- expectedAllowDuplicates
55
- );
56
- assert.calledOnceWithExactly(
57
- eventCallback,
58
- 'calling startScanning(callback) is deprecated'
59
- );
60
- });
61
-
62
- it('should emit warning due to allowDuplicates', () => {
63
- const callback = sinon.spy();
64
- const eventCallback = sinon.spy();
65
- const expectedServiceUuids = [1, 2, 3];
66
- noble.on('warning', eventCallback);
67
-
68
- noble.startScanning(expectedServiceUuids, callback);
69
- noble.emit('stateChange', 'poweredOn');
70
- // Check for single callback
71
- noble.emit('stateChange', 'poweredOn');
72
- noble.emit('scanStart');
73
- // Check for single callback
74
- noble.emit('scanStart');
75
-
76
- assert.calledOnceWithExactly(
77
- mockBindings.startScanning,
78
- expectedServiceUuids,
79
- callback
80
- );
81
- assert.calledOnceWithExactly(
82
- eventCallback,
83
- 'calling startScanning(serviceUuids, callback) is deprecated'
84
- );
85
- });
46
+ afterEach(() => {
47
+ jest.clearAllMocks();
48
+ });
86
49
 
87
- it('should delegate to binding', () => {
50
+ describe('startScanning', () => {
51
+
52
+ test('should delegate to binding', () => {
88
53
  const expectedServiceUuids = [1, 2, 3];
89
54
  const expectedAllowDuplicates = true;
90
55
 
@@ -96,17 +61,17 @@ describe('noble', () => {
96
61
  // Check for single callback
97
62
  noble.emit('scanStart');
98
63
 
99
- assert.calledOnceWithExactly(
100
- mockBindings.startScanning,
64
+ expect(mockBindings.startScanning).toHaveBeenCalledWith(
101
65
  expectedServiceUuids,
102
66
  expectedAllowDuplicates
103
67
  );
68
+ expect(mockBindings.startScanning).toHaveBeenCalledTimes(1);
104
69
  });
105
70
 
106
- it('should delegate to callback', async () => {
71
+ test('should delegate to callback', async () => {
107
72
  const expectedServiceUuids = [1, 2, 3];
108
73
  const expectedAllowDuplicates = true;
109
- const callback = sinon.spy();
74
+ const callback = jest.fn();
110
75
 
111
76
  noble.startScanning(
112
77
  expectedServiceUuids,
@@ -120,31 +85,32 @@ describe('noble', () => {
120
85
  // Check for single callback
121
86
  noble.emit('scanStart');
122
87
 
123
- assert.calledOnceWithExactly(callback, null, undefined);
124
- assert.calledOnceWithExactly(
125
- mockBindings.startScanning,
88
+ expect(callback).toHaveBeenCalledWith(null, undefined);
89
+ expect(callback).toHaveBeenCalledTimes(1);
90
+ expect(mockBindings.startScanning).toHaveBeenCalledWith(
126
91
  expectedServiceUuids,
127
92
  expectedAllowDuplicates
128
93
  );
94
+ expect(mockBindings.startScanning).toHaveBeenCalledTimes(1);
129
95
  });
130
96
 
131
- it('should delegate to callback, already initialized', async () => {
132
- noble.initialized = true;
97
+ test('should delegate to callback, already initialized', async () => {
98
+ noble._initialized = true;
133
99
  noble._state = 'poweredOn';
134
100
 
135
101
  noble.startScanning();
136
102
 
137
- assert.calledOnceWithExactly(
138
- mockBindings.startScanning,
103
+ expect(mockBindings.startScanning).toHaveBeenCalledWith(
139
104
  undefined,
140
105
  undefined
141
106
  );
107
+ expect(mockBindings.startScanning).toHaveBeenCalledTimes(1);
142
108
  });
143
109
 
144
- it('should delegate to callback with filter', async () => {
110
+ test('should delegate to callback with filter', async () => {
145
111
  const expectedServiceUuids = [1, 2, 3];
146
112
  const expectedAllowDuplicates = true;
147
- const callback = sinon.spy();
113
+ const callback = jest.fn();
148
114
 
149
115
  noble.startScanning(
150
116
  expectedServiceUuids,
@@ -156,16 +122,17 @@ describe('noble', () => {
156
122
  noble.emit('stateChange', 'poweredOn');
157
123
  noble.emit('scanStart', 'filter');
158
124
 
159
- assert.calledOnceWithExactly(callback, null, 'filter');
160
- assert.calledOnceWithExactly(
161
- mockBindings.startScanning,
125
+ expect(callback).toHaveBeenCalledWith(null, 'filter');
126
+ expect(callback).toHaveBeenCalledTimes(1);
127
+ expect(mockBindings.startScanning).toHaveBeenCalledWith(
162
128
  expectedServiceUuids,
163
129
  expectedAllowDuplicates
164
130
  );
131
+ expect(mockBindings.startScanning).toHaveBeenCalledTimes(1);
165
132
  });
166
133
 
167
- it('should throw an error if not powered on', async () => {
168
- try {
134
+ test('should throw an error if not powered on', async () => {
135
+ expect(() => {
169
136
  noble.startScanning();
170
137
  noble.emit('stateChange', 'poweredOff');
171
138
  // Check for single callback
@@ -173,27 +140,14 @@ describe('noble', () => {
173
140
  noble.emit('scanStart');
174
141
  // Check for single callback
175
142
  noble.emit('scanStart');
176
-
177
- assert.fail();
178
- } catch (e) {
179
- should(e.message).equal(
180
- 'Could not start scanning, state is poweredOff (not poweredOn)'
181
- );
182
- }
183
- assert.notCalled(mockBindings.startScanning);
143
+ }).toThrow('Could not start scanning, state is poweredOff (not poweredOn)');
144
+
145
+ expect(mockBindings.startScanning).not.toHaveBeenCalled();
184
146
  });
185
147
  });
186
148
 
187
149
  describe('startScanningAsync', () => {
188
- beforeEach(() => {
189
- mockBindings.startScanning = sinon.spy();
190
- });
191
-
192
- afterEach(() => {
193
- sinon.reset();
194
- });
195
-
196
- it('should delegate to binding', async () => {
150
+ test('should delegate to binding', async () => {
197
151
  const expectedServiceUuids = [1, 2, 3];
198
152
  const expectedAllowDuplicates = true;
199
153
 
@@ -208,15 +162,15 @@ describe('noble', () => {
208
162
  // Check for single callback
209
163
  noble.emit('scanStart');
210
164
 
211
- should(promise).resolvedWith(undefined);
212
- assert.calledOnceWithExactly(
213
- mockBindings.startScanning,
165
+ await expect(promise).resolves.toBeUndefined();
166
+ expect(mockBindings.startScanning).toHaveBeenCalledWith(
214
167
  expectedServiceUuids,
215
168
  expectedAllowDuplicates
216
169
  );
170
+ expect(mockBindings.startScanning).toHaveBeenCalledTimes(1);
217
171
  });
218
172
 
219
- it('should throw an error if not powered on', async () => {
173
+ test('should throw an error if not powered on', async () => {
220
174
  const promise = noble.startScanningAsync();
221
175
  noble.emit('stateChange', 'poweredOff');
222
176
  // Check for single callback
@@ -225,311 +179,335 @@ describe('noble', () => {
225
179
  // Check for single callback
226
180
  noble.emit('scanStart');
227
181
 
228
- should(promise).rejectedWith(
182
+ await expect(promise).rejects.toThrow(
229
183
  'Could not start scanning, state is poweredOff (not poweredOn)'
230
184
  );
231
- assert.notCalled(mockBindings.startScanning);
185
+ expect(mockBindings.startScanning).not.toHaveBeenCalled();
232
186
  });
233
187
  });
234
188
 
235
189
  describe('stopScanning', () => {
236
- beforeEach(() => {
237
- mockBindings.stopScanning = sinon.spy();
238
- });
239
-
240
- afterEach(() => {
241
- sinon.reset();
242
- });
243
-
244
- it('should no callback', async () => {
245
- noble.initialized = true;
190
+ test('should no callback', async () => {
191
+ noble._initialized = true;
246
192
  noble.stopScanning();
247
- assert.calledOnceWithExactly(mockBindings.stopScanning);
193
+ expect(mockBindings.stopScanning).toHaveBeenCalled();
194
+ expect(mockBindings.stopScanning).toHaveBeenCalledTimes(1);
248
195
  });
249
196
  });
250
197
 
251
198
  describe('stopScanningAsync', () => {
252
- beforeEach(() => {
253
- mockBindings.stopScanning = sinon.spy();
254
- });
255
-
256
- afterEach(() => {
257
- sinon.reset();
258
- });
259
-
260
- it('should not delegate to binding (not initialized)', async () => {
199
+ test('should not delegate to binding (not initialized)', async () => {
261
200
  const promise = noble.stopScanningAsync();
262
201
  noble.emit('scanStop');
263
202
 
264
- should(promise).resolvedWith(undefined);
265
- assert.notCalled(mockBindings.stopScanning);
203
+ await expect(promise).rejects.toThrow('Bindings are not initialized');
204
+ expect(mockBindings.stopScanning).not.toHaveBeenCalled();
266
205
  });
267
206
 
268
- it('should delegate to binding (initilazed)', async () => {
269
- noble.initialized = true;
207
+ test('should delegate to binding (initilazed)', async () => {
208
+ noble._initialized = true;
270
209
  const promise = noble.stopScanningAsync();
271
210
  noble.emit('scanStop');
272
211
 
273
- should(promise).resolvedWith(undefined);
274
- assert.calledOnceWithExactly(mockBindings.stopScanning);
212
+ await expect(promise).resolves.toBeUndefined();
213
+ expect(mockBindings.stopScanning).toHaveBeenCalled();
214
+ expect(mockBindings.stopScanning).toHaveBeenCalledTimes(1);
275
215
  });
276
216
  });
277
217
 
278
218
  describe('connect', () => {
279
- beforeEach(() => {
280
- mockBindings.connect = sinon.spy();
281
- });
282
-
283
- afterEach(() => {
284
- sinon.reset();
285
- });
286
- it('should delegate to binding', () => {
219
+ test('should delegate to binding', () => {
287
220
  const peripheralUuid = 'peripheral-uuid';
288
221
  const parameters = {};
289
222
 
223
+ mockBindings.addressToId = jest.fn().mockReturnValue(peripheralUuid);
290
224
  noble.connect(peripheralUuid, parameters);
291
-
292
- assert.calledOnceWithExactly(
293
- mockBindings.connect,
225
+
226
+ expect(mockBindings.connect).toHaveBeenCalledWith(
294
227
  peripheralUuid,
295
228
  parameters
296
229
  );
230
+ expect(mockBindings.connect).toHaveBeenCalledTimes(1);
297
231
  });
298
232
  });
299
233
 
300
234
  describe('onConnect', () => {
301
- it('should emit connected on existing peripheral', () => {
302
- const emit = sinon.spy();
303
- noble._peripherals = {
304
- uuid: { emit }
305
- };
235
+ test('should emit connected on existing peripheral', () => {
236
+ const emit = jest.fn();
237
+ noble._peripherals.set('uuid', { emit });
306
238
 
307
- const warningCallback = sinon.spy();
239
+ const warningCallback = jest.fn();
308
240
 
309
241
  noble.on('warning', warningCallback);
310
- noble.onConnect('uuid', false);
242
+ noble._onConnect('uuid', false);
311
243
 
312
- assert.calledOnceWithExactly(emit, 'connect', false);
313
- assert.notCalled(warningCallback);
244
+ expect(emit).toHaveBeenCalledWith('connect', false);
245
+ expect(emit).toHaveBeenCalledTimes(1);
246
+ expect(warningCallback).not.toHaveBeenCalled();
314
247
 
315
- should(noble._peripherals).deepEqual({
316
- uuid: { state: 'connected', emit }
317
- });
248
+ const peripheral = noble._peripherals.get('uuid');
249
+ expect(peripheral).toHaveProperty('emit', emit);
250
+ expect(peripheral).toHaveProperty('state', 'connected');
318
251
  });
319
252
 
320
- it('should emit error on existing peripheral', () => {
321
- const emit = sinon.spy();
322
- noble._peripherals = {
323
- uuid: { emit }
324
- };
253
+ test('should emit error on existing peripheral', () => {
254
+ const emit = jest.fn();
255
+ noble._peripherals.set('uuid', { emit });
325
256
 
326
- const warningCallback = sinon.spy();
257
+ const warningCallback = jest.fn();
327
258
 
328
259
  noble.on('warning', warningCallback);
329
- noble.onConnect('uuid', true);
260
+ noble._onConnect('uuid', true);
330
261
 
331
- assert.calledOnceWithExactly(emit, 'connect', true);
332
- assert.notCalled(warningCallback);
262
+ expect(emit).toHaveBeenCalledWith('connect', true);
263
+ expect(emit).toHaveBeenCalledTimes(1);
264
+ expect(warningCallback).not.toHaveBeenCalled();
333
265
 
334
- should(noble._peripherals).deepEqual({
335
- uuid: { state: 'error', emit }
336
- });
266
+ const peripheral = noble._peripherals.get('uuid');
267
+ expect(peripheral).toHaveProperty('emit', emit);
268
+ expect(peripheral).toHaveProperty('state', 'error');
337
269
  });
338
270
 
339
- it('should emit warning on missing peripheral', () => {
340
- const warningCallback = sinon.spy();
271
+ test('should emit warning on missing peripheral', () => {
272
+ const warningCallback = jest.fn();
341
273
 
342
274
  noble.on('warning', warningCallback);
343
- noble.onConnect('uuid', true);
275
+ noble._onConnect('uuid', true);
344
276
 
345
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid connected!');
346
-
347
- should(noble._peripherals).deepEqual({});
277
+ expect(warningCallback).toHaveBeenCalledWith('unknown peripheral uuid connected!');
278
+ expect(warningCallback).toHaveBeenCalledTimes(1);
279
+ expect(noble._peripherals.size).toBe(0);
348
280
  });
349
281
  });
350
282
 
351
283
  describe('setScanParameters', () => {
352
- beforeEach(() => {
353
- mockBindings.setScanParameters = sinon.spy();
354
- });
355
-
356
- afterEach(() => {
357
- sinon.reset();
358
- });
359
-
360
- it('should delegate to binding', async () => {
284
+ test('should delegate to binding', async () => {
361
285
  const interval = 'interval';
362
286
  const window = 'window';
363
287
 
364
288
  noble.setScanParameters(interval, window);
365
289
  noble.emit('scanParametersSet');
366
290
 
367
- assert.calledOnceWithExactly(
368
- mockBindings.setScanParameters,
291
+ expect(mockBindings.setScanParameters).toHaveBeenCalledWith(
369
292
  interval,
370
293
  window
371
294
  );
295
+ expect(mockBindings.setScanParameters).toHaveBeenCalledTimes(1);
372
296
  });
373
297
 
374
- it('should delegate to callback too', async () => {
298
+ test('should delegate to callback too', async () => {
375
299
  const interval = 'interval';
376
300
  const window = 'window';
377
- const callback = sinon.spy();
301
+ const callback = jest.fn();
378
302
 
379
303
  noble.setScanParameters(interval, window, callback);
380
304
  noble.emit('scanParametersSet');
381
305
  // Check for single callback
382
306
  noble.emit('scanParametersSet');
383
307
 
384
- assert.calledOnceWithExactly(
385
- mockBindings.setScanParameters,
308
+ expect(mockBindings.setScanParameters).toHaveBeenCalledWith(
386
309
  interval,
387
310
  window
388
311
  );
389
- assert.calledOnceWithExactly(callback);
312
+ expect(mockBindings.setScanParameters).toHaveBeenCalledTimes(1);
313
+ expect(callback).toHaveBeenCalled();
314
+ expect(callback).toHaveBeenCalledTimes(1);
390
315
  });
391
316
  });
392
317
 
393
318
  describe('cancelConnect', () => {
394
- beforeEach(() => {
395
- mockBindings.cancelConnect = sinon.spy();
396
- });
397
-
398
- afterEach(() => {
399
- sinon.reset();
400
- });
401
-
402
- it('should delegate to binding', () => {
319
+ test('should delegate to binding', () => {
403
320
  const peripheralUuid = 'peripheral-uuid';
404
321
  const parameters = {};
405
322
 
323
+ mockBindings.addressToId = jest.fn().mockReturnValue(peripheralUuid);
406
324
  noble.cancelConnect(peripheralUuid, parameters);
407
325
 
408
- assert.calledOnceWithExactly(
409
- mockBindings.cancelConnect,
326
+ expect(mockBindings.cancelConnect).toHaveBeenCalledWith(
410
327
  peripheralUuid,
411
328
  parameters
412
329
  );
330
+ expect(mockBindings.cancelConnect).toHaveBeenCalledTimes(1);
331
+ });
332
+
333
+ test('should update peripheral state when cancelConnect is called during connection', () => {
334
+ // Setup a peripheral in connecting state
335
+ const peripheral = {
336
+ id: 'test-peripheral',
337
+ state: 'connecting',
338
+ emit: jest.fn()
339
+ };
340
+
341
+ noble._peripherals.set('test-peripheral', peripheral);
342
+
343
+ // Mock addressToId to return the peripheral id
344
+ mockBindings.addressToId = jest.fn().mockReturnValue('test-peripheral');
345
+
346
+ // Spy on noble's emit method
347
+ const emitSpy = jest.spyOn(noble, 'emit');
348
+
349
+ // Call cancelConnect
350
+ noble.cancelConnect('test-peripheral');
351
+
352
+ // Verify cancelConnect was called with correct parameters
353
+ expect(mockBindings.cancelConnect).toHaveBeenCalledWith(
354
+ 'test-peripheral',
355
+ undefined
356
+ );
357
+
358
+ // Verify peripheral state was updated to disconnected
359
+ expect(peripheral.state).toBe('disconnected');
360
+
361
+ // Verify connect event was emitted with error
362
+ expect(emitSpy).toHaveBeenCalledWith(
363
+ 'connect:test-peripheral',
364
+ expect.objectContaining({
365
+ message: 'connection canceled!'
366
+ })
367
+ );
413
368
  });
414
369
  });
415
370
 
416
- it('should emit state', () => {
417
- const callback = sinon.spy();
371
+ test('should emit state', () => {
372
+ const callback = jest.fn();
418
373
  noble.on('stateChange', callback);
419
374
 
420
375
  const state = 'newState';
421
- noble.onStateChange(state);
422
-
423
- should(noble._state).equal(state);
424
- assert.calledOnceWithExactly(callback, state);
425
- });
426
-
427
- it('should change address', () => {
376
+ noble._onStateChange(state);
377
+
378
+ expect(noble.state).toBe(state);
379
+ expect(callback).toHaveBeenCalledWith(state);
380
+ expect(callback).toHaveBeenCalledTimes(1);
381
+ });
382
+
383
+ describe('waitForPoweredOnAsync', () => {
384
+ test('should resolve when state changes to poweredOn', async () => {
385
+ // Set initial state to something other than poweredOn
386
+ noble._state = 'poweredOff';
387
+
388
+ // Create promise but don't await it yet
389
+ const promise = noble.waitForPoweredOnAsync();
390
+
391
+ // Emit state change event to poweredOn
392
+ noble.emit('stateChange', 'poweredOn');
393
+
394
+ // Now await the promise - it should resolve
395
+ await expect(promise).resolves.toBeUndefined();
396
+ });
397
+
398
+ test('should resolve immediately if state is already poweredOn', async () => {
399
+ // Set initial state to poweredOn
400
+ noble._state = 'poweredOn';
401
+
402
+ // Multiple concurrent calls should resolve immediately
403
+ const promise1 = noble.waitForPoweredOnAsync();
404
+ const promise2 = noble.waitForPoweredOnAsync();
405
+ const promise3 = noble.waitForPoweredOnAsync();
406
+
407
+ // Both promises should resolve
408
+ await expect(promise1).resolves.toBeUndefined();
409
+ await expect(promise2).resolves.toBeUndefined();
410
+ await expect(promise3).resolves.toBeUndefined();
411
+ });
412
+
413
+ test('should reject if timeout occurs before state changes to poweredOn', async () => {
414
+ // Set initial state to something other than poweredOn
415
+ noble._state = 'poweredOff';
416
+
417
+ // Set a very short timeout
418
+ const promise = noble.waitForPoweredOnAsync(10);
419
+
420
+ // Promise should reject after timeout
421
+ await expect(promise).rejects.toThrow('Timeout waiting for Noble to be powered on');
422
+ });
423
+ });
424
+
425
+ test('should change address', () => {
428
426
  const address = 'newAddress';
429
- noble.onAddressChange(address);
427
+ noble._onAddressChange(address);
430
428
 
431
- should(noble.address).equal(address);
429
+ expect(noble.address).toBe(address);
432
430
  });
433
431
 
434
- it('should emit scanParametersSet event', () => {
435
- const callback = sinon.spy();
432
+ test('should emit scanParametersSet event', () => {
433
+ const callback = jest.fn();
436
434
  noble.on('scanParametersSet', callback);
437
435
 
438
- noble.onScanParametersSet();
436
+ noble._onScanParametersSet();
439
437
 
440
- assert.calledOnceWithExactly(callback);
438
+ expect(callback).toHaveBeenCalled();
439
+ expect(callback).toHaveBeenCalledTimes(1);
441
440
  });
442
441
 
443
- it('should emit scanStart event', () => {
444
- const callback = sinon.spy();
442
+ test('should emit scanStart event', () => {
443
+ const callback = jest.fn();
445
444
  noble.on('scanStart', callback);
446
445
 
447
- noble.onScanStart('filterDuplicates');
446
+ noble._onScanStart('filterDuplicates');
448
447
 
449
- assert.calledOnceWithExactly(callback, 'filterDuplicates');
448
+ expect(callback).toHaveBeenCalledWith('filterDuplicates');
449
+ expect(callback).toHaveBeenCalledTimes(1);
450
450
  });
451
451
 
452
- it('should emit scanStop event', () => {
453
- const callback = sinon.spy();
452
+ test('should emit scanStop event', () => {
453
+ const callback = jest.fn();
454
454
  noble.on('scanStop', callback);
455
455
 
456
- noble.onScanStop();
456
+ noble._onScanStop();
457
457
 
458
- assert.calledOnceWithExactly(callback);
458
+ expect(callback).toHaveBeenCalled();
459
+ expect(callback).toHaveBeenCalledTimes(1);
459
460
  });
460
461
 
461
462
  describe('reset', () => {
462
- beforeEach(() => {
463
- mockBindings.reset = sinon.spy();
464
- });
465
-
466
- afterEach(() => {
467
- sinon.reset();
468
- });
469
-
470
- it('should reset', () => {
463
+ test('should reset', () => {
471
464
  noble.reset();
472
- assert.calledOnceWithExactly(mockBindings.reset);
465
+ expect(mockBindings.reset).toHaveBeenCalled();
466
+ expect(mockBindings.reset).toHaveBeenCalledTimes(1);
473
467
  });
474
468
  });
475
469
 
476
470
  describe('disconnect', () => {
477
- beforeEach(() => {
478
- mockBindings.disconnect = sinon.spy();
479
- });
480
-
481
- afterEach(() => {
482
- sinon.reset();
483
- });
484
-
485
- it('should disconnect', () => {
471
+ test('should disconnect', () => {
486
472
  noble.disconnect('peripheralUuid');
487
- assert.calledOnceWithExactly(mockBindings.disconnect, 'peripheralUuid');
473
+ expect(mockBindings.disconnect).toHaveBeenCalledWith('peripheralUuid');
474
+ expect(mockBindings.disconnect).toHaveBeenCalledTimes(1);
488
475
  });
489
476
  });
490
477
 
491
478
  describe('onDisconnect', () => {
492
- it('should emit disconnect on existing peripheral', () => {
493
- const emit = sinon.spy();
494
- noble._peripherals = {
495
- uuid: { emit }
496
- };
479
+ test('should emit disconnect on existing peripheral', () => {
480
+ const emit = jest.fn();
481
+ noble._peripherals.set('uuid', { emit });
497
482
 
498
- const warningCallback = sinon.spy();
483
+ const warningCallback = jest.fn();
499
484
 
500
485
  noble.on('warning', warningCallback);
501
- noble.onDisconnect('uuid', false);
486
+ noble._onDisconnect('uuid', false);
502
487
 
503
- assert.calledOnceWithExactly(emit, 'disconnect', false);
504
- assert.notCalled(warningCallback);
488
+ expect(emit).toHaveBeenCalledWith('disconnect', false);
489
+ expect(emit).toHaveBeenCalledTimes(1);
490
+ expect(warningCallback).not.toHaveBeenCalled();
505
491
 
506
- should(noble._peripherals).deepEqual({
507
- uuid: { state: 'disconnected', emit }
508
- });
492
+ const peripheral = noble._peripherals.get('uuid');
493
+ expect(peripheral).toHaveProperty('emit', emit);
494
+ expect(peripheral).toHaveProperty('state', 'disconnected');
509
495
  });
510
496
 
511
- it('should emit warning on missing peripheral', () => {
512
- const warningCallback = sinon.spy();
497
+ test('should emit warning on missing peripheral', () => {
498
+ const warningCallback = jest.fn();
513
499
 
514
500
  noble.on('warning', warningCallback);
515
- noble.onDisconnect('uuid', true);
501
+ noble._onDisconnect('uuid', true);
516
502
 
517
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid disconnected!');
518
-
519
- should(noble._peripherals).deepEqual({});
503
+ expect(warningCallback).toHaveBeenCalledWith('unknown peripheral uuid disconnected!');
504
+ expect(warningCallback).toHaveBeenCalledTimes(1);
505
+ expect(noble._peripherals.size).toBe(0);
520
506
  });
521
507
  });
522
508
 
523
509
  describe('onDiscover', () => {
524
- beforeEach(() => {
525
- mockBindings.disconnect = sinon.spy();
526
- });
527
-
528
- afterEach(() => {
529
- sinon.reset();
530
- });
531
-
532
- it('should add new peripheral', () => {
510
+ test('should add new peripheral', () => {
533
511
  const uuid = 'uuid';
534
512
  const address = 'address';
535
513
  const addressType = 'addressType';
@@ -537,10 +515,10 @@ describe('noble', () => {
537
515
  const advertisement = [];
538
516
  const rssi = 'rssi';
539
517
 
540
- const eventCallback = sinon.spy();
518
+ const eventCallback = jest.fn();
541
519
  noble.on('discover', eventCallback);
542
520
 
543
- noble.onDiscover(
521
+ noble._onDiscover(
544
522
  uuid,
545
523
  address,
546
524
  addressType,
@@ -550,25 +528,27 @@ describe('noble', () => {
550
528
  );
551
529
 
552
530
  // Check new peripheral
553
- should(noble._peripherals).have.keys(uuid);
554
- const peripheral = noble._peripherals[uuid];
555
- should(peripheral._noble).equal(noble);
556
- should(peripheral.id).equal(uuid);
557
- should(peripheral.address).equal(address);
558
- should(peripheral.addressType).equal(addressType);
559
- should(peripheral.connectable).equal(connectable);
560
- should(peripheral.advertisement).equal(advertisement);
561
- should(peripheral.rssi).equal(rssi);
562
-
563
- should(noble._services).have.keys(uuid);
564
- should(noble._characteristics).have.keys(uuid);
565
- should(noble._descriptors).have.keys(uuid);
566
- should(noble._discoveredPeripheralUUids).deepEqual({ uuid: true });
567
-
568
- assert.calledOnceWithExactly(eventCallback, peripheral);
531
+ expect(noble._peripherals.has(uuid)).toBe(true);
532
+ expect(noble._discoveredPeripherals.has(uuid)).toBe(true);
533
+
534
+ const peripheral = noble._peripherals.get(uuid);
535
+ expect(peripheral._noble).toBe(noble);
536
+ expect(peripheral.id).toBe(uuid);
537
+ expect(peripheral.address).toBe(address);
538
+ expect(peripheral.addressType).toBe(addressType);
539
+ expect(peripheral.connectable).toBe(connectable);
540
+ expect(peripheral.advertisement).toBe(advertisement);
541
+ expect(peripheral.rssi).toBe(rssi);
542
+
543
+ expect(noble._services[uuid]).toEqual({});
544
+ expect(noble._characteristics[uuid]).toEqual({});
545
+ expect(noble._descriptors[uuid]).toEqual({});
546
+
547
+ expect(eventCallback).toHaveBeenCalledWith(peripheral);
548
+ expect(eventCallback).toHaveBeenCalledTimes(1);
569
549
  });
570
550
 
571
- it('should update existing peripheral', () => {
551
+ test('should update existing peripheral', () => {
572
552
  const uuid = 'uuid';
573
553
  const address = 'address';
574
554
  const addressType = 'addressType';
@@ -577,7 +557,7 @@ describe('noble', () => {
577
557
  const rssi = 'rssi';
578
558
 
579
559
  // init peripheral
580
- noble._peripherals[uuid] = new Peripheral(
560
+ noble._peripherals.set(uuid, new Peripheral(
581
561
  noble,
582
562
  uuid,
583
563
  'originalAddress',
@@ -585,12 +565,12 @@ describe('noble', () => {
585
565
  'originalConnectable',
586
566
  ['adv1'],
587
567
  'originalRssi'
588
- );
568
+ ));
589
569
 
590
- const eventCallback = sinon.spy();
570
+ const eventCallback = jest.fn();
591
571
  noble.on('discover', eventCallback);
592
572
 
593
- noble.onDiscover(
573
+ noble._onDiscover(
594
574
  uuid,
595
575
  address,
596
576
  addressType,
@@ -599,26 +579,28 @@ describe('noble', () => {
599
579
  rssi
600
580
  );
601
581
 
602
- // Check new peripheral
603
- should(noble._peripherals).have.keys(uuid);
604
- const peripheral = noble._peripherals[uuid];
605
- should(peripheral._noble).equal(noble);
606
- should(peripheral.id).equal(uuid);
607
- should(peripheral.address).equal('originalAddress');
608
- should(peripheral.addressType).equal('originalAddressType');
609
- should(peripheral.connectable).equal(connectable);
610
- should(peripheral.advertisement).deepEqual(['adv1', 'adv2', 'adv3']);
611
- should(peripheral.rssi).equal(rssi);
612
-
613
- should(noble._services).be.empty();
614
- should(noble._characteristics).be.empty();
615
- should(noble._descriptors).be.empty();
616
- should(noble._discoveredPeripheralUUids).deepEqual({ uuid: true });
617
-
618
- assert.calledOnceWithExactly(eventCallback, peripheral);
582
+ // Check updated peripheral
583
+ expect(noble._peripherals.has(uuid)).toBe(true);
584
+ expect(noble._discoveredPeripherals.has(uuid)).toBe(true);
585
+
586
+ const peripheral = noble._peripherals.get(uuid);
587
+ expect(peripheral._noble).toBe(noble);
588
+ expect(peripheral.id).toBe(uuid);
589
+ expect(peripheral.address).toBe('originalAddress');
590
+ expect(peripheral.addressType).toBe('originalAddressType');
591
+ expect(peripheral.connectable).toBe(connectable);
592
+ expect(peripheral.advertisement).toEqual(['adv1', 'adv2', 'adv3']);
593
+ expect(peripheral.rssi).toBe(rssi);
594
+
595
+ expect(Object.keys(noble._services)).toHaveLength(0);
596
+ expect(Object.keys(noble._characteristics)).toHaveLength(0);
597
+ expect(Object.keys(noble._descriptors)).toHaveLength(0);
598
+
599
+ expect(eventCallback).toHaveBeenCalledWith(peripheral);
600
+ expect(eventCallback).toHaveBeenCalledTimes(1);
619
601
  });
620
602
 
621
- it('should emit on duplicate', () => {
603
+ test('should emit on duplicate', () => {
622
604
  const uuid = 'uuid';
623
605
  const address = 'address';
624
606
  const addressType = 'addressType';
@@ -627,13 +609,13 @@ describe('noble', () => {
627
609
  const rssi = 'rssi';
628
610
 
629
611
  // register peripheral
630
- noble._discoveredPeripheralUUids = { uuid: true };
612
+ noble._discoveredPeripherals.add(uuid);
631
613
  noble._allowDuplicates = true;
632
614
 
633
- const eventCallback = sinon.spy();
615
+ const eventCallback = jest.fn();
634
616
  noble.on('discover', eventCallback);
635
617
 
636
- noble.onDiscover(
618
+ noble._onDiscover(
637
619
  uuid,
638
620
  address,
639
621
  addressType,
@@ -642,10 +624,11 @@ describe('noble', () => {
642
624
  rssi
643
625
  );
644
626
 
645
- assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
627
+ expect(eventCallback).toHaveBeenCalledWith(noble._peripherals.get(uuid));
628
+ expect(eventCallback).toHaveBeenCalledTimes(1);
646
629
  });
647
630
 
648
- it('should not emit on duplicate', () => {
631
+ test('should not emit on duplicate', () => {
649
632
  const uuid = 'uuid';
650
633
  const address = 'address';
651
634
  const addressType = 'addressType';
@@ -654,12 +637,13 @@ describe('noble', () => {
654
637
  const rssi = 'rssi';
655
638
 
656
639
  // register peripheral
657
- noble._discoveredPeripheralUUids = { uuid: true };
640
+ noble._discoveredPeripherals.add(uuid);
641
+ noble._allowDuplicates = false;
658
642
 
659
- const eventCallback = sinon.spy();
643
+ const eventCallback = jest.fn();
660
644
  noble.on('discover', eventCallback);
661
645
 
662
- noble.onDiscover(
646
+ noble._onDiscover(
663
647
  uuid,
664
648
  address,
665
649
  addressType,
@@ -668,10 +652,10 @@ describe('noble', () => {
668
652
  rssi
669
653
  );
670
654
 
671
- assert.notCalled(eventCallback);
655
+ expect(eventCallback).not.toHaveBeenCalled();
672
656
  });
673
657
 
674
- it('should emit on new peripheral (even if duplicates are disallowed)', () => {
658
+ test('should emit on new peripheral (even if duplicates are disallowed)', () => {
675
659
  const uuid = 'uuid';
676
660
  const address = 'address';
677
661
  const addressType = 'addressType';
@@ -679,10 +663,10 @@ describe('noble', () => {
679
663
  const advertisement = ['adv1', 'adv2', 'adv3'];
680
664
  const rssi = 'rssi';
681
665
 
682
- const eventCallback = sinon.spy();
666
+ const eventCallback = jest.fn();
683
667
  noble.on('discover', eventCallback);
684
668
 
685
- noble.onDiscover(
669
+ noble._onDiscover(
686
670
  uuid,
687
671
  address,
688
672
  addressType,
@@ -691,69 +675,57 @@ describe('noble', () => {
691
675
  rssi
692
676
  );
693
677
 
694
- assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
678
+ expect(eventCallback).toHaveBeenCalledWith(noble._peripherals.get(uuid));
679
+ expect(eventCallback).toHaveBeenCalledTimes(1);
695
680
  });
696
681
  });
697
682
 
698
683
  describe('updateRssi', () => {
699
- beforeEach(() => {
700
- mockBindings.updateRssi = sinon.spy();
701
- });
702
-
703
- afterEach(() => {
704
- sinon.reset();
705
- });
706
-
707
- it('should updateRssi', () => {
684
+ test('should updateRssi', () => {
708
685
  noble.updateRssi('peripheralUuid');
709
- assert.calledOnceWithExactly(mockBindings.updateRssi, 'peripheralUuid');
686
+ expect(mockBindings.updateRssi).toHaveBeenCalledWith('peripheralUuid');
687
+ expect(mockBindings.updateRssi).toHaveBeenCalledTimes(1);
710
688
  });
711
689
  });
712
690
 
713
691
  describe('onRssiUpdate', () => {
714
- it('should emit rssiUpdate on existing peripheral', () => {
715
- const emit = sinon.spy();
716
- noble._peripherals = {
717
- uuid: { emit }
718
- };
719
-
720
- const warningCallback = sinon.spy();
692
+ test('should emit rssiUpdate on existing peripheral', () => {
693
+ const emit = jest.fn();
694
+ noble._peripherals.set('uuid', { emit });
721
695
 
722
- noble.on('warning', warningCallback);
723
- noble.onRssiUpdate('uuid', 3);
696
+ noble._onRssiUpdate('uuid', 3);
724
697
 
725
- assert.calledOnceWithExactly(emit, 'rssiUpdate', 3);
726
- assert.notCalled(warningCallback);
698
+ expect(emit).toHaveBeenCalledWith('rssiUpdate', 3, undefined);
699
+ expect(emit).toHaveBeenCalledTimes(1);
727
700
 
728
- should(noble._peripherals).deepEqual({
729
- uuid: { rssi: 3, emit }
730
- });
701
+ const peripheral = noble._peripherals.get('uuid');
702
+ expect(peripheral).toHaveProperty('emit', emit);
703
+ expect(peripheral).toHaveProperty('rssi', 3);
731
704
  });
732
705
 
733
- it('should emit warning on missing peripheral', () => {
734
- const warningCallback = sinon.spy();
706
+ test('should emit warning on missing peripheral', () => {
707
+ const warningCallback = jest.fn();
735
708
 
736
709
  noble.on('warning', warningCallback);
737
- noble.onRssiUpdate('uuid', 4);
710
+ noble._onRssiUpdate('uuid', 4);
738
711
 
739
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid RSSI update!');
740
-
741
- should(noble._peripherals).deepEqual({});
712
+ expect(warningCallback).toHaveBeenCalledWith('unknown peripheral uuid RSSI update!');
713
+ expect(warningCallback).toHaveBeenCalledTimes(1);
714
+ expect(noble._peripherals.size).toBe(0);
742
715
  });
743
716
  });
744
717
 
745
- it('should add multiple services', () => {
746
- noble.addService = sinon.stub().returnsArg(1);
718
+ test('should add multiple services', () => {
719
+ noble.addService = jest.fn().mockImplementation((peripheralUuid, service) => service);
747
720
 
748
721
  const peripheralUuid = 'peripheralUuid';
749
722
  const services = ['service1', 'service2'];
750
723
  const result = noble.addServices(peripheralUuid, services);
751
724
 
752
- assert.callCount(noble.addService, 2);
753
- assert.calledWithExactly(noble.addService, peripheralUuid, 'service1');
754
- assert.calledWithExactly(noble.addService, peripheralUuid, 'service2');
755
-
756
- should(result).deepEqual(services);
725
+ expect(noble.addService).toHaveBeenCalledTimes(2);
726
+ expect(noble.addService).toHaveBeenNthCalledWith(1, peripheralUuid, 'service1');
727
+ expect(noble.addService).toHaveBeenNthCalledWith(2, peripheralUuid, 'service2');
728
+ expect(result).toEqual(services);
757
729
  });
758
730
 
759
731
  describe('addService', () => {
@@ -764,58 +736,59 @@ describe('noble', () => {
764
736
  const peripheral = {};
765
737
 
766
738
  beforeEach(() => {
767
- noble._peripherals = { [peripheralUuid]: peripheral };
739
+ noble._peripherals.set(peripheralUuid, peripheral);
768
740
  noble._services = { [peripheralUuid]: {} };
769
741
  noble._characteristics = { [peripheralUuid]: {} };
770
742
  noble._descriptors = { [peripheralUuid]: {} };
771
743
  });
772
744
 
773
- it('should add service to lower layer', () => {
774
- noble._bindings.addService = sinon.spy();
745
+ test('should add service to lower layer', () => {
746
+ noble._bindings.addService = jest.fn();
775
747
 
776
748
  const result = noble.addService(peripheralUuid, service);
777
749
 
778
- assert.calledOnceWithExactly(noble._bindings.addService, peripheralUuid, service);
750
+ expect(noble._bindings.addService).toHaveBeenCalledWith(peripheralUuid, service);
751
+ expect(noble._bindings.addService).toHaveBeenCalledTimes(1);
779
752
 
780
753
  const expectedService = new Service(noble, peripheralUuid, service.uuid);
781
- should(result).deepEqual(expectedService);
782
- should(peripheral.services).deepEqual([expectedService]);
783
- should(noble._services).deepEqual({
754
+ expect(result).toEqual(expectedService);
755
+ expect(peripheral.services).toEqual([expectedService]);
756
+ expect(noble._services).toEqual({
784
757
  [peripheralUuid]: {
785
758
  [service.uuid]: expectedService
786
759
  }
787
760
  });
788
- should(noble._characteristics).deepEqual({
761
+ expect(noble._characteristics).toEqual({
789
762
  [peripheralUuid]: {
790
763
  [service.uuid]: {}
791
764
  }
792
765
  });
793
- should(noble._descriptors).deepEqual({
766
+ expect(noble._descriptors).toEqual({
794
767
  [peripheralUuid]: {
795
768
  [service.uuid]: {}
796
769
  }
797
770
  });
798
771
  });
799
772
 
800
- it('should add service only to noble', () => {
773
+ test('should add service only to noble', () => {
801
774
  peripheral.services = [];
802
775
 
803
776
  const result = noble.addService(peripheralUuid, service);
804
777
 
805
778
  const expectedService = new Service(noble, peripheralUuid, service.uuid);
806
- should(result).deepEqual(expectedService);
807
- should(peripheral.services).deepEqual([expectedService]);
808
- should(noble._services).deepEqual({
779
+ expect(result).toEqual(expectedService);
780
+ expect(peripheral.services).toEqual([expectedService]);
781
+ expect(noble._services).toEqual({
809
782
  [peripheralUuid]: {
810
783
  [service.uuid]: expectedService
811
784
  }
812
785
  });
813
- should(noble._characteristics).deepEqual({
786
+ expect(noble._characteristics).toEqual({
814
787
  [peripheralUuid]: {
815
788
  [service.uuid]: {}
816
789
  }
817
790
  });
818
- should(noble._descriptors).deepEqual({
791
+ expect(noble._descriptors).toEqual({
819
792
  [peripheralUuid]: {
820
793
  [service.uuid]: {}
821
794
  }
@@ -827,740 +800,105 @@ describe('noble', () => {
827
800
  const peripheralUuid = 'peripheralUuid';
828
801
  const services = ['service1', 'service2'];
829
802
 
830
- it('should not emit servicesDiscovered', () => {
831
- const callback = sinon.spy();
803
+ test('should not emit servicesDiscovered', () => {
804
+ const callback = jest.fn();
832
805
  noble.on('servicesDiscovered', callback);
833
806
 
834
- noble.onServicesDiscovered(peripheralUuid, services);
807
+ noble._onServicesDiscovered(peripheralUuid, services);
835
808
 
836
- assert.notCalled(callback);
809
+ expect(callback).not.toHaveBeenCalled();
837
810
  });
838
811
 
839
- it('should emit servicesDiscovered', () => {
840
- const emit = sinon.spy();
841
- noble._peripherals = { [peripheralUuid]: { uuid: 'peripheral', emit } };
812
+ test('should emit servicesDiscovered', () => {
813
+ const emit = jest.fn();
814
+ noble._peripherals.set(peripheralUuid, { uuid: 'peripheral', emit });
842
815
 
843
- noble.onServicesDiscovered(peripheralUuid, services);
816
+ noble._onServicesDiscovered(peripheralUuid, services);
844
817
 
845
- assert.calledOnceWithExactly(emit, 'servicesDiscovered', { uuid: 'peripheral', emit }, services);
818
+ expect(emit).toHaveBeenCalledWith('servicesDiscovered', { uuid: 'peripheral', emit }, services);
819
+ expect(emit).toHaveBeenCalledTimes(1);
846
820
  });
847
821
  });
848
822
 
849
- it('discoverServices - should delegate to bindings', () => {
850
- noble._bindings.discoverServices = sinon.spy();
823
+ test('discoverServices - should delegate to bindings', () => {
824
+ noble._bindings.discoverServices = jest.fn();
851
825
  noble.discoverServices('peripheral', 'uuids');
852
- assert.calledOnceWithExactly(noble._bindings.discoverServices, 'peripheral', 'uuids');
853
- });
854
-
855
- describe('onServicesDiscover', () => {
856
- it('should emit warning', () => {
857
- const warningCallback = sinon.spy();
858
-
859
- noble.on('warning', warningCallback);
860
-
861
- noble.onServicesDiscover('pUuid', ['service1', 'service2']);
862
-
863
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral pUuid services discover!');
864
- });
865
-
866
- it('should emit servicesDiscover and store services', () => {
867
- const warningCallback = sinon.spy();
868
- const discoverCallback = sinon.spy();
869
-
870
- const peripheralUuid = 'peripheralUuid';
871
-
872
- noble._peripherals = { [peripheralUuid]: { emit: discoverCallback } };
873
- noble._services = { [peripheralUuid]: {} };
874
- noble._characteristics = { [peripheralUuid]: {} };
875
- noble._descriptors = { [peripheralUuid]: {} };
876
-
877
- noble.on('warning', warningCallback);
878
-
879
- noble.onServicesDiscover(peripheralUuid, ['service1', 'service2']);
880
-
881
- const services = [new Service(noble, peripheralUuid, 'service1'), new Service(noble, peripheralUuid, 'service2')];
882
-
883
- assert.calledOnceWithExactly(discoverCallback, 'servicesDiscover', services);
884
- assert.notCalled(warningCallback);
885
-
886
- should(noble._peripherals).deepEqual({
887
- [peripheralUuid]: { services, emit: discoverCallback }
888
- });
889
- should(noble._services).deepEqual({
890
- [peripheralUuid]: { service1: services[0], service2: services[1] }
891
- });
892
- should(noble._characteristics).deepEqual({
893
- [peripheralUuid]: { service1: {}, service2: {} }
894
- });
895
- should(noble._descriptors).deepEqual({
896
- [peripheralUuid]: { service1: {}, service2: {} }
897
- });
898
- });
899
- });
900
-
901
- describe('discoverIncludedServices', () => {
902
- beforeEach(() => {
903
- mockBindings.discoverIncludedServices = sinon.spy();
904
- });
905
-
906
- afterEach(() => {
907
- sinon.reset();
908
- });
909
-
910
- it('should disconnect', () => {
911
- noble.discoverIncludedServices('peripheralUuid', 'serviceUuid', 'serviceUuids');
912
- assert.calledOnceWithExactly(mockBindings.discoverIncludedServices, 'peripheralUuid', 'serviceUuid', 'serviceUuids');
913
- });
914
- });
915
-
916
- describe('addCharacteristics', () => {
917
- const peripheralUuid = 'peripheralUuid';
918
- const serviceUuid = 'serviceUuid';
919
- const characteristic1 = {
920
- uuid: 'characteristic1',
921
- properties: 'properties1'
922
- };
923
- const characteristic2 = {
924
- uuid: 'characteristic2',
925
- properties: 'properties2'
926
- };
927
- const characteristics = [characteristic1, characteristic2];
928
-
929
- beforeEach(() => {
930
- noble._services = { [peripheralUuid]: { [serviceUuid]: {} } };
931
- noble._characteristics = { [peripheralUuid]: { [serviceUuid]: {} } };
932
- noble._descriptors = { [peripheralUuid]: { [serviceUuid]: {} } };
933
- });
934
-
935
- it('should delegate to bindings', () => {
936
- const warningCallback = sinon.spy();
937
-
938
- noble._bindings.addCharacteristics = sinon.spy();
939
- noble.on('warning', warningCallback);
940
-
941
- const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
942
-
943
- assert.notCalled(warningCallback);
944
- assert.calledOnceWithExactly(noble._bindings.addCharacteristics, peripheralUuid, serviceUuid, characteristics);
945
-
946
- const expectedCharacteristics = [
947
- new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic1', 'properties1'),
948
- new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic2', 'properties2')
949
- ];
950
- should(result).deepEqual(expectedCharacteristics);
951
- should(noble._services).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristics: expectedCharacteristics } } });
952
- should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] } } });
953
- should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } } });
954
- });
955
-
956
- it('should not delegate to bindings', () => {
957
- const warningCallback = sinon.spy();
958
-
959
- noble.on('warning', warningCallback);
960
-
961
- const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
962
-
963
- assert.notCalled(warningCallback);
964
-
965
- const expectedCharacteristics = [
966
- new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic1', 'properties1'),
967
- new Characteristic(noble, peripheralUuid, serviceUuid, 'characteristic2', 'properties2')
968
- ];
969
- should(result).deepEqual(expectedCharacteristics);
970
- should(noble._services).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristics: expectedCharacteristics } } });
971
- should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] } } });
972
- should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } } });
973
- });
974
-
975
- it('should emit warning', () => {
976
- const warningCallback = sinon.spy();
977
-
978
- noble.on('warning', warningCallback);
979
-
980
- noble._services = { peripheralUuid: {} };
981
- const result = noble.addCharacteristics(peripheralUuid, serviceUuid, characteristics);
982
-
983
- assert.calledOnceWithExactly(warningCallback, 'unknown service peripheralUuid, serviceUuid characteristics discover!');
984
-
985
- should(result).equal(undefined);
986
- should(noble._services).deepEqual({ [peripheralUuid]: { } });
987
- should(noble._characteristics).deepEqual({ [peripheralUuid]: { [serviceUuid]: { } } });
988
- should(noble._descriptors).deepEqual({ [peripheralUuid]: { [serviceUuid]: { } } });
989
- });
990
- });
991
-
992
- it('onCharacteristicsDiscovered - should emit event', () => {
993
- const emit = sinon.spy();
994
-
995
- noble._services = {
996
- peripheralUuid: {
997
- serviceUuid: {
998
- emit
999
- }
1000
- }
1001
- };
1002
-
1003
- noble.onCharacteristicsDiscovered('peripheralUuid', 'serviceUuid', 'characteristics');
1004
-
1005
- assert.calledOnceWithExactly(emit, 'characteristicsDiscovered', 'characteristics');
1006
- });
1007
-
1008
- it('discoverCharacteristics - should delegate', () => {
1009
- noble._bindings.discoverCharacteristics = sinon.spy();
1010
-
1011
- noble.discoverCharacteristics('peripheralUuid', 'serviceUuid', 'characteristicUuids');
1012
-
1013
- assert.calledOnceWithExactly(noble._bindings.discoverCharacteristics, 'peripheralUuid', 'serviceUuid', 'characteristicUuids');
826
+ expect(noble._bindings.discoverServices).toHaveBeenCalledWith('peripheral', 'uuids');
827
+ expect(noble._bindings.discoverServices).toHaveBeenCalledTimes(1);
1014
828
  });
1015
829
 
1016
- describe('onCharacteristicsDiscover', () => {
1017
- it('should emit warning', () => {
1018
- const warningCallback = sinon.spy();
1019
-
1020
- const peripheralUuid = 'peripheralUuid';
1021
- const serviceUuid = 'serviceUuid';
1022
- const characteristics = ['characteristic1', 'characteristic2'];
1023
-
1024
- noble.on('warning', warningCallback);
1025
-
1026
- noble._services[peripheralUuid] = {};
1027
- noble.onCharacteristicsDiscover(peripheralUuid, serviceUuid, characteristics);
1028
-
1029
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid characteristics discover!');
1030
- });
1031
-
1032
- it('should emit characteristicsDiscover and store characteristics', () => {
1033
- const warningCallback = sinon.spy();
1034
- const emit = sinon.spy();
1035
-
1036
- const peripheralUuid = 'peripheralUuid';
1037
- const serviceUuid = 'serviceUuid';
1038
- const characteristics = [
1039
- { uuid: 'characteristic1', properties: 'properties1' },
1040
- { uuid: 'characteristic2', properties: 'properties2' }
1041
- ];
1042
-
1043
- noble._services = { [peripheralUuid]: { [serviceUuid]: { emit } } };
1044
- noble._characteristics = { [peripheralUuid]: { [serviceUuid]: {} } };
1045
- noble._descriptors = { [peripheralUuid]: { [serviceUuid]: {} } };
1046
-
1047
- noble.on('warning', warningCallback);
1048
-
1049
- noble.onCharacteristicsDiscover(peripheralUuid, serviceUuid, characteristics);
1050
-
1051
- const expectedCharacteristics = [
1052
- new Characteristic(noble, peripheralUuid, serviceUuid, characteristics[0].uuid, characteristics[0].properties),
1053
- new Characteristic(noble, peripheralUuid, serviceUuid, characteristics[1].uuid, characteristics[1].properties)
1054
- ];
1055
-
1056
- assert.calledOnceWithExactly(emit, 'characteristicsDiscover', expectedCharacteristics);
1057
- assert.notCalled(warningCallback);
1058
-
1059
- should(noble._services).deepEqual({
1060
- [peripheralUuid]: {
1061
- [serviceUuid]: {
1062
- emit, characteristics: expectedCharacteristics
1063
- }
1064
- }
1065
- });
1066
- should(noble._characteristics).deepEqual({
1067
- [peripheralUuid]: {
1068
- [serviceUuid]: { characteristic1: expectedCharacteristics[0], characteristic2: expectedCharacteristics[1] }
1069
- }
1070
- });
1071
- should(noble._descriptors).deepEqual({
1072
- [peripheralUuid]: { [serviceUuid]: { characteristic1: {}, characteristic2: {} } }
1073
- });
1074
- });
1075
- });
1076
-
1077
- it('read - should delegate to bindings', () => {
1078
- noble._bindings.read = sinon.spy();
1079
- noble.read('peripheralUuid', 'serviceUuid', 'characteristicUuid');
1080
- assert.calledOnceWithExactly(noble._bindings.read, 'peripheralUuid', 'serviceUuid', 'characteristicUuid');
1081
- });
1082
-
1083
- describe('onRead', () => {
1084
- it('should emit warning', () => {
1085
- const warningCallback = sinon.spy();
1086
- noble.on('warning', warningCallback);
1087
-
1088
- noble._characteristics = {
1089
- peripheralUuid: {
1090
- serviceUuid: {
1091
- }
1092
- }
1093
- };
1094
- noble.onRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'data', 'isNotification');
1095
-
1096
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid read!');
1097
- });
1098
-
1099
- it('should emit data and read', () => {
1100
- const warningCallback = sinon.spy();
1101
- const emit = sinon.spy();
1102
-
1103
- noble.on('warning', warningCallback);
1104
-
1105
- noble._characteristics = {
1106
- peripheralUuid: {
1107
- serviceUuid: {
1108
- characteristicUuid: {
1109
- emit
1110
- }
1111
- }
1112
- }
1113
- };
1114
- noble.onRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
1115
-
1116
- assert.notCalled(warningCallback);
1117
- assert.callCount(emit, 2);
1118
- assert.calledWithExactly(emit, 'data', 'dataArg', 'isNotification');
1119
- assert.calledWithExactly(emit, 'read', 'dataArg', 'isNotification');
1120
- });
1121
- });
1122
-
1123
- it('write - should delegate to bindings', () => {
1124
- noble._bindings.write = sinon.spy();
1125
- noble.write('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
1126
- assert.calledOnceWithExactly(noble._bindings.write, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'dataArg', 'isNotification');
1127
- });
1128
-
1129
- describe('onWrite', () => {
1130
- it('should emit warning', () => {
1131
- const warningCallback = sinon.spy();
1132
- noble.on('warning', warningCallback);
1133
-
1134
- noble._characteristics = {
1135
- peripheralUuid: {
1136
- serviceUuid: {
1137
- }
1138
- }
1139
- };
1140
- noble.onWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid');
1141
-
1142
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid write!');
1143
- });
1144
-
1145
- it('should emit write', () => {
1146
- const warningCallback = sinon.spy();
1147
- const emit = sinon.spy();
1148
-
1149
- noble.on('warning', warningCallback);
1150
-
1151
- noble._characteristics = {
1152
- peripheralUuid: {
1153
- serviceUuid: {
1154
- characteristicUuid: {
1155
- emit
1156
- }
1157
- }
1158
- }
1159
- };
1160
- noble.onWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid');
1161
-
1162
- assert.notCalled(warningCallback);
1163
- assert.calledOnceWithExactly(emit, 'write');
1164
- });
1165
- });
1166
-
1167
- it('broadcast - should delegate to bindings', () => {
1168
- noble._bindings.broadcast = sinon.spy();
1169
- noble.broadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'broadcast');
1170
- assert.calledOnceWithExactly(noble._bindings.broadcast, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'broadcast');
1171
- });
1172
-
1173
- describe('onBroadcast', () => {
1174
- it('should emit warning', () => {
1175
- const warningCallback = sinon.spy();
1176
- noble.on('warning', warningCallback);
1177
-
1178
- noble._characteristics = {
1179
- peripheralUuid: {
1180
- serviceUuid: {
1181
- }
1182
- }
1183
- };
1184
- noble.onBroadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
1185
-
1186
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid broadcast!');
1187
- });
1188
-
1189
- it('should emit broadcast', () => {
1190
- const warningCallback = sinon.spy();
1191
- const emit = sinon.spy();
1192
-
1193
- noble.on('warning', warningCallback);
1194
-
1195
- noble._characteristics = {
1196
- peripheralUuid: {
1197
- serviceUuid: {
1198
- characteristicUuid: {
1199
- emit
1200
- }
1201
- }
1202
- }
1203
- };
1204
- noble.onBroadcast('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
1205
-
1206
- assert.notCalled(warningCallback);
1207
- assert.calledOnceWithExactly(emit, 'broadcast', 'state');
1208
- });
1209
- });
1210
-
1211
- it('notify - should delegate to bindings', () => {
1212
- noble._bindings.notify = sinon.spy();
1213
- noble.notify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'notify');
1214
- assert.calledOnceWithExactly(noble._bindings.notify, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'notify');
1215
- });
1216
-
1217
- describe('onNotify', () => {
1218
- it('should emit warning', () => {
1219
- const warningCallback = sinon.spy();
1220
- noble.on('warning', warningCallback);
1221
-
1222
- noble._characteristics = {
1223
- peripheralUuid: {
1224
- serviceUuid: {
1225
- }
1226
- }
1227
- };
1228
- noble.onNotify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
1229
-
1230
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid notify!');
1231
- });
1232
-
1233
- it('should emit notify', () => {
1234
- const warningCallback = sinon.spy();
1235
- const emit = sinon.spy();
1236
-
1237
- noble.on('warning', warningCallback);
1238
-
1239
- noble._characteristics = {
1240
- peripheralUuid: {
1241
- serviceUuid: {
1242
- characteristicUuid: {
1243
- emit
1244
- }
1245
- }
1246
- }
1247
- };
1248
- noble.onNotify('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'state');
1249
-
1250
- assert.notCalled(warningCallback);
1251
- assert.calledOnceWithExactly(emit, 'notify', 'state');
1252
- });
1253
- });
1254
-
1255
- it('discoverDescriptors - should delegate', () => {
1256
- noble._bindings.discoverDescriptors = sinon.spy();
1257
-
1258
- noble.discoverDescriptors('peripheralUuid', 'serviceUuid', 'characteristicUuid');
1259
-
1260
- assert.calledOnceWithExactly(noble._bindings.discoverDescriptors, 'peripheralUuid', 'serviceUuid', 'characteristicUuid');
1261
- });
1262
-
1263
- describe('onDescriptorsDiscover', () => {
1264
- it('should emit warning', () => {
1265
- const warningCallback = sinon.spy();
1266
-
1267
- const peripheralUuid = 'peripheralUuid';
1268
- const serviceUuid = 'serviceUuid';
1269
- const characteristicUuid = 'characteristicUuid';
1270
- const descriptors = ['descriptor1', 'descriptor2'];
1271
-
1272
- noble.on('warning', warningCallback);
1273
-
1274
- noble._characteristics[peripheralUuid] = {
1275
- [serviceUuid]: {}
1276
- };
1277
- noble.onDescriptorsDiscover(peripheralUuid, serviceUuid, characteristicUuid, descriptors);
1278
-
1279
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid descriptors discover!');
1280
- });
1281
-
1282
- it('should emit characteristicsDiscover and store characteristics', () => {
1283
- const warningCallback = sinon.spy();
1284
- const emit = sinon.spy();
1285
-
1286
- const peripheralUuid = 'peripheralUuid';
1287
- const serviceUuid = 'serviceUuid';
1288
- const characteristicUuid = 'characteristicUuid';
1289
- const descriptors = ['descriptor1', 'descriptor2'];
1290
-
1291
- noble._characteristics = { [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { emit } } } };
1292
- noble._descriptors = { [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: {} } } };
1293
-
1294
- noble.on('warning', warningCallback);
1295
-
1296
- noble.onDescriptorsDiscover(peripheralUuid, serviceUuid, characteristicUuid, descriptors);
1297
-
1298
- const expectedDescriptors = [
1299
- new Descriptor(noble, peripheralUuid, serviceUuid, characteristicUuid, descriptors[0]),
1300
- new Descriptor(noble, peripheralUuid, serviceUuid, characteristicUuid, descriptors[1])
1301
- ];
1302
-
1303
- assert.calledOnceWithExactly(emit, 'descriptorsDiscover', expectedDescriptors);
1304
- assert.notCalled(warningCallback);
1305
-
1306
- should(noble._characteristics).deepEqual({
1307
- [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { emit, descriptors: expectedDescriptors } } }
1308
- });
1309
- should(noble._descriptors).deepEqual({
1310
- [peripheralUuid]: { [serviceUuid]: { [characteristicUuid]: { descriptor1: expectedDescriptors[0], descriptor2: expectedDescriptors[1] } } }
1311
- });
1312
- });
1313
- });
1314
-
1315
- it('readValue - should delegate to bindings', () => {
1316
- noble._bindings.readValue = sinon.spy();
1317
- noble.readValue('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
1318
- assert.calledOnceWithExactly(noble._bindings.readValue, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
1319
- });
1320
-
1321
- describe('onValueRead', () => {
1322
- it('should emit warning', () => {
1323
- const warningCallback = sinon.spy();
1324
- noble.on('warning', warningCallback);
1325
-
1326
- noble._descriptors = {
1327
- peripheralUuid: {
1328
- serviceUuid: {
1329
- characteristicUuid: {}
1330
- }
1331
- }
1332
- };
1333
- noble.onValueRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
1334
-
1335
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid value read!');
1336
- });
1337
-
1338
- it('should emit valueRead', () => {
1339
- const warningCallback = sinon.spy();
1340
- const emit = sinon.spy();
1341
-
1342
- noble.on('warning', warningCallback);
1343
-
1344
- noble._descriptors = {
1345
- peripheralUuid: {
1346
- serviceUuid: {
1347
- characteristicUuid: {
1348
- descriptorUuid: {
1349
- emit
1350
- }
1351
- }
1352
- }
1353
- }
1354
- };
1355
- noble.onValueRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
1356
-
1357
- assert.notCalled(warningCallback);
1358
- assert.calledOnceWithExactly(emit, 'valueRead', 'data');
1359
- });
1360
- });
1361
-
1362
- it('writeValue - should delegate to bindings', () => {
1363
- noble._bindings.writeValue = sinon.spy();
1364
- noble.writeValue('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
1365
- assert.calledOnceWithExactly(noble._bindings.writeValue, 'peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid', 'data');
1366
- });
1367
-
1368
- describe('onValueWrite', () => {
1369
- it('should emit warning', () => {
1370
- const warningCallback = sinon.spy();
1371
- noble.on('warning', warningCallback);
1372
-
1373
- noble._descriptors = {
1374
- peripheralUuid: {
1375
- serviceUuid: {
1376
- characteristicUuid: {}
1377
- }
1378
- }
1379
- };
1380
- noble.onValueWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
1381
-
1382
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid value write!');
1383
- });
1384
-
1385
- it('should emit valueWrite', () => {
1386
- const warningCallback = sinon.spy();
1387
- const emit = sinon.spy();
1388
-
1389
- noble.on('warning', warningCallback);
1390
-
1391
- noble._descriptors = {
1392
- peripheralUuid: {
1393
- serviceUuid: {
1394
- characteristicUuid: {
1395
- descriptorUuid: {
1396
- emit
1397
- }
1398
- }
1399
- }
1400
- }
1401
- };
1402
- noble.onValueWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'descriptorUuid');
1403
-
1404
- assert.notCalled(warningCallback);
1405
- assert.calledOnceWithExactly(emit, 'valueWrite');
1406
- });
1407
- });
1408
-
1409
- it('readHandle - should delegate to bindings', () => {
1410
- noble._bindings.readHandle = sinon.spy();
1411
- noble.readHandle('peripheralUuid', 'handle');
1412
- assert.calledOnceWithExactly(noble._bindings.readHandle, 'peripheralUuid', 'handle');
1413
- });
1414
-
1415
- describe('onHandleRead', () => {
1416
- it('should emit warning', () => {
1417
- const warningCallback = sinon.spy();
1418
- noble.on('warning', warningCallback);
1419
-
1420
- noble._peripherals = {
830
+ describe('onMtu', () => {
831
+ test('should update peripheral mtu when set before already', () => {
832
+ const peripheral = {
833
+ mtu: 234,
834
+ emit: jest.fn()
1421
835
  };
1422
- noble.onHandleRead('peripheralUuid', 'nameOfHandle', 'data');
1423
836
 
1424
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle read!');
1425
- });
1426
-
1427
- it('should emit handleWrite', () => {
1428
- const warningCallback = sinon.spy();
1429
- const emit = sinon.spy();
1430
-
1431
- noble.on('warning', warningCallback);
1432
-
1433
- noble._peripherals = {
1434
- peripheralUuid: {
1435
- emit
1436
- }
1437
- };
1438
- noble.onHandleRead('peripheralUuid', 'nameOfHandle', 'data');
837
+ noble._peripherals.set('uuid', peripheral);
838
+ noble._onMtu('uuid', 123);
1439
839
 
1440
- assert.notCalled(warningCallback);
1441
- assert.calledOnceWithExactly(emit, 'handleReadnameOfHandle', 'data');
840
+ expect(peripheral.mtu).toBe(123);
841
+ expect(peripheral.emit).toHaveBeenCalledWith('mtu', 123);
842
+ expect(peripheral.emit).toHaveBeenCalledTimes(1);
1442
843
  });
1443
- });
1444
-
1445
- it('writeHandle - should delegate to bindings', () => {
1446
- noble._bindings.writeHandle = sinon.spy();
1447
- noble.writeHandle('peripheralUuid', 'handle', 'data', 'withoutResponse');
1448
- assert.calledOnceWithExactly(noble._bindings.writeHandle, 'peripheralUuid', 'handle', 'data', 'withoutResponse');
1449
- });
1450
844
 
1451
- describe('onHandleWrite', () => {
1452
- it('should emit warning', () => {
1453
- const warningCallback = sinon.spy();
1454
- noble.on('warning', warningCallback);
1455
-
1456
- noble._peripherals = {
845
+ test('should update peripheral mtu too when empty', () => {
846
+ const peripheral = {
847
+ mtu: null,
848
+ emit: jest.fn()
1457
849
  };
1458
- noble.onHandleWrite('peripheralUuid', 'nameOfHandle');
1459
-
1460
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle write!');
1461
- });
1462
850
 
1463
- it('should emit handleRead', () => {
1464
- const warningCallback = sinon.spy();
1465
- const emit = sinon.spy();
851
+ noble._peripherals.set('uuid', peripheral);
852
+ noble._onMtu('uuid', 123);
1466
853
 
1467
- noble.on('warning', warningCallback);
1468
-
1469
- noble._peripherals = {
1470
- peripheralUuid: {
1471
- emit
1472
- }
1473
- };
1474
- noble.onHandleWrite('peripheralUuid', 'nameOfHandle');
1475
-
1476
- assert.notCalled(warningCallback);
1477
- assert.calledOnceWithExactly(emit, 'handleWritenameOfHandle');
854
+ expect(peripheral.mtu).toBe(123);
855
+ expect(peripheral.emit).toHaveBeenCalledWith('mtu', 123);
856
+ expect(peripheral.emit).toHaveBeenCalledTimes(1);
1478
857
  });
1479
858
  });
1480
859
 
1481
- describe('onHandleNotify', () => {
1482
- it('should emit warning', () => {
1483
- const warningCallback = sinon.spy();
1484
- noble.on('warning', warningCallback);
1485
-
1486
- noble._peripherals = {
860
+ describe('state change handling', () => {
861
+ test('should disconnect peripherals when state changes to poweredOff', () => {
862
+ // Setup a connected peripheral
863
+ const peripheral = {
864
+ id: 'test-peripheral',
865
+ state: 'connected',
866
+ emit: jest.fn()
1487
867
  };
1488
- noble.onHandleNotify('peripheralUuid', 'nameOfHandle', 'data');
1489
-
1490
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle notify!');
1491
- });
1492
-
1493
- it('should emit handleNotify', () => {
1494
- const warningCallback = sinon.spy();
1495
- const emit = sinon.spy();
1496
-
1497
- noble.on('warning', warningCallback);
1498
-
1499
- noble._peripherals = {
1500
- peripheralUuid: {
1501
- emit
1502
- }
1503
- };
1504
- noble.onHandleNotify('peripheralUuid', 'nameOfHandle', 'data');
1505
-
1506
- assert.notCalled(warningCallback);
1507
- assert.calledOnceWithExactly(emit, 'handleNotify', 'nameOfHandle', 'data');
1508
- });
1509
- });
1510
-
1511
- it('onMtu - should update peripheral mtu when set before already', () => {
1512
- const peripheral = {
1513
- mtu: 234
1514
- };
1515
-
1516
- noble._peripherals = { uuid: peripheral };
1517
- noble.onMtu('uuid', 123);
1518
-
1519
- should(peripheral).deepEqual({ mtu: 123 });
1520
- });
1521
-
1522
- it('onMtu - should update peripheral mtu too when empty', () => {
1523
- const peripheral = {
1524
- mtu: null
1525
- };
1526
-
1527
- noble._peripherals = { uuid: peripheral };
1528
- noble.onMtu('uuid', 123);
1529
-
1530
- should(peripheral).deepEqual({ mtu: 123 });
1531
- });
1532
-
1533
- describe('onIncludedServicesDiscover', () => {
1534
- it('should emit connected on existing peripheral', () => {
1535
- const emit = sinon.spy();
1536
- noble._services = {
1537
- uuid: { serviceUuid: { emit } }
868
+ noble._peripherals.set('test-peripheral', peripheral);
869
+ noble._state = 'poweredOn';
870
+
871
+ // Mock the _onDisconnect method to verify it's called
872
+ const originalOnDisconnect = noble._onDisconnect;
873
+ noble._onDisconnect = jest.fn();
874
+
875
+ // Trigger state change to poweredOff
876
+ noble._onStateChange('poweredOff');
877
+
878
+ // Check if _onDisconnect was called for the peripheral
879
+ expect(noble._onDisconnect).toHaveBeenCalledWith('test-peripheral', 'cleanup');
880
+
881
+ // Restore original method
882
+ noble._onDisconnect = originalOnDisconnect;
883
+ });
884
+
885
+ test('should update peripheral state when cleaned up during poweredOff', () => {
886
+ // Setup a connected peripheral
887
+ const peripheral = {
888
+ id: 'test-peripheral',
889
+ state: 'connected',
890
+ emit: jest.fn()
1538
891
  };
1539
-
1540
- const warningCallback = sinon.spy();
1541
-
1542
- noble.on('warning', warningCallback);
1543
- noble.onIncludedServicesDiscover('uuid', 'serviceUuid', 'serviceUuids');
1544
-
1545
- assert.calledOnceWithExactly(emit, 'includedServicesDiscover', 'serviceUuids');
1546
- assert.notCalled(warningCallback);
1547
-
1548
- should(noble._services).deepEqual({
1549
- uuid: { serviceUuid: { includedServiceUuids: 'serviceUuids', emit } }
1550
- });
1551
- });
1552
-
1553
- it('should emit warning on missing peripheral', () => {
1554
- noble._services = { uuid: {} };
1555
-
1556
- const warningCallback = sinon.spy();
1557
-
1558
- noble.on('warning', warningCallback);
1559
- noble.onIncludedServicesDiscover('uuid', 'serviceUuid', 'serviceUuids');
1560
-
1561
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid, serviceUuid included services discover!');
1562
-
1563
- should(noble._services).deepEqual({ uuid: {} });
1564
- });
1565
- });
1566
- });
892
+ noble._peripherals.set('test-peripheral', peripheral);
893
+
894
+ // Call the cleanup method directly
895
+ noble._cleanupPeriperals('test-peripheral');
896
+
897
+ // Verify peripheral emitted disconnect event
898
+ expect(peripheral.emit).toHaveBeenCalledWith('disconnect', 'cleanup');
899
+
900
+ // Verify peripheral state was updated
901
+ expect(peripheral.state).toBe('disconnected');
902
+ });
903
+ });
904
+ });