@neurodevs/node-lsl 17.1.1 → 18.1.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 (198) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.vscode/launch.json +54 -57
  3. package/.vscode/settings.json +61 -66
  4. package/.vscode/tasks.json +98 -129
  5. package/README.md +20 -44
  6. package/build/__tests__/AbstractPackageTest.d.ts +7 -5
  7. package/build/__tests__/AbstractPackageTest.js +22 -15
  8. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  9. package/build/__tests__/impl/BleDeviceController.test.d.ts +54 -0
  10. package/build/__tests__/impl/BleDeviceController.test.js +333 -0
  11. package/build/__tests__/impl/BleDeviceController.test.js.map +1 -0
  12. package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
  13. package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
  14. package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
  15. package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
  16. package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
  17. package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
  18. package/build/__tests__/impl/LslStreamInlet.test.d.ts +20 -8
  19. package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
  20. package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
  21. package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
  22. package/build/__tests__/impl/LslStreamOutlet.test.js +40 -50
  23. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  24. package/build/__tests__/impl/LslWebSocketBridge.test.js +19 -20
  25. package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
  26. package/build/assertions.d.ts +1 -1
  27. package/build/assertions.js.map +1 -1
  28. package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
  29. package/build/impl/LslEventMarkerEmitter.js +86 -0
  30. package/build/impl/LslEventMarkerEmitter.js.map +1 -0
  31. package/build/impl/LslStreamInfo.d.ts +4 -8
  32. package/build/impl/LslStreamInfo.js +8 -21
  33. package/build/impl/LslStreamInfo.js.map +1 -1
  34. package/build/impl/LslStreamInlet.d.ts +31 -50
  35. package/build/impl/LslStreamInlet.js +79 -149
  36. package/build/impl/LslStreamInlet.js.map +1 -1
  37. package/build/impl/LslStreamOutlet.d.ts +15 -18
  38. package/build/impl/LslStreamOutlet.js +39 -47
  39. package/build/impl/LslStreamOutlet.js.map +1 -1
  40. package/build/impl/LslWebSocketBridge.d.ts +4 -5
  41. package/build/impl/LslWebSocketBridge.js +10 -10
  42. package/build/impl/LslWebSocketBridge.js.map +1 -1
  43. package/build/impl/controllers/BleDeviceController.d.ts +58 -0
  44. package/build/impl/controllers/BleDeviceController.js +145 -0
  45. package/build/impl/controllers/BleDeviceController.js.map +1 -0
  46. package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
  47. package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
  48. package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
  49. package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
  50. package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
  51. package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
  52. package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
  53. package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
  54. package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
  55. package/build/index.d.ts +14 -14
  56. package/build/index.js +16 -16
  57. package/build/index.js.map +1 -1
  58. package/build/scripts/discoverMuse.js +40 -0
  59. package/build/scripts/discoverMuse.js.map +1 -0
  60. package/build/scripts/finalizeHandles.d.ts +2 -0
  61. package/build/scripts/finalizeHandles.js +48 -0
  62. package/build/scripts/finalizeHandles.js.map +1 -0
  63. package/build/scripts/runLslEventMarkerEmitter.d.ts +1 -0
  64. package/build/scripts/runLslEventMarkerEmitter.js +11 -0
  65. package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
  66. package/build/scripts/runMuse.d.ts +1 -0
  67. package/build/scripts/runMuse.js +40 -0
  68. package/build/scripts/runMuse.js.map +1 -0
  69. package/build/scripts/runOutletToInlet.js +7 -6
  70. package/build/scripts/runOutletToInlet.js.map +1 -1
  71. package/build/scripts/testDestroyOutlet.d.ts +1 -0
  72. package/build/scripts/testDestroyOutlet.js +4 -0
  73. package/build/scripts/testDestroyOutlet.js.map +1 -0
  74. package/build/testDoubles/BleController/FakeBleController.d.ts +24 -0
  75. package/build/testDoubles/BleController/FakeBleController.js +42 -0
  76. package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
  77. package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
  78. package/build/testDoubles/BleController/SpyBleController.js +48 -0
  79. package/build/testDoubles/BleController/SpyBleController.js.map +1 -0
  80. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
  81. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
  82. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
  83. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
  84. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
  85. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
  86. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
  87. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
  88. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
  89. package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
  90. package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
  91. package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
  92. package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
  93. package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
  94. package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
  95. package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
  96. package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
  97. package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
  98. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
  99. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +8 -8
  100. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
  101. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
  102. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
  103. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
  104. package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
  105. package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
  106. package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
  107. package/build/testDoubles/generateRandomOutletOptions.js +1 -1
  108. package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
  109. package/build/validations.js +0 -2
  110. package/build/validations.js.map +1 -1
  111. package/eslint.config.js +3 -0
  112. package/package.json +27 -49
  113. package/prettier.config.js +3 -0
  114. package/src/__tests__/AbstractPackageTest.ts +38 -21
  115. package/src/__tests__/impl/BleDeviceController.test.ts +492 -0
  116. package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +323 -0
  117. package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
  118. package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
  119. package/src/__tests__/impl/LslStreamOutlet.test.ts +65 -73
  120. package/src/__tests__/impl/LslWebSocketBridge.test.ts +22 -21
  121. package/src/assertions.ts +2 -1
  122. package/src/impl/LslEventMarkerEmitter.ts +133 -0
  123. package/src/impl/LslStreamInfo.ts +17 -29
  124. package/src/impl/LslStreamInlet.ts +102 -215
  125. package/src/impl/LslStreamOutlet.ts +54 -78
  126. package/src/impl/LslWebSocketBridge.ts +14 -14
  127. package/src/impl/controllers/BleDeviceController.ts +223 -0
  128. package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
  129. package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
  130. package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
  131. package/src/index.ts +16 -16
  132. package/src/scripts/discoverMuse.ts +50 -0
  133. package/src/scripts/finalizeHandles.ts +63 -0
  134. package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
  135. package/src/scripts/runMuse.ts +50 -0
  136. package/src/scripts/runOutletToInlet.ts +10 -8
  137. package/src/scripts/testDestroyOutlet.ts +5 -0
  138. package/src/testDoubles/BleController/FakeBleController.ts +70 -0
  139. package/src/testDoubles/BleController/SpyBleController.ts +61 -0
  140. package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
  141. package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
  142. package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
  143. package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
  144. package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
  145. package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
  146. package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +15 -15
  147. package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
  148. package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
  149. package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
  150. package/src/validations.ts +0 -2
  151. package/tsconfig.json +23 -27
  152. package/build/.spruce/settings.json +0 -11
  153. package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
  154. package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
  155. package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
  156. package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
  157. package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
  158. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
  159. package/build/handleError.d.ts +0 -8
  160. package/build/handleError.js +0 -25
  161. package/build/handleError.js.map +0 -1
  162. package/build/impl/LiblslAdapter.d.ts +0 -154
  163. package/build/impl/LiblslAdapter.js +0 -317
  164. package/build/impl/LiblslAdapter.js.map +0 -1
  165. package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
  166. package/build/impl/LslEventMarkerOutlet.js +0 -63
  167. package/build/impl/LslEventMarkerOutlet.js.map +0 -1
  168. package/build/scripts/runLslEventMarkerOutlet.js +0 -18
  169. package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
  170. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
  171. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
  172. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
  173. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
  174. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
  175. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
  176. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
  177. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
  178. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
  179. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
  180. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
  181. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
  182. package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
  183. package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
  184. package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
  185. package/eslint.config.mjs +0 -3
  186. package/src/.spruce/settings.json +0 -11
  187. package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
  188. package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
  189. package/src/handleError.ts +0 -24
  190. package/src/impl/LiblslAdapter.ts +0 -543
  191. package/src/impl/LslEventMarkerOutlet.ts +0 -97
  192. package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
  193. package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
  194. package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
  195. package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
  196. package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
  197. package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
  198. /package/build/scripts/{runLslEventMarkerOutlet.d.ts → discoverMuse.d.ts} +0 -0
@@ -1,18 +1,14 @@
1
+ import {
2
+ FakeLiblsl,
3
+ FakeLibndx,
4
+ InfoHandle,
5
+ LiblslAdapter,
6
+ LibndxAdapter,
7
+ } from '@neurodevs/ndx-native'
1
8
  import AbstractModuleTest from '@neurodevs/node-tdd'
2
9
  import WebSocket, { Server } from 'ws'
3
10
 
4
- import LiblslAdapter from '../impl/LiblslAdapter.js'
5
- import LslEventMarkerOutlet from '../impl/LslEventMarkerOutlet.js'
6
- import LslStreamInfo from '../impl/LslStreamInfo.js'
7
- import LslStreamInlet, {
8
- OnDataCallback,
9
- StreamInletOptions,
10
- } from '../impl/LslStreamInlet.js'
11
- import LslStreamOutlet from '../impl/LslStreamOutlet.js'
12
- import LslWebSocketBridge from '../impl/LslWebSocketBridge.js'
13
-
14
- import SpyEventMarkerOutlet from '../testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js'
15
- import FakeLiblsl from '../testDoubles/Liblsl/FakeLiblsl.js'
11
+ import SpyEventMarkerEmitter from '../testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
16
12
  import FakeStreamInfo from '../testDoubles/StreamInfo/FakeStreamInfo.js'
17
13
  import SpyStreamInfo from '../testDoubles/StreamInfo/SpyStreamInfo.js'
18
14
  import FakeStreamInlet from '../testDoubles/StreamInlet/FakeStreamInlet.js'
@@ -22,8 +18,19 @@ import SpyLslWebSocketBridge from '../testDoubles/WebSocketBridge/SpyLslWebSocke
22
18
  import FakeWebSocket from '../testDoubles/WebSockets/FakeWebSocket.js'
23
19
  import FakeWebSocketServer from '../testDoubles/WebSockets/FakeWebSocketServer.js'
24
20
 
21
+ import LslWebSocketBridge from '../impl/LslWebSocketBridge.js'
22
+ import BleDeviceController from '../impl/controllers/BleDeviceController.js'
23
+ import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
24
+ import LslStreamInfo from '../impl/LslStreamInfo.js'
25
+ import LslStreamInlet, {
26
+ OnDataCallback,
27
+ StreamInletOptions,
28
+ } from '../impl/LslStreamInlet.js'
29
+ import LslStreamOutlet from '../impl/LslStreamOutlet.js'
30
+
25
31
  export default class AbstractPackageTest extends AbstractModuleTest {
26
32
  protected static fakeLiblsl: FakeLiblsl
33
+ protected static fakeLibndx: FakeLibndx
27
34
 
28
35
  protected static async beforeEach() {
29
36
  await super.beforeEach()
@@ -34,6 +41,17 @@ export default class AbstractPackageTest extends AbstractModuleTest {
34
41
  LiblslAdapter.setInstance(this.fakeLiblsl)
35
42
 
36
43
  FakeLiblsl.fakeErrorCode = 0
44
+ FakeLiblsl.fakeInfoHandles = [{} as InfoHandle]
45
+ }
46
+
47
+ protected static setFakeLibndx() {
48
+ this.fakeLibndx = new FakeLibndx()
49
+ LibndxAdapter.setInstance(this.fakeLibndx)
50
+
51
+ FakeLibndx.resetTestDouble()
52
+ FakeLibndx.fakeResult = { status: 200 }
53
+
54
+ BleDeviceController.ndx = this.fakeLibndx
37
55
  }
38
56
 
39
57
  protected static setSpyStreamInfo() {
@@ -60,8 +78,8 @@ export default class AbstractPackageTest extends AbstractModuleTest {
60
78
  FakeStreamOutlet.resetTestDouble()
61
79
  }
62
80
 
63
- protected static setSpyEventMarkerOutlet() {
64
- LslEventMarkerOutlet.Class = SpyEventMarkerOutlet
81
+ protected static setSpyEventMarkerEmitter() {
82
+ LslEventMarkerEmitter.Class = SpyEventMarkerEmitter
65
83
  }
66
84
 
67
85
  protected static setSpyLslWebSocketBridge() {
@@ -78,7 +96,8 @@ export default class AbstractPackageTest extends AbstractModuleTest {
78
96
  FakeWebSocketServer.resetTestDouble()
79
97
  }
80
98
 
81
- protected static readonly info = new FakeStreamInfo()
99
+ protected static readonly fakeStreamInfo = new FakeStreamInfo()
100
+
82
101
  protected static readonly name_ = this.generateId()
83
102
  protected static readonly type = this.generateId()
84
103
  protected static readonly sourceId = this.generateId()
@@ -90,9 +109,7 @@ export default class AbstractPackageTest extends AbstractModuleTest {
90
109
  this.generateId(),
91
110
  ]
92
111
 
93
- protected static get channelCount() {
94
- return this.channelNames.length
95
- }
112
+ protected static readonly channelCount = this.channelNames.length
96
113
 
97
114
  protected static readonly chunkSize = 2
98
115
  protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
@@ -102,12 +119,12 @@ export default class AbstractPackageTest extends AbstractModuleTest {
102
119
  options: Partial<StreamInletOptions>,
103
120
  onData: OnDataCallback
104
121
  ) {
105
- const defaultOptions = {
106
- info: this.info,
122
+ const defaultOptions: StreamInletOptions = {
123
+ sourceId: this.sourceId,
107
124
  chunkSize: this.chunkSize,
108
125
  maxBufferedMs: this.maxBufferedMs,
109
126
  ...options,
110
- } as StreamInletOptions
127
+ }
111
128
 
112
129
  return LslStreamInlet.Create(defaultOptions, onData)
113
130
  }
@@ -0,0 +1,492 @@
1
+ import { randomInt } from 'node:crypto'
2
+
3
+ import { test, assert } from '@neurodevs/node-tdd'
4
+ import { FakeLibndx, NativePeripheral } from '@neurodevs/ndx-native'
5
+
6
+ import SpyBleController from '../../testDoubles/BleController/SpyBleController.js'
7
+ import AbstractPackageTest from '../AbstractPackageTest.js'
8
+ import BleDeviceController, {
9
+ BleControllerOptions,
10
+ } from '../../impl/controllers/BleDeviceController.js'
11
+
12
+ export default class BleDeviceControllerTest extends AbstractPackageTest {
13
+ private static instance: SpyBleController
14
+
15
+ private static readonly uuid = this.generateId()
16
+ private static readonly namePrefix = this.generateId()
17
+ private static readonly discoveredUuid = this.generateId()
18
+ private static readonly charUuid = this.generateId()
19
+ private static readonly charValueToWrite = this.generateId()
20
+ private static readonly rssiIntervalMs = randomInt(1, 5)
21
+ private static readonly fakeError = this.generateId()
22
+ private static readonly fake400Error = `400 error: ${this.fakeError}`
23
+ private static readonly fake500Error = `500 error: ${this.fakeError}`
24
+
25
+ private static readonly charCallbacks = [
26
+ {
27
+ charUuid: this.generateId(),
28
+ charName: this.generateId(),
29
+ onData: async () => {},
30
+ },
31
+ {
32
+ charUuid: this.generateId(),
33
+ charName: this.generateId(),
34
+ onData: async () => {},
35
+ },
36
+ ]
37
+
38
+ private static onConnected = (_peripheral: NativePeripheral) => {
39
+ this.wasConnected = true
40
+ }
41
+
42
+ private static wasConnected: boolean
43
+
44
+ private static nativePeripheral: NativePeripheral = {
45
+ uuid: this.generateId(),
46
+ name: this.generateId(),
47
+ }
48
+
49
+ protected static async beforeAll() {
50
+ assert.isEqual(
51
+ BleDeviceController.waitAfterMs,
52
+ 1000,
53
+ 'Set incorrect waitAfterMs!'
54
+ )
55
+ }
56
+
57
+ protected static async beforeEach() {
58
+ await super.beforeEach()
59
+
60
+ BleDeviceController.waitAfterMs = 0
61
+
62
+ this.setFakeLibndx()
63
+ BleDeviceController.Class = SpyBleController
64
+
65
+ this.wasConnected = false
66
+
67
+ this.instance = await this.BleController()
68
+ }
69
+
70
+ @test()
71
+ protected static async createsInstance() {
72
+ assert.isTruthy(this.instance, 'Failed to create instance!')
73
+ }
74
+
75
+ @test()
76
+ protected static async connectCallsLibndxCreateBleBackend() {
77
+ await this.connect()
78
+
79
+ assert.isEqualDeep(
80
+ FakeLibndx.callsToCreateBleBackend[0],
81
+ {
82
+ deviceUuid: this.uuid,
83
+ },
84
+ 'Did not call createBleBackend!'
85
+ )
86
+ }
87
+
88
+ @test()
89
+ protected static async discoversUuidWhenDeviceUuidNotProvided() {
90
+ const instance = await this.BleControllerWithPrefix()
91
+
92
+ await this.connectWithDiscovery(instance)
93
+
94
+ const call = FakeLibndx.callsToDiscoverBleUuid[0]
95
+
96
+ assert.isEqual(
97
+ call?.namePrefix,
98
+ this.namePrefix,
99
+ 'Did not call discoverBleUuid with deviceNamePrefix!'
100
+ )
101
+
102
+ assert.isFunction(
103
+ call?.onDiscovered,
104
+ 'Did not pass an onDiscovered callback to discoverBleUuid!'
105
+ )
106
+ }
107
+
108
+ @test()
109
+ protected static async doesNotDiscoverUuidWhenDeviceUuidProvided() {
110
+ await this.connect()
111
+
112
+ assert.isEqual(
113
+ FakeLibndx.callsToDiscoverBleUuid.length,
114
+ 0,
115
+ 'Should not call discoverBleUuid when deviceUuid is provided!'
116
+ )
117
+ }
118
+
119
+ @test()
120
+ protected static async usesDiscoveredUuidToCreateBleBackend() {
121
+ const instance = await this.BleControllerWithPrefix()
122
+
123
+ await this.connectWithDiscovery(instance)
124
+
125
+ assert.isEqualDeep(
126
+ FakeLibndx.callsToCreateBleBackend[0],
127
+ {
128
+ deviceUuid: this.discoveredUuid,
129
+ },
130
+ 'Did not create BLE backend with the discovered uuid!'
131
+ )
132
+ }
133
+
134
+ @test()
135
+ protected static async usesDiscoveredUuidToStartBleBackend() {
136
+ const instance = await this.BleControllerWithPrefix()
137
+
138
+ await this.connectWithDiscovery(instance)
139
+
140
+ assert.isEqual(
141
+ FakeLibndx.callsToStartBleBackend[0]?.deviceUuid,
142
+ this.discoveredUuid,
143
+ 'Did not start BLE backend with the discovered uuid!'
144
+ )
145
+ }
146
+
147
+ @test()
148
+ protected static async exposesDiscoveredUuid() {
149
+ const instance = await this.BleControllerWithPrefix()
150
+
151
+ await this.connectWithDiscovery(instance)
152
+
153
+ assert.isEqual(
154
+ instance.uuid,
155
+ this.discoveredUuid,
156
+ 'Did not expose the discovered uuid!'
157
+ )
158
+ }
159
+
160
+ @test()
161
+ protected static async createBleBackendThrowsOn400() {
162
+ this.setFake400Error()
163
+
164
+ await assert.doesThrowAsync(
165
+ async () => await this.instance.connect(),
166
+ this.fake400Error,
167
+ 'Did not throw error!'
168
+ )
169
+ }
170
+
171
+ @test()
172
+ protected static async createBleBackendThrowsOn500() {
173
+ this.setFake500Error()
174
+
175
+ await assert.doesThrowAsync(
176
+ async () => await this.instance.connect(),
177
+ this.fake500Error,
178
+ 'Did not throw error!'
179
+ )
180
+ }
181
+
182
+ @test()
183
+ protected static async connectCallsLibndxStartBleBackend() {
184
+ await this.connect()
185
+
186
+ const call = FakeLibndx.callsToStartBleBackend[0]
187
+
188
+ assert.isEqual(
189
+ call.deviceUuid,
190
+ this.uuid,
191
+ 'Did not call startBleBackend with correct deviceUuid!'
192
+ )
193
+
194
+ assert.isEqual(
195
+ call.charCallbacks.length,
196
+ 2,
197
+ 'Did not call startBleBackend with charCallbacks!'
198
+ )
199
+
200
+ let i = 0
201
+ for (const charCallback of call.charCallbacks) {
202
+ assert.isEqual(
203
+ charCallback.charUuid,
204
+ this.charCallbacks[i].charUuid,
205
+ 'Incorrect charUuid!'
206
+ )
207
+
208
+ assert.isEqual(
209
+ charCallback.charName,
210
+ this.charCallbacks[i].charName,
211
+ 'Incorrect charName!'
212
+ )
213
+
214
+ assert.isFunction(
215
+ charCallback.onData,
216
+ 'Callback is not a function!'
217
+ )
218
+ i++
219
+ }
220
+ }
221
+
222
+ @test()
223
+ protected static async startBleBackendThrowsOn400() {
224
+ //@ts-ignore
225
+ this.instance.createBleBackend = () => {}
226
+
227
+ this.setFake400Error()
228
+
229
+ await assert.doesThrowAsync(
230
+ async () => await this.instance.connect(),
231
+ this.fake400Error,
232
+ 'Did not throw error!'
233
+ )
234
+ }
235
+
236
+ @test()
237
+ protected static async startBleBackendThrowsOn500() {
238
+ //@ts-ignore
239
+ this.instance.createBleBackend = () => {}
240
+
241
+ this.setFake500Error()
242
+
243
+ await assert.doesThrowAsync(
244
+ async () => await this.instance.connect(),
245
+ this.fake500Error,
246
+ 'Did not throw error!'
247
+ )
248
+ }
249
+
250
+ @test()
251
+ protected static async connectWaitsForOnConnectedEvent() {
252
+ await this.connect()
253
+
254
+ assert.isTruthy(
255
+ this.wasConnected,
256
+ 'Did not wait for onConnected event!'
257
+ )
258
+ }
259
+
260
+ @test()
261
+ protected static async waitsAfterOnConnectedToDiscoverServices() {
262
+ const waitAfterMs = 20
263
+ BleDeviceController.waitAfterMs = waitAfterMs
264
+
265
+ const t0 = Date.now()
266
+ await this.connect()
267
+ const t1 = Date.now()
268
+
269
+ assert.isAbove(
270
+ t1 - t0,
271
+ 100 + waitAfterMs * 0.8,
272
+ 'Did not wait after on connected!'
273
+ )
274
+ }
275
+
276
+ @test()
277
+ protected static async writeCharacteristicCallsLibndxBinding() {
278
+ await this.writeCharacteristic()
279
+
280
+ assert.isEqualDeep(
281
+ FakeLibndx.callsToWriteBleCharacteristic[0],
282
+ {
283
+ deviceUuid: this.uuid,
284
+ charUuid: this.charUuid,
285
+ value: this.charValueToWrite,
286
+ },
287
+ 'Did not call writeBleCharacteristic as expected!'
288
+ )
289
+ }
290
+
291
+ @test()
292
+ protected static async writeCharacteristicThrowsOn400() {
293
+ this.setFake400Error()
294
+
295
+ await assert.doesThrowAsync(
296
+ async () => await this.writeCharacteristic(),
297
+ this.fake400Error,
298
+ 'Did not throw error!'
299
+ )
300
+ }
301
+
302
+ @test()
303
+ protected static async writeCharacteristicThrowsOn500() {
304
+ this.setFake500Error()
305
+
306
+ await assert.doesThrowAsync(
307
+ async () => await this.writeCharacteristic(),
308
+ this.fake500Error,
309
+ 'Did not throw error!'
310
+ )
311
+ }
312
+
313
+ @test()
314
+ protected static async callsSetBleRssiInterval() {
315
+ await this.connect()
316
+
317
+ const { deviceUuid, intervalMs } =
318
+ FakeLibndx.callsToSetBleRssiInterval[0]
319
+
320
+ assert.isEqualDeep(
321
+ { deviceUuid, intervalMs },
322
+ {
323
+ deviceUuid: this.uuid,
324
+ intervalMs: this.rssiIntervalMs,
325
+ },
326
+ 'Did not call setBleRssiInterval as expected!'
327
+ )
328
+ }
329
+
330
+ @test()
331
+ protected static async disconnectCallsLibndxStopBleBackend() {
332
+ await this.disconnect()
333
+
334
+ assert.isEqualDeep(
335
+ FakeLibndx.callsToStopBleBackend[0],
336
+ {
337
+ deviceUuid: this.uuid,
338
+ },
339
+ 'Did not call stopBleBackend!'
340
+ )
341
+ }
342
+
343
+ @test()
344
+ protected static async disconnectThrowsOn400() {
345
+ this.setFake400Error()
346
+
347
+ await assert.doesThrowAsync(
348
+ async () => await this.disconnect(),
349
+ this.fake400Error,
350
+ 'Did not throw error!'
351
+ )
352
+ }
353
+
354
+ @test()
355
+ protected static async disconnectThrowsOn500() {
356
+ this.setFake500Error()
357
+
358
+ await assert.doesThrowAsync(
359
+ async () => await this.disconnect(),
360
+ this.fake500Error,
361
+ 'Did not throw error!'
362
+ )
363
+ }
364
+
365
+ @test()
366
+ protected static async disconnectResetsConnectedFlag() {
367
+ await this.connect()
368
+ await this.disconnect()
369
+
370
+ assert.isFalse(
371
+ this.instance.getConnected(),
372
+ 'Did not reset connected flag on disconnect!'
373
+ )
374
+ }
375
+
376
+ @test()
377
+ protected static async exposesPeriperalName() {
378
+ await this.connect()
379
+
380
+ assert.isEqual(
381
+ this.instance.name,
382
+ this.nativePeripheral.name,
383
+ 'Did not set peripheral name!'
384
+ )
385
+ }
386
+
387
+ @test()
388
+ protected static async returnsNAIfNameNotAvailable() {
389
+ assert.isEqual(
390
+ this.instance.name,
391
+ 'N/A',
392
+ 'Did not set default name to N/A!'
393
+ )
394
+ }
395
+
396
+ @test()
397
+ protected static async throwsWithUnknownErrorIfNoError() {
398
+ this.setFake500ErrorWithoutError()
399
+
400
+ await assert.doesThrowAsync(
401
+ async () => await this.connect(),
402
+ 'Unknown error',
403
+ 'Did not throw error!'
404
+ )
405
+ }
406
+
407
+ private static async connect() {
408
+ const promise = this.instance.connect()
409
+
410
+ const startCall = FakeLibndx.callsToStartBleBackend[0]
411
+ startCall?.onConnected(this.nativePeripheral)
412
+
413
+ await promise
414
+ }
415
+
416
+ private static async connectWithDiscovery(instance: SpyBleController) {
417
+ const promise = instance.connect()
418
+
419
+ FakeLibndx.callsToDiscoverBleUuid[0]?.onDiscovered(this.discoveredUuid)
420
+
421
+ await this.waitForCall(() => FakeLibndx.callsToStartBleBackend[0])
422
+
423
+ FakeLibndx.callsToStartBleBackend[0]?.onConnected(this.nativePeripheral)
424
+
425
+ await promise
426
+ }
427
+
428
+ private static async waitForCall<T>(getCall: () => T) {
429
+ await new Promise<void>((resolve) => {
430
+ const check = () => {
431
+ if (getCall()) {
432
+ resolve()
433
+ } else {
434
+ setTimeout(check, 10)
435
+ }
436
+ }
437
+ check()
438
+ })
439
+ }
440
+
441
+ private static async writeCharacteristic() {
442
+ await this.instance.writeCharacteristic(
443
+ this.charUuid,
444
+ this.charValueToWrite
445
+ )
446
+ }
447
+
448
+ private static async disconnect() {
449
+ await this.instance.disconnect()
450
+ }
451
+
452
+ private static setFake400Error() {
453
+ FakeLibndx.fakeResult = {
454
+ status: 400,
455
+ error: this.fakeError,
456
+ }
457
+ }
458
+
459
+ private static setFake500Error() {
460
+ FakeLibndx.fakeResult = {
461
+ status: 500,
462
+ error: this.fakeError,
463
+ }
464
+ }
465
+
466
+ private static setFake500ErrorWithoutError() {
467
+ FakeLibndx.fakeResult = {
468
+ status: 500,
469
+ }
470
+ }
471
+
472
+ private static async BleController(
473
+ options?: Partial<BleControllerOptions>
474
+ ) {
475
+ return (await BleDeviceController.Create({
476
+ deviceUuid: this.uuid,
477
+ charCallbacks: this.charCallbacks,
478
+ onConnected: this.onConnected,
479
+ rssiIntervalMs: this.rssiIntervalMs,
480
+ ...options,
481
+ })) as SpyBleController
482
+ }
483
+
484
+ private static async BleControllerWithPrefix() {
485
+ return (await BleDeviceController.Create({
486
+ deviceNamePrefix: this.namePrefix,
487
+ charCallbacks: this.charCallbacks,
488
+ onConnected: this.onConnected,
489
+ rssiIntervalMs: this.rssiIntervalMs,
490
+ } as unknown as BleControllerOptions)) as SpyBleController
491
+ }
492
+ }