@stoprocent/noble 1.19.0 → 2.0.0

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 +579 -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 +381 -1085
  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,293 @@ 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);
344
-
345
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid connected!');
275
+ noble._onConnect('uuid', true);
346
276
 
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);
376
+ noble._onStateChange(state);
422
377
 
423
- should(noble._state).equal(state);
424
- assert.calledOnceWithExactly(callback, state);
378
+ expect(noble.state).toBe(state);
379
+ expect(callback).toHaveBeenCalledWith(state);
380
+ expect(callback).toHaveBeenCalledTimes(1);
425
381
  });
426
382
 
427
- it('should change address', () => {
383
+ test('should change address', () => {
428
384
  const address = 'newAddress';
429
- noble.onAddressChange(address);
385
+ noble._onAddressChange(address);
430
386
 
431
- should(noble.address).equal(address);
387
+ expect(noble.address).toBe(address);
432
388
  });
433
389
 
434
- it('should emit scanParametersSet event', () => {
435
- const callback = sinon.spy();
390
+ test('should emit scanParametersSet event', () => {
391
+ const callback = jest.fn();
436
392
  noble.on('scanParametersSet', callback);
437
393
 
438
- noble.onScanParametersSet();
394
+ noble._onScanParametersSet();
439
395
 
440
- assert.calledOnceWithExactly(callback);
396
+ expect(callback).toHaveBeenCalled();
397
+ expect(callback).toHaveBeenCalledTimes(1);
441
398
  });
442
399
 
443
- it('should emit scanStart event', () => {
444
- const callback = sinon.spy();
400
+ test('should emit scanStart event', () => {
401
+ const callback = jest.fn();
445
402
  noble.on('scanStart', callback);
446
403
 
447
- noble.onScanStart('filterDuplicates');
404
+ noble._onScanStart('filterDuplicates');
448
405
 
449
- assert.calledOnceWithExactly(callback, 'filterDuplicates');
406
+ expect(callback).toHaveBeenCalledWith('filterDuplicates');
407
+ expect(callback).toHaveBeenCalledTimes(1);
450
408
  });
451
409
 
452
- it('should emit scanStop event', () => {
453
- const callback = sinon.spy();
410
+ test('should emit scanStop event', () => {
411
+ const callback = jest.fn();
454
412
  noble.on('scanStop', callback);
455
413
 
456
- noble.onScanStop();
414
+ noble._onScanStop();
457
415
 
458
- assert.calledOnceWithExactly(callback);
416
+ expect(callback).toHaveBeenCalled();
417
+ expect(callback).toHaveBeenCalledTimes(1);
459
418
  });
460
419
 
461
420
  describe('reset', () => {
462
- beforeEach(() => {
463
- mockBindings.reset = sinon.spy();
464
- });
465
-
466
- afterEach(() => {
467
- sinon.reset();
468
- });
469
-
470
- it('should reset', () => {
421
+ test('should reset', () => {
471
422
  noble.reset();
472
- assert.calledOnceWithExactly(mockBindings.reset);
423
+ expect(mockBindings.reset).toHaveBeenCalled();
424
+ expect(mockBindings.reset).toHaveBeenCalledTimes(1);
473
425
  });
474
426
  });
475
427
 
476
428
  describe('disconnect', () => {
477
- beforeEach(() => {
478
- mockBindings.disconnect = sinon.spy();
479
- });
480
-
481
- afterEach(() => {
482
- sinon.reset();
483
- });
484
-
485
- it('should disconnect', () => {
429
+ test('should disconnect', () => {
486
430
  noble.disconnect('peripheralUuid');
487
- assert.calledOnceWithExactly(mockBindings.disconnect, 'peripheralUuid');
431
+ expect(mockBindings.disconnect).toHaveBeenCalledWith('peripheralUuid');
432
+ expect(mockBindings.disconnect).toHaveBeenCalledTimes(1);
488
433
  });
489
434
  });
490
435
 
491
436
  describe('onDisconnect', () => {
492
- it('should emit disconnect on existing peripheral', () => {
493
- const emit = sinon.spy();
494
- noble._peripherals = {
495
- uuid: { emit }
496
- };
437
+ test('should emit disconnect on existing peripheral', () => {
438
+ const emit = jest.fn();
439
+ noble._peripherals.set('uuid', { emit });
497
440
 
498
- const warningCallback = sinon.spy();
441
+ const warningCallback = jest.fn();
499
442
 
500
443
  noble.on('warning', warningCallback);
501
- noble.onDisconnect('uuid', false);
444
+ noble._onDisconnect('uuid', false);
502
445
 
503
- assert.calledOnceWithExactly(emit, 'disconnect', false);
504
- assert.notCalled(warningCallback);
446
+ expect(emit).toHaveBeenCalledWith('disconnect', false);
447
+ expect(emit).toHaveBeenCalledTimes(1);
448
+ expect(warningCallback).not.toHaveBeenCalled();
505
449
 
506
- should(noble._peripherals).deepEqual({
507
- uuid: { state: 'disconnected', emit }
508
- });
450
+ const peripheral = noble._peripherals.get('uuid');
451
+ expect(peripheral).toHaveProperty('emit', emit);
452
+ expect(peripheral).toHaveProperty('state', 'disconnected');
509
453
  });
510
454
 
511
- it('should emit warning on missing peripheral', () => {
512
- const warningCallback = sinon.spy();
455
+ test('should emit warning on missing peripheral', () => {
456
+ const warningCallback = jest.fn();
513
457
 
514
458
  noble.on('warning', warningCallback);
515
- noble.onDisconnect('uuid', true);
516
-
517
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid disconnected!');
459
+ noble._onDisconnect('uuid', true);
518
460
 
519
- should(noble._peripherals).deepEqual({});
461
+ expect(warningCallback).toHaveBeenCalledWith('unknown peripheral uuid disconnected!');
462
+ expect(warningCallback).toHaveBeenCalledTimes(1);
463
+ expect(noble._peripherals.size).toBe(0);
520
464
  });
521
465
  });
522
466
 
523
467
  describe('onDiscover', () => {
524
- beforeEach(() => {
525
- mockBindings.disconnect = sinon.spy();
526
- });
527
-
528
- afterEach(() => {
529
- sinon.reset();
530
- });
531
-
532
- it('should add new peripheral', () => {
468
+ test('should add new peripheral', () => {
533
469
  const uuid = 'uuid';
534
470
  const address = 'address';
535
471
  const addressType = 'addressType';
@@ -537,10 +473,10 @@ describe('noble', () => {
537
473
  const advertisement = [];
538
474
  const rssi = 'rssi';
539
475
 
540
- const eventCallback = sinon.spy();
476
+ const eventCallback = jest.fn();
541
477
  noble.on('discover', eventCallback);
542
478
 
543
- noble.onDiscover(
479
+ noble._onDiscover(
544
480
  uuid,
545
481
  address,
546
482
  addressType,
@@ -550,25 +486,27 @@ describe('noble', () => {
550
486
  );
551
487
 
552
488
  // 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);
489
+ expect(noble._peripherals.has(uuid)).toBe(true);
490
+ expect(noble._discoveredPeripherals.has(uuid)).toBe(true);
491
+
492
+ const peripheral = noble._peripherals.get(uuid);
493
+ expect(peripheral._noble).toBe(noble);
494
+ expect(peripheral.id).toBe(uuid);
495
+ expect(peripheral.address).toBe(address);
496
+ expect(peripheral.addressType).toBe(addressType);
497
+ expect(peripheral.connectable).toBe(connectable);
498
+ expect(peripheral.advertisement).toBe(advertisement);
499
+ expect(peripheral.rssi).toBe(rssi);
500
+
501
+ expect(noble._services[uuid]).toEqual({});
502
+ expect(noble._characteristics[uuid]).toEqual({});
503
+ expect(noble._descriptors[uuid]).toEqual({});
504
+
505
+ expect(eventCallback).toHaveBeenCalledWith(peripheral);
506
+ expect(eventCallback).toHaveBeenCalledTimes(1);
569
507
  });
570
508
 
571
- it('should update existing peripheral', () => {
509
+ test('should update existing peripheral', () => {
572
510
  const uuid = 'uuid';
573
511
  const address = 'address';
574
512
  const addressType = 'addressType';
@@ -577,7 +515,7 @@ describe('noble', () => {
577
515
  const rssi = 'rssi';
578
516
 
579
517
  // init peripheral
580
- noble._peripherals[uuid] = new Peripheral(
518
+ noble._peripherals.set(uuid, new Peripheral(
581
519
  noble,
582
520
  uuid,
583
521
  'originalAddress',
@@ -585,12 +523,12 @@ describe('noble', () => {
585
523
  'originalConnectable',
586
524
  ['adv1'],
587
525
  'originalRssi'
588
- );
526
+ ));
589
527
 
590
- const eventCallback = sinon.spy();
528
+ const eventCallback = jest.fn();
591
529
  noble.on('discover', eventCallback);
592
530
 
593
- noble.onDiscover(
531
+ noble._onDiscover(
594
532
  uuid,
595
533
  address,
596
534
  addressType,
@@ -599,26 +537,28 @@ describe('noble', () => {
599
537
  rssi
600
538
  );
601
539
 
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);
540
+ // Check updated peripheral
541
+ expect(noble._peripherals.has(uuid)).toBe(true);
542
+ expect(noble._discoveredPeripherals.has(uuid)).toBe(true);
543
+
544
+ const peripheral = noble._peripherals.get(uuid);
545
+ expect(peripheral._noble).toBe(noble);
546
+ expect(peripheral.id).toBe(uuid);
547
+ expect(peripheral.address).toBe('originalAddress');
548
+ expect(peripheral.addressType).toBe('originalAddressType');
549
+ expect(peripheral.connectable).toBe(connectable);
550
+ expect(peripheral.advertisement).toEqual(['adv1', 'adv2', 'adv3']);
551
+ expect(peripheral.rssi).toBe(rssi);
552
+
553
+ expect(Object.keys(noble._services)).toHaveLength(0);
554
+ expect(Object.keys(noble._characteristics)).toHaveLength(0);
555
+ expect(Object.keys(noble._descriptors)).toHaveLength(0);
556
+
557
+ expect(eventCallback).toHaveBeenCalledWith(peripheral);
558
+ expect(eventCallback).toHaveBeenCalledTimes(1);
619
559
  });
620
560
 
621
- it('should emit on duplicate', () => {
561
+ test('should emit on duplicate', () => {
622
562
  const uuid = 'uuid';
623
563
  const address = 'address';
624
564
  const addressType = 'addressType';
@@ -627,13 +567,13 @@ describe('noble', () => {
627
567
  const rssi = 'rssi';
628
568
 
629
569
  // register peripheral
630
- noble._discoveredPeripheralUUids = { uuid: true };
570
+ noble._discoveredPeripherals.add(uuid);
631
571
  noble._allowDuplicates = true;
632
572
 
633
- const eventCallback = sinon.spy();
573
+ const eventCallback = jest.fn();
634
574
  noble.on('discover', eventCallback);
635
575
 
636
- noble.onDiscover(
576
+ noble._onDiscover(
637
577
  uuid,
638
578
  address,
639
579
  addressType,
@@ -642,10 +582,11 @@ describe('noble', () => {
642
582
  rssi
643
583
  );
644
584
 
645
- assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
585
+ expect(eventCallback).toHaveBeenCalledWith(noble._peripherals.get(uuid));
586
+ expect(eventCallback).toHaveBeenCalledTimes(1);
646
587
  });
647
588
 
648
- it('should not emit on duplicate', () => {
589
+ test('should not emit on duplicate', () => {
649
590
  const uuid = 'uuid';
650
591
  const address = 'address';
651
592
  const addressType = 'addressType';
@@ -654,12 +595,13 @@ describe('noble', () => {
654
595
  const rssi = 'rssi';
655
596
 
656
597
  // register peripheral
657
- noble._discoveredPeripheralUUids = { uuid: true };
598
+ noble._discoveredPeripherals.add(uuid);
599
+ noble._allowDuplicates = false;
658
600
 
659
- const eventCallback = sinon.spy();
601
+ const eventCallback = jest.fn();
660
602
  noble.on('discover', eventCallback);
661
603
 
662
- noble.onDiscover(
604
+ noble._onDiscover(
663
605
  uuid,
664
606
  address,
665
607
  addressType,
@@ -668,10 +610,10 @@ describe('noble', () => {
668
610
  rssi
669
611
  );
670
612
 
671
- assert.notCalled(eventCallback);
613
+ expect(eventCallback).not.toHaveBeenCalled();
672
614
  });
673
615
 
674
- it('should emit on new peripheral (even if duplicates are disallowed)', () => {
616
+ test('should emit on new peripheral (even if duplicates are disallowed)', () => {
675
617
  const uuid = 'uuid';
676
618
  const address = 'address';
677
619
  const addressType = 'addressType';
@@ -679,10 +621,10 @@ describe('noble', () => {
679
621
  const advertisement = ['adv1', 'adv2', 'adv3'];
680
622
  const rssi = 'rssi';
681
623
 
682
- const eventCallback = sinon.spy();
624
+ const eventCallback = jest.fn();
683
625
  noble.on('discover', eventCallback);
684
626
 
685
- noble.onDiscover(
627
+ noble._onDiscover(
686
628
  uuid,
687
629
  address,
688
630
  addressType,
@@ -691,69 +633,57 @@ describe('noble', () => {
691
633
  rssi
692
634
  );
693
635
 
694
- assert.calledOnceWithExactly(eventCallback, noble._peripherals[uuid]);
636
+ expect(eventCallback).toHaveBeenCalledWith(noble._peripherals.get(uuid));
637
+ expect(eventCallback).toHaveBeenCalledTimes(1);
695
638
  });
696
639
  });
697
640
 
698
641
  describe('updateRssi', () => {
699
- beforeEach(() => {
700
- mockBindings.updateRssi = sinon.spy();
701
- });
702
-
703
- afterEach(() => {
704
- sinon.reset();
705
- });
706
-
707
- it('should updateRssi', () => {
642
+ test('should updateRssi', () => {
708
643
  noble.updateRssi('peripheralUuid');
709
- assert.calledOnceWithExactly(mockBindings.updateRssi, 'peripheralUuid');
644
+ expect(mockBindings.updateRssi).toHaveBeenCalledWith('peripheralUuid');
645
+ expect(mockBindings.updateRssi).toHaveBeenCalledTimes(1);
710
646
  });
711
647
  });
712
648
 
713
649
  describe('onRssiUpdate', () => {
714
- it('should emit rssiUpdate on existing peripheral', () => {
715
- const emit = sinon.spy();
716
- noble._peripherals = {
717
- uuid: { emit }
718
- };
650
+ test('should emit rssiUpdate on existing peripheral', () => {
651
+ const emit = jest.fn();
652
+ noble._peripherals.set('uuid', { emit });
719
653
 
720
- const warningCallback = sinon.spy();
654
+ noble._onRssiUpdate('uuid', 3);
721
655
 
722
- noble.on('warning', warningCallback);
723
- noble.onRssiUpdate('uuid', 3);
724
-
725
- assert.calledOnceWithExactly(emit, 'rssiUpdate', 3);
726
- assert.notCalled(warningCallback);
656
+ expect(emit).toHaveBeenCalledWith('rssiUpdate', 3, undefined);
657
+ expect(emit).toHaveBeenCalledTimes(1);
727
658
 
728
- should(noble._peripherals).deepEqual({
729
- uuid: { rssi: 3, emit }
730
- });
659
+ const peripheral = noble._peripherals.get('uuid');
660
+ expect(peripheral).toHaveProperty('emit', emit);
661
+ expect(peripheral).toHaveProperty('rssi', 3);
731
662
  });
732
663
 
733
- it('should emit warning on missing peripheral', () => {
734
- const warningCallback = sinon.spy();
664
+ test('should emit warning on missing peripheral', () => {
665
+ const warningCallback = jest.fn();
735
666
 
736
667
  noble.on('warning', warningCallback);
737
- noble.onRssiUpdate('uuid', 4);
668
+ noble._onRssiUpdate('uuid', 4);
738
669
 
739
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral uuid RSSI update!');
740
-
741
- should(noble._peripherals).deepEqual({});
670
+ expect(warningCallback).toHaveBeenCalledWith('unknown peripheral uuid RSSI update!');
671
+ expect(warningCallback).toHaveBeenCalledTimes(1);
672
+ expect(noble._peripherals.size).toBe(0);
742
673
  });
743
674
  });
744
675
 
745
- it('should add multiple services', () => {
746
- noble.addService = sinon.stub().returnsArg(1);
676
+ test('should add multiple services', () => {
677
+ noble.addService = jest.fn().mockImplementation((peripheralUuid, service) => service);
747
678
 
748
679
  const peripheralUuid = 'peripheralUuid';
749
680
  const services = ['service1', 'service2'];
750
681
  const result = noble.addServices(peripheralUuid, services);
751
682
 
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);
683
+ expect(noble.addService).toHaveBeenCalledTimes(2);
684
+ expect(noble.addService).toHaveBeenNthCalledWith(1, peripheralUuid, 'service1');
685
+ expect(noble.addService).toHaveBeenNthCalledWith(2, peripheralUuid, 'service2');
686
+ expect(result).toEqual(services);
757
687
  });
758
688
 
759
689
  describe('addService', () => {
@@ -764,58 +694,59 @@ describe('noble', () => {
764
694
  const peripheral = {};
765
695
 
766
696
  beforeEach(() => {
767
- noble._peripherals = { [peripheralUuid]: peripheral };
697
+ noble._peripherals.set(peripheralUuid, peripheral);
768
698
  noble._services = { [peripheralUuid]: {} };
769
699
  noble._characteristics = { [peripheralUuid]: {} };
770
700
  noble._descriptors = { [peripheralUuid]: {} };
771
701
  });
772
702
 
773
- it('should add service to lower layer', () => {
774
- noble._bindings.addService = sinon.spy();
703
+ test('should add service to lower layer', () => {
704
+ noble._bindings.addService = jest.fn();
775
705
 
776
706
  const result = noble.addService(peripheralUuid, service);
777
707
 
778
- assert.calledOnceWithExactly(noble._bindings.addService, peripheralUuid, service);
708
+ expect(noble._bindings.addService).toHaveBeenCalledWith(peripheralUuid, service);
709
+ expect(noble._bindings.addService).toHaveBeenCalledTimes(1);
779
710
 
780
711
  const expectedService = new Service(noble, peripheralUuid, service.uuid);
781
- should(result).deepEqual(expectedService);
782
- should(peripheral.services).deepEqual([expectedService]);
783
- should(noble._services).deepEqual({
712
+ expect(result).toEqual(expectedService);
713
+ expect(peripheral.services).toEqual([expectedService]);
714
+ expect(noble._services).toEqual({
784
715
  [peripheralUuid]: {
785
716
  [service.uuid]: expectedService
786
717
  }
787
718
  });
788
- should(noble._characteristics).deepEqual({
719
+ expect(noble._characteristics).toEqual({
789
720
  [peripheralUuid]: {
790
721
  [service.uuid]: {}
791
722
  }
792
723
  });
793
- should(noble._descriptors).deepEqual({
724
+ expect(noble._descriptors).toEqual({
794
725
  [peripheralUuid]: {
795
726
  [service.uuid]: {}
796
727
  }
797
728
  });
798
729
  });
799
730
 
800
- it('should add service only to noble', () => {
731
+ test('should add service only to noble', () => {
801
732
  peripheral.services = [];
802
733
 
803
734
  const result = noble.addService(peripheralUuid, service);
804
735
 
805
736
  const expectedService = new Service(noble, peripheralUuid, service.uuid);
806
- should(result).deepEqual(expectedService);
807
- should(peripheral.services).deepEqual([expectedService]);
808
- should(noble._services).deepEqual({
737
+ expect(result).toEqual(expectedService);
738
+ expect(peripheral.services).toEqual([expectedService]);
739
+ expect(noble._services).toEqual({
809
740
  [peripheralUuid]: {
810
741
  [service.uuid]: expectedService
811
742
  }
812
743
  });
813
- should(noble._characteristics).deepEqual({
744
+ expect(noble._characteristics).toEqual({
814
745
  [peripheralUuid]: {
815
746
  [service.uuid]: {}
816
747
  }
817
748
  });
818
- should(noble._descriptors).deepEqual({
749
+ expect(noble._descriptors).toEqual({
819
750
  [peripheralUuid]: {
820
751
  [service.uuid]: {}
821
752
  }
@@ -827,740 +758,105 @@ describe('noble', () => {
827
758
  const peripheralUuid = 'peripheralUuid';
828
759
  const services = ['service1', 'service2'];
829
760
 
830
- it('should not emit servicesDiscovered', () => {
831
- const callback = sinon.spy();
761
+ test('should not emit servicesDiscovered', () => {
762
+ const callback = jest.fn();
832
763
  noble.on('servicesDiscovered', callback);
833
764
 
834
- noble.onServicesDiscovered(peripheralUuid, services);
765
+ noble._onServicesDiscovered(peripheralUuid, services);
835
766
 
836
- assert.notCalled(callback);
767
+ expect(callback).not.toHaveBeenCalled();
837
768
  });
838
769
 
839
- it('should emit servicesDiscovered', () => {
840
- const emit = sinon.spy();
841
- noble._peripherals = { [peripheralUuid]: { uuid: 'peripheral', emit } };
770
+ test('should emit servicesDiscovered', () => {
771
+ const emit = jest.fn();
772
+ noble._peripherals.set(peripheralUuid, { uuid: 'peripheral', emit });
842
773
 
843
- noble.onServicesDiscovered(peripheralUuid, services);
774
+ noble._onServicesDiscovered(peripheralUuid, services);
844
775
 
845
- assert.calledOnceWithExactly(emit, 'servicesDiscovered', { uuid: 'peripheral', emit }, services);
776
+ expect(emit).toHaveBeenCalledWith('servicesDiscovered', { uuid: 'peripheral', emit }, services);
777
+ expect(emit).toHaveBeenCalledTimes(1);
846
778
  });
847
779
  });
848
780
 
849
- it('discoverServices - should delegate to bindings', () => {
850
- noble._bindings.discoverServices = sinon.spy();
781
+ test('discoverServices - should delegate to bindings', () => {
782
+ noble._bindings.discoverServices = jest.fn();
851
783
  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
- });
784
+ expect(noble._bindings.discoverServices).toHaveBeenCalledWith('peripheral', 'uuids');
785
+ expect(noble._bindings.discoverServices).toHaveBeenCalledTimes(1);
899
786
  });
900
787
 
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');
1014
- });
1015
-
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
- }
788
+ describe('onMtu', () => {
789
+ test('should update peripheral mtu when set before already', () => {
790
+ const peripheral = {
791
+ mtu: 234,
792
+ emit: jest.fn()
1093
793
  };
1094
- noble.onRead('peripheralUuid', 'serviceUuid', 'characteristicUuid', 'data', 'isNotification');
1095
-
1096
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid read!');
1097
- });
1098
794
 
1099
- it('should emit data and read', () => {
1100
- const warningCallback = sinon.spy();
1101
- const emit = sinon.spy();
795
+ noble._peripherals.set('uuid', peripheral);
796
+ noble._onMtu('uuid', 123);
1102
797
 
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');
798
+ expect(peripheral.mtu).toBe(123);
799
+ expect(peripheral.emit).toHaveBeenCalledWith('mtu', 123);
800
+ expect(peripheral.emit).toHaveBeenCalledTimes(1);
1120
801
  });
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
802
 
1134
- noble._characteristics = {
1135
- peripheralUuid: {
1136
- serviceUuid: {
1137
- }
1138
- }
803
+ test('should update peripheral mtu too when empty', () => {
804
+ const peripheral = {
805
+ mtu: null,
806
+ emit: jest.fn()
1139
807
  };
1140
- noble.onWrite('peripheralUuid', 'serviceUuid', 'characteristicUuid');
1141
-
1142
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid, serviceUuid, characteristicUuid write!');
1143
- });
1144
808
 
1145
- it('should emit write', () => {
1146
- const warningCallback = sinon.spy();
1147
- const emit = sinon.spy();
809
+ noble._peripherals.set('uuid', peripheral);
810
+ noble._onMtu('uuid', 123);
1148
811
 
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');
812
+ expect(peripheral.mtu).toBe(123);
813
+ expect(peripheral.emit).toHaveBeenCalledWith('mtu', 123);
814
+ expect(peripheral.emit).toHaveBeenCalledTimes(1);
1164
815
  });
1165
816
  });
1166
817
 
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
- }
818
+ describe('state change handling', () => {
819
+ test('should disconnect peripherals when state changes to poweredOff', () => {
820
+ // Setup a connected peripheral
821
+ const peripheral = {
822
+ id: 'test-peripheral',
823
+ state: 'connected',
824
+ emit: jest.fn()
1203
825
  };
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 = {
1421
- };
1422
- noble.onHandleRead('peripheralUuid', 'nameOfHandle', 'data');
1423
-
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');
1439
-
1440
- assert.notCalled(warningCallback);
1441
- assert.calledOnceWithExactly(emit, 'handleReadnameOfHandle', 'data');
1442
- });
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
-
1451
- describe('onHandleWrite', () => {
1452
- it('should emit warning', () => {
1453
- const warningCallback = sinon.spy();
1454
- noble.on('warning', warningCallback);
1455
-
1456
- noble._peripherals = {
1457
- };
1458
- noble.onHandleWrite('peripheralUuid', 'nameOfHandle');
1459
-
1460
- assert.calledOnceWithExactly(warningCallback, 'unknown peripheral peripheralUuid handle write!');
1461
- });
1462
-
1463
- it('should emit handleRead', () => {
1464
- const warningCallback = sinon.spy();
1465
- const emit = sinon.spy();
1466
-
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');
1478
- });
1479
- });
1480
-
1481
- describe('onHandleNotify', () => {
1482
- it('should emit warning', () => {
1483
- const warningCallback = sinon.spy();
1484
- noble.on('warning', warningCallback);
1485
-
1486
- noble._peripherals = {
1487
- };
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 } }
826
+ noble._peripherals.set('test-peripheral', peripheral);
827
+ noble._state = 'poweredOn';
828
+
829
+ // Mock the _onDisconnect method to verify it's called
830
+ const originalOnDisconnect = noble._onDisconnect;
831
+ noble._onDisconnect = jest.fn();
832
+
833
+ // Trigger state change to poweredOff
834
+ noble._onStateChange('poweredOff');
835
+
836
+ // Check if _onDisconnect was called for the peripheral
837
+ expect(noble._onDisconnect).toHaveBeenCalledWith('test-peripheral', 'cleanup');
838
+
839
+ // Restore original method
840
+ noble._onDisconnect = originalOnDisconnect;
841
+ });
842
+
843
+ test('should update peripheral state when cleaned up during poweredOff', () => {
844
+ // Setup a connected peripheral
845
+ const peripheral = {
846
+ id: 'test-peripheral',
847
+ state: 'connected',
848
+ emit: jest.fn()
1538
849
  };
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
- });
850
+ noble._peripherals.set('test-peripheral', peripheral);
851
+
852
+ // Call the cleanup method directly
853
+ noble._cleanupPeriperals('test-peripheral');
854
+
855
+ // Verify peripheral emitted disconnect event
856
+ expect(peripheral.emit).toHaveBeenCalledWith('disconnect', 'cleanup');
857
+
858
+ // Verify peripheral state was updated
859
+ expect(peripheral.state).toBe('disconnected');
860
+ });
861
+ });
862
+ });