@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,102 +1,227 @@
1
- const should = require('should');
2
- const proxyquire = require('proxyquire').noCallThru();
1
+ // Import EventEmitter to extend mock classes
3
2
  const { EventEmitter } = require('events');
4
3
 
5
- let chosenPlatform;
6
- let chosenRelease;
7
- const platform = () => chosenPlatform;
8
- const release = () => chosenRelease;
9
-
10
- class NobleMac {}
11
-
12
- class NobleWinrt {}
13
-
14
- const NobleMacImport = proxyquire('../../lib/mac/bindings', {
15
- 'node-gyp-build': () => ({ NobleMac })
16
- });
17
-
18
- const NobleWinrtImport = proxyquire('../../lib/win/bindings', {
19
- 'node-gyp-build': () => ({ NobleWinrt })
20
- });
21
-
22
- const WebSocket = require('../../lib/websocket/bindings');
23
- const NobleBindings = proxyquire('../../lib/distributed/bindings', {
24
- ws: { Server: EventEmitter }
25
- });
26
- const HciNobleBindings = proxyquire('../../lib/hci-socket/bindings', {
27
- './hci': EventEmitter
28
- });
29
- const resolver = proxyquire('../../lib/resolve-bindings', {
30
- './distributed/bindings': NobleBindings,
31
- './hci-socket/bindings': HciNobleBindings,
32
- './mac/bindings': NobleMacImport,
33
- './win/bindings': NobleWinrtImport,
34
- os: { platform, release }
35
- });
4
+ // Mock classes
5
+ class MockNoble extends EventEmitter {}
6
+ class MockHciBindings extends EventEmitter {}
7
+ class MockMacBindings extends EventEmitter {}
8
+ class MockWinBindings extends EventEmitter {}
9
+ class MockNobleClass {
10
+ constructor(bindings) {
11
+ this.bindings = bindings;
12
+ }
13
+ }
14
+
15
+ // Mock platform data
16
+ let mockPlatform;
17
+ let mockRelease;
18
+
19
+ // Mock os module
20
+ jest.mock('os', () => ({
21
+ platform: () => mockPlatform,
22
+ release: () => mockRelease
23
+ }));
24
+
25
+ // Mock the various binding modules
26
+ jest.mock('../../lib/hci-socket/bindings', () => MockHciBindings, { virtual: true });
27
+ jest.mock('../../lib/mac/bindings', () => MockMacBindings, { virtual: true });
28
+ jest.mock('../../lib/win/bindings', () => MockWinBindings, { virtual: true });
29
+ jest.mock('../../lib/noble', () => MockNobleClass, { virtual: true });
30
+
31
+ // Mock node-gyp-build
32
+ jest.mock('node-gyp-build', () => () => ({
33
+ NobleMac: MockMacBindings,
34
+ NobleWinrt: MockWinBindings
35
+ }), { virtual: true });
36
+
37
+ // Import the module under test after mocks are set up
38
+ let resolver;
36
39
 
37
40
  describe('resolve-bindings', () => {
38
41
  const OLD_ENV = process.env;
39
42
 
40
43
  beforeEach(() => {
44
+ // Reset modules before each test to ensure fresh mocks
45
+ jest.resetModules();
46
+
41
47
  // Clone initial environment
42
- process.env = Object.assign({}, OLD_ENV);
48
+ process.env = { ...OLD_ENV };
49
+
50
+ // Import the module under test after mocks are set up
51
+ resolver = require('../../lib/resolve-bindings');
43
52
  });
44
53
 
45
54
  afterEach(() => {
46
55
  // Restore initial environment
47
56
  process.env = OLD_ENV;
57
+
58
+ // Clear all mocks
59
+ jest.clearAllMocks();
48
60
  });
49
61
 
50
- it('web socket', () => {
51
- process.env.NOBLE_WEBSOCKET = true;
52
-
53
- const bindings = resolver({});
54
- should(bindings).instanceof(WebSocket);
55
- });
56
-
57
- it('distributed', () => {
58
- process.env.NOBLE_DISTRIBUTED = true;
59
-
60
- const bindings = resolver({});
61
- should(bindings).instanceof(NobleBindings);
62
+ describe('default bindings', () => {
63
+ test('should use Mac bindings on macOS', () => {
64
+ mockPlatform = 'darwin';
65
+
66
+ const noble = resolver();
67
+ expect(noble).toBeInstanceOf(MockNobleClass);
68
+ expect(noble.bindings).toBeInstanceOf(MockMacBindings);
69
+ });
70
+
71
+ test('should use HCI bindings on Linux', () => {
72
+ mockPlatform = 'linux';
73
+
74
+ const noble = resolver();
75
+ expect(noble).toBeInstanceOf(MockNobleClass);
76
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
77
+ });
78
+
79
+ test('should use HCI bindings on FreeBSD', () => {
80
+ mockPlatform = 'freebsd';
81
+
82
+ const noble = resolver();
83
+ expect(noble).toBeInstanceOf(MockNobleClass);
84
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
85
+ });
86
+
87
+ test('should use Windows bindings on Windows 10 with BLE support', () => {
88
+ mockPlatform = 'win32';
89
+ mockRelease = '10.0.15063';
90
+
91
+ const noble = resolver();
92
+ expect(noble).toBeInstanceOf(MockNobleClass);
93
+ expect(noble.bindings).toBeInstanceOf(MockWinBindings);
94
+ });
95
+
96
+ test('should use HCI bindings on older Windows versions', () => {
97
+ mockPlatform = 'win32';
98
+ mockRelease = '6.3.9600'; // Windows 8.1
99
+
100
+ const noble = resolver();
101
+ expect(noble).toBeInstanceOf(MockNobleClass);
102
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
103
+ });
104
+
105
+ test('should throw error for unsupported platforms', () => {
106
+ expect(() => resolver('unknown')).toThrow('Unsupported binding type: unknown');
107
+ });
108
+
109
+ test('should use HCI bindings when BLUETOOTH_HCI_SOCKET_UART_PORT is set, regardless of platform', () => {
110
+ mockPlatform = 'darwin'; // Even on macOS
111
+ process.env.BLUETOOTH_HCI_SOCKET_UART_PORT = '/dev/ttyUSB0';
112
+
113
+ const noble = resolver();
114
+ expect(noble).toBeInstanceOf(MockNobleClass);
115
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
116
+ });
117
+
118
+ test('should use HCI bindings when BLUETOOTH_HCI_SOCKET_FORCE_UART is set', () => {
119
+ mockPlatform = 'darwin';
120
+ process.env.BLUETOOTH_HCI_SOCKET_FORCE_UART = 'true';
121
+
122
+ const noble = resolver();
123
+ expect(noble).toBeInstanceOf(MockNobleClass);
124
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
125
+ });
126
+
127
+ test('should use HCI bindings when USB VID and PID are set', () => {
128
+ mockPlatform = 'darwin'; // Even on macOS
129
+ process.env.BLUETOOTH_HCI_SOCKET_USB_VID = '0x0483';
130
+ process.env.BLUETOOTH_HCI_SOCKET_USB_PID = '0x5740';
131
+
132
+ const noble = resolver();
133
+ expect(noble).toBeInstanceOf(MockNobleClass);
134
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
135
+ });
136
+
137
+ test('should pass options to bindings', () => {
138
+ mockPlatform = 'darwin';
139
+ const options = { testOption: true };
140
+
141
+ const noble = resolver('default', options);
142
+ expect(noble).toBeInstanceOf(MockNobleClass);
143
+ expect(noble.bindings).toBeInstanceOf(MockMacBindings);
144
+ // Would need to enhance mock to verify options are passed through
145
+ });
62
146
  });
63
147
 
64
- it('mac', () => {
65
- chosenPlatform = 'darwin';
66
-
67
- const bindings = resolver({});
68
- should(bindings).instanceof(NobleMac);
69
- });
70
-
71
- it('linux', () => {
72
- chosenPlatform = 'linux';
73
-
74
- const bindings = resolver({});
75
- should(bindings).instanceof(HciNobleBindings);
148
+ describe('explicit bindings', () => {
149
+ test('should load HCI bindings when explicitly specified', () => {
150
+ const noble = resolver('hci');
151
+ expect(noble).toBeInstanceOf(MockNobleClass);
152
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
153
+ });
154
+
155
+ test('should load Mac bindings when explicitly specified', () => {
156
+ const noble = resolver('mac');
157
+ expect(noble).toBeInstanceOf(MockNobleClass);
158
+ expect(noble.bindings).toBeInstanceOf(MockMacBindings);
159
+ });
160
+
161
+ test('should load Windows bindings when explicitly specified', () => {
162
+ mockRelease = '10.0.15063';
163
+ const noble = resolver('win');
164
+ expect(noble).toBeInstanceOf(MockNobleClass);
165
+ expect(noble.bindings).toBeInstanceOf(MockWinBindings);
166
+ });
167
+
168
+ test('should throw error for unsupported binding type', () => {
169
+ expect(() => resolver('unsupported')).toThrow('Unsupported binding type: unsupported');
170
+ });
171
+
172
+ test('should pass options to explicitly specified bindings', () => {
173
+ const options = { testOption: true };
174
+
175
+ const noble = resolver('hci', options);
176
+ expect(noble).toBeInstanceOf(MockNobleClass);
177
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
178
+ // Would need to enhance mock to verify options are passed through
179
+ });
76
180
  });
77
181
 
78
- it('freebsd', () => {
79
- chosenPlatform = 'freebsd';
80
-
81
- const bindings = resolver({});
82
- should(bindings).instanceof(HciNobleBindings);
83
- });
84
-
85
- it('win32', () => {
86
- chosenPlatform = 'win32';
87
- chosenRelease = '10.0.22000';
88
-
89
- const bindings = resolver({});
90
- should(bindings).instanceof(NobleWinrt);
91
- });
92
-
93
- it('unknwon', () => {
94
- chosenPlatform = 'unknwon';
95
-
96
- try {
97
- resolver({});
98
- } catch (e) {
99
- should(e).have.property('message', 'Unsupported platform');
100
- }
182
+ describe('Windows version detection', () => {
183
+ beforeEach(() => {
184
+ mockPlatform = 'win32';
185
+ });
186
+
187
+ test('should use WinRT bindings on Windows 10 with minimum required version', () => {
188
+ mockRelease = '10.0.15063'; // Exactly the minimum version
189
+
190
+ const noble = resolver();
191
+ expect(noble).toBeInstanceOf(MockNobleClass);
192
+ expect(noble.bindings).toBeInstanceOf(MockWinBindings);
193
+ });
194
+
195
+ test('should use WinRT bindings on Windows 10 with higher version', () => {
196
+ mockRelease = '10.0.19042'; // Later Windows 10 version
197
+
198
+ const noble = resolver();
199
+ expect(noble).toBeInstanceOf(MockNobleClass);
200
+ expect(noble.bindings).toBeInstanceOf(MockWinBindings);
201
+ });
202
+
203
+ test('should use WinRT bindings on Windows 11', () => {
204
+ mockRelease = '11.0.22621';
205
+
206
+ const noble = resolver();
207
+ expect(noble).toBeInstanceOf(MockNobleClass);
208
+ expect(noble.bindings).toBeInstanceOf(MockWinBindings);
209
+ });
210
+
211
+ test('should use HCI bindings on Windows 10 with earlier version', () => {
212
+ mockRelease = '10.0.10240'; // Early Windows 10 without proper BLE support
213
+
214
+ const noble = resolver();
215
+ expect(noble).toBeInstanceOf(MockNobleClass);
216
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
217
+ });
218
+
219
+ test('should use HCI bindings on Windows 8.1', () => {
220
+ mockRelease = '6.3.9600';
221
+
222
+ const noble = resolver();
223
+ expect(noble).toBeInstanceOf(MockNobleClass);
224
+ expect(noble.bindings).toBeInstanceOf(MockHciBindings);
225
+ });
101
226
  });
102
- });
227
+ });
@@ -1,8 +1,3 @@
1
- const should = require('should');
2
- const sinon = require('sinon');
3
-
4
- const { assert } = sinon;
5
-
6
1
  const Service = require('../../lib/service');
7
2
 
8
3
  describe('service', () => {
@@ -13,183 +8,179 @@ describe('service', () => {
13
8
  let service = null;
14
9
 
15
10
  beforeEach(() => {
16
- mockNoble = {};
11
+ mockNoble = {
12
+ discoverIncludedServices: jest.fn(),
13
+ discoverCharacteristics: jest.fn(),
14
+ _withDisconnectHandler: (id, operation) => {
15
+ return operation();
16
+ }
17
+ };
17
18
 
18
19
  service = new Service(mockNoble, mockPeripheralId, mockUuid);
19
20
  });
20
21
 
21
- it('should have a uuid', () => {
22
- should(service.uuid).equal(mockUuid);
22
+ afterEach(() => {
23
+ jest.clearAllMocks();
23
24
  });
24
25
 
25
- it('should lookup name and type by uuid', () => {
26
+ test('should have a uuid', () => {
27
+ expect(service.uuid).toEqual(mockUuid);
28
+ });
29
+
30
+ test('should lookup name and type by uuid', () => {
26
31
  service = new Service(mockNoble, mockPeripheralId, '1800');
27
32
 
28
- should(service.name).equal('Generic Access');
29
- should(service.type).equal('org.bluetooth.service.generic_access');
33
+ expect(service.name).toEqual('Generic Access');
34
+ expect(service.type).toEqual('org.bluetooth.service.generic_access');
30
35
  });
31
36
 
32
37
  describe('toString', () => {
33
- it('should be uuid, name, type, includedServiceUuids', () => {
34
- should(service.toString()).equal('{"uuid":"mock-uuid","name":null,"type":null,"includedServiceUuids":null}');
38
+ test('should be uuid, name, type, includedServiceUuids', () => {
39
+ expect(service.toString()).toEqual('{"uuid":"mock-uuid","name":null,"type":null,"includedServiceUuids":null}');
35
40
  });
36
41
  });
37
42
 
38
43
  describe('discoverIncludedServices', () => {
39
- beforeEach(() => {
40
- mockNoble.discoverIncludedServices = sinon.spy();
41
- });
42
-
43
- afterEach(() => {
44
- sinon.reset();
45
- });
46
-
47
- it('should delegate to noble', () => {
44
+ test('should delegate to noble', () => {
48
45
  service.discoverIncludedServices();
49
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, undefined);
46
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
47
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
50
48
  });
51
49
 
52
- it('should delegate to noble, with uuids', () => {
50
+ test('should delegate to noble, with uuids', () => {
53
51
  const mockUuids = [];
54
52
  service.discoverIncludedServices(mockUuids);
55
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, mockUuids);
53
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, mockUuids);
54
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
56
55
  });
57
56
 
58
- it('should callback', () => {
59
- const callback = sinon.spy();
57
+ test('should callback', () => {
58
+ const callback = jest.fn();
60
59
 
61
60
  service.discoverIncludedServices(null, callback);
62
61
  service.emit('includedServicesDiscover');
63
62
 
64
- assert.calledOnceWithExactly(callback, null, undefined);
65
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, null);
63
+ expect(callback).toHaveBeenCalledWith(undefined, undefined);
64
+ expect(callback).toHaveBeenCalledTimes(1);
65
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, null);
66
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
66
67
  });
67
68
 
68
- it('should callback with data', () => {
69
+ test('should callback with data', () => {
69
70
  const mockIncludedServiceUuids = ['service1'];
70
- const callback = sinon.spy();
71
+ const callback = jest.fn();
71
72
 
72
73
  service.discoverIncludedServices(null, callback);
73
74
  service.emit('includedServicesDiscover', mockIncludedServiceUuids);
74
75
 
75
- assert.calledOnceWithExactly(callback, null, mockIncludedServiceUuids);
76
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, null);
76
+ expect(callback).toHaveBeenCalledWith(undefined, mockIncludedServiceUuids);
77
+ expect(callback).toHaveBeenCalledTimes(1);
78
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, null);
79
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
77
80
  });
78
81
  });
79
82
 
80
83
  describe('discoverIncludedServicesAsync', () => {
81
- beforeEach(() => {
82
- mockNoble.discoverIncludedServices = sinon.spy();
83
- });
84
-
85
- afterEach(() => {
86
- sinon.reset();
87
- });
88
-
89
- it('should delegate to noble', async () => {
84
+ test('should delegate to noble', async () => {
90
85
  const promise = service.discoverIncludedServicesAsync();
91
86
  service.emit('includedServicesDiscover');
92
87
 
93
- should(promise).resolvedWith(undefined);
94
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, undefined);
88
+ await expect(promise).resolves.toBeUndefined();
89
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
90
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
95
91
  });
96
92
 
97
- it('should delegate to noble, with uuids', async () => {
93
+ test('should delegate to noble, with uuids', async () => {
98
94
  const mockUuids = [];
99
95
  const promise = service.discoverIncludedServicesAsync(mockUuids);
100
96
  service.emit('includedServicesDiscover');
101
97
 
102
- should(promise).resolvedWith(undefined);
103
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, mockUuids);
98
+ await expect(promise).resolves.toBeUndefined();
99
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, mockUuids);
100
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
104
101
  });
105
102
 
106
- it('should resolve with data', async () => {
103
+ test('should resolve with data', async () => {
107
104
  const mockIncludedServiceUuids = ['service1'];
108
105
 
109
106
  const promise = service.discoverIncludedServicesAsync();
110
107
  service.emit('includedServicesDiscover', mockIncludedServiceUuids);
111
108
 
112
- should(promise).resolvedWith(mockIncludedServiceUuids);
113
- assert.calledOnceWithExactly(mockNoble.discoverIncludedServices, mockPeripheralId, mockUuid, undefined);
109
+ await expect(promise).resolves.toEqual(mockIncludedServiceUuids);
110
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
111
+ expect(mockNoble.discoverIncludedServices).toHaveBeenCalledTimes(1);
114
112
  });
115
113
  });
116
114
 
117
115
  describe('discoverCharacteristics', () => {
118
- beforeEach(() => {
119
- mockNoble.discoverCharacteristics = sinon.spy();
120
- });
121
-
122
- afterEach(() => {
123
- sinon.reset();
124
- });
125
-
126
- it('should delegate to noble', () => {
116
+ test('should delegate to noble', () => {
127
117
  service.discoverCharacteristics();
128
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, undefined);
118
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
119
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
129
120
  });
130
121
 
131
- it('should delegate to noble, with uuids', () => {
122
+ test('should delegate to noble, with uuids', () => {
132
123
  const mockUuids = [];
133
124
  service.discoverCharacteristics(mockUuids);
134
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, mockUuids);
125
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, mockUuids);
126
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
135
127
  });
136
128
 
137
- it('should callback', () => {
138
- const callback = sinon.spy();
129
+ test('should callback', () => {
130
+ const callback = jest.fn();
139
131
 
140
132
  service.discoverCharacteristics(null, callback);
141
133
  service.emit('characteristicsDiscover');
142
134
 
143
- assert.calledOnceWithExactly(callback, null, undefined);
144
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, null);
135
+ expect(callback).toHaveBeenCalledWith(undefined, undefined);
136
+ expect(callback).toHaveBeenCalledTimes(1);
137
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, null);
138
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
145
139
  });
146
140
 
147
- it('should callback with data', () => {
141
+ test('should callback with data', () => {
148
142
  const mockCharacteristics = [];
149
- const callback = sinon.spy();
143
+ const callback = jest.fn();
150
144
 
151
145
  service.discoverCharacteristics(null, callback);
152
146
  service.emit('characteristicsDiscover', mockCharacteristics);
153
147
 
154
- assert.calledOnceWithExactly(callback, null, mockCharacteristics);
155
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, null);
148
+ expect(callback).toHaveBeenCalledWith(undefined, mockCharacteristics);
149
+ expect(callback).toHaveBeenCalledTimes(1);
150
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, null);
151
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
156
152
  });
157
153
  });
158
154
 
159
155
  describe('discoverCharacteristicsAsync', () => {
160
- beforeEach(() => {
161
- mockNoble.discoverCharacteristics = sinon.spy();
162
- });
163
-
164
- afterEach(() => {
165
- sinon.reset();
166
- });
167
-
168
- it('should delegate to noble', async () => {
156
+ test('should delegate to noble', async () => {
169
157
  const promise = service.discoverCharacteristicsAsync();
170
158
  service.emit('characteristicsDiscover');
171
159
 
172
- should(promise).resolvedWith(undefined);
173
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, undefined);
160
+ await expect(promise).resolves.toBeUndefined();
161
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
162
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
174
163
  });
175
164
 
176
- it('should delegate to noble, with uuids', async () => {
165
+ test('should delegate to noble, with uuids', async () => {
177
166
  const mockUuids = [];
178
167
  const promise = service.discoverCharacteristicsAsync(mockUuids);
179
168
  service.emit('characteristicsDiscover');
180
169
 
181
- should(promise).resolvedWith(undefined);
182
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, mockUuids);
170
+ await expect(promise).resolves.toBeUndefined();
171
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, mockUuids);
172
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
183
173
  });
184
174
 
185
- it('should resolve with data', async () => {
175
+ test('should resolve with data', async () => {
186
176
  const mockCharacteristics = [];
187
177
 
188
178
  const promise = service.discoverCharacteristicsAsync();
189
179
  service.emit('characteristicsDiscover', mockCharacteristics);
190
180
 
191
- should(promise).resolvedWith(mockCharacteristics);
192
- assert.calledOnceWithExactly(mockNoble.discoverCharacteristics, mockPeripheralId, mockUuid, undefined);
181
+ await expect(promise).resolves.toEqual(mockCharacteristics);
182
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledWith(mockPeripheralId, mockUuid, undefined);
183
+ expect(mockNoble.discoverCharacteristics).toHaveBeenCalledTimes(1);
193
184
  });
194
185
  });
195
- });
186
+ });