@neurodevs/node-lsl 18.0.0 → 19.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.
- package/.vscode/launch.json +54 -58
- package/.vscode/settings.json +61 -66
- package/.vscode/tasks.json +98 -129
- package/README.md +14 -12
- package/build/__tests__/AbstractPackageTest.d.ts +16 -12
- package/build/__tests__/AbstractPackageTest.js +48 -20
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/BleDeviceController.test.d.ts +59 -0
- package/build/__tests__/impl/BleDeviceController.test.js +364 -0
- package/build/__tests__/impl/BleDeviceController.test.js.map +1 -0
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js +1 -1
- package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.js +2 -2
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamOutlet.test.js +11 -13
- package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.js +3 -3
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
- package/build/__tests__/impl/UsbDeviceController.test.d.ts +17 -0
- package/build/__tests__/impl/UsbDeviceController.test.js +81 -0
- package/build/__tests__/impl/UsbDeviceController.test.js.map +1 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.d.ts +19 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.js +172 -0
- package/build/__tests__/impl/WindowedClockRegressor.test.js.map +1 -0
- package/build/impl/LslStreamInlet.d.ts +1 -0
- package/build/impl/LslStreamInlet.js +2 -1
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +3 -2
- package/build/impl/LslStreamOutlet.js +4 -3
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.js +2 -2
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/impl/WindowedClockRegressor.d.ts +24 -0
- package/build/impl/WindowedClockRegressor.js +73 -0
- package/build/impl/WindowedClockRegressor.js.map +1 -0
- package/build/impl/controllers/BleDeviceController.d.ts +60 -0
- package/build/impl/controllers/BleDeviceController.js +153 -0
- package/build/impl/controllers/BleDeviceController.js.map +1 -0
- package/build/impl/controllers/UsbDeviceController.d.ts +23 -0
- package/build/impl/controllers/UsbDeviceController.js +40 -0
- package/build/impl/controllers/UsbDeviceController.js.map +1 -0
- package/build/impl/workers/inlet/StreamInletWorker.d.ts +4 -4
- package/build/impl/workers/inlet/StreamInletWorker.js +12 -12
- package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -1
- package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +3 -3
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js +7 -7
- package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -1
- package/build/index.d.ts +14 -4
- package/build/index.js +17 -5
- package/build/index.js.map +1 -1
- package/build/scripts/discoverMuse.d.ts +1 -0
- package/build/scripts/discoverMuse.js +40 -0
- package/build/scripts/discoverMuse.js.map +1 -0
- package/build/scripts/runMuse.d.ts +1 -0
- package/build/scripts/runMuse.js +40 -0
- package/build/scripts/runMuse.js.map +1 -0
- package/build/scripts/runUsb.d.ts +1 -0
- package/build/scripts/runUsb.js +14 -0
- package/build/scripts/runUsb.js.map +1 -0
- package/build/testDoubles/BleController/FakeBleController.d.ts +26 -0
- package/build/testDoubles/BleController/FakeBleController.js +47 -0
- package/build/testDoubles/BleController/FakeBleController.js.map +1 -0
- package/build/testDoubles/BleController/SpyBleController.d.ts +14 -0
- package/build/testDoubles/BleController/SpyBleController.js +48 -0
- package/build/testDoubles/BleController/SpyBleController.js.map +1 -0
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.d.ts +17 -0
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.js +23 -0
- package/build/testDoubles/ClockRegressor/FakeClockRegressor.js.map +1 -0
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +2 -2
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +5 -2
- package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
- package/build/testDoubles/UsbController/FakeUsbController.d.ts +12 -0
- package/build/testDoubles/UsbController/FakeUsbController.js +25 -0
- package/build/testDoubles/UsbController/FakeUsbController.js.map +1 -0
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/build/testDoubles/generateRandomOutletOptions.js +1 -1
- package/build/testDoubles/generateRandomOutletOptions.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +19 -57
- package/prettier.config.js +3 -0
- package/src/__tests__/AbstractPackageTest.ts +86 -29
- package/src/__tests__/impl/BleDeviceController.test.ts +535 -0
- package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +2 -1
- package/src/__tests__/impl/LslStreamInlet.test.ts +2 -2
- package/src/__tests__/impl/LslStreamOutlet.test.ts +15 -14
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +4 -3
- package/src/__tests__/impl/UsbDeviceController.test.ts +109 -0
- package/src/__tests__/impl/WindowedClockRegressor.test.ts +262 -0
- package/src/impl/LslStreamInlet.ts +4 -1
- package/src/impl/LslStreamOutlet.ts +5 -4
- package/src/impl/LslWebSocketBridge.ts +2 -2
- package/src/impl/WindowedClockRegressor.ts +136 -0
- package/src/impl/controllers/BleDeviceController.ts +240 -0
- package/src/impl/controllers/UsbDeviceController.ts +65 -0
- package/src/impl/workers/inlet/StreamInletWorker.ts +12 -12
- package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +8 -8
- package/src/index.ts +24 -5
- package/src/scripts/discoverMuse.ts +50 -0
- package/src/scripts/runMuse.ts +50 -0
- package/src/scripts/runUsb.ts +20 -0
- package/src/testDoubles/BleController/FakeBleController.ts +81 -0
- package/src/testDoubles/BleController/SpyBleController.ts +61 -0
- package/src/testDoubles/ClockRegressor/FakeClockRegressor.ts +46 -0
- package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +6 -3
- package/src/testDoubles/UsbController/FakeUsbController.ts +34 -0
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -2
- package/src/testDoubles/generateRandomOutletOptions.ts +2 -1
- package/tsconfig.json +23 -27
- package/.regressionproof.json +0 -7
- package/build/.spruce/settings.json +0 -15
- package/build/__tests__/impl/LslBackpressureMonitor.test.d.ts +0 -7
- package/build/__tests__/impl/LslBackpressureMonitor.test.js +0 -26
- package/build/__tests__/impl/LslBackpressureMonitor.test.js.map +0 -1
- package/build/impl/LslBackpressureMonitor.d.ts +0 -8
- package/build/impl/LslBackpressureMonitor.js +0 -8
- package/build/impl/LslBackpressureMonitor.js.map +0 -1
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.d.ts +0 -6
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js +0 -10
- package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js.map +0 -1
- package/eslint.config.mjs +0 -3
- package/src/.spruce/settings.json +0 -15
- package/src/__tests__/impl/LslBackpressureMonitor.test.ts +0 -25
- package/src/impl/LslBackpressureMonitor.ts +0 -13
- package/src/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.ts +0 -13
|
@@ -0,0 +1,535 @@
|
|
|
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 readonly extraCharCallbacks = [
|
|
39
|
+
{
|
|
40
|
+
charUuid: this.generateId(),
|
|
41
|
+
charName: this.generateId(),
|
|
42
|
+
onData: async () => {},
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
private static onConnected = (_peripheral: NativePeripheral) => {
|
|
47
|
+
this.wasConnected = true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private static wasConnected: boolean
|
|
51
|
+
|
|
52
|
+
private static nativePeripheral: NativePeripheral = {
|
|
53
|
+
uuid: this.generateId(),
|
|
54
|
+
name: this.generateId(),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected static async beforeAll() {
|
|
58
|
+
assert.isEqual(
|
|
59
|
+
BleDeviceController.waitAfterMs,
|
|
60
|
+
1000,
|
|
61
|
+
'Set incorrect waitAfterMs!'
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected static async beforeEach() {
|
|
66
|
+
await super.beforeEach()
|
|
67
|
+
|
|
68
|
+
BleDeviceController.waitAfterMs = 0
|
|
69
|
+
BleDeviceController.Class = SpyBleController
|
|
70
|
+
|
|
71
|
+
this.wasConnected = false
|
|
72
|
+
|
|
73
|
+
this.instance = await this.BleController()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@test()
|
|
77
|
+
protected static async createsInstance() {
|
|
78
|
+
assert.isTruthy(this.instance, 'Failed to create instance!')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@test()
|
|
82
|
+
protected static async connectCallsLibndxCreateBleBackend() {
|
|
83
|
+
await this.connect()
|
|
84
|
+
|
|
85
|
+
assert.isEqualDeep(
|
|
86
|
+
FakeLibndx.callsToCreateBleBackend[0],
|
|
87
|
+
{
|
|
88
|
+
deviceUuid: this.uuid,
|
|
89
|
+
},
|
|
90
|
+
'Did not call createBleBackend!'
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@test()
|
|
95
|
+
protected static async discoversUuidWhenDeviceUuidNotProvided() {
|
|
96
|
+
const instance = await this.BleControllerWithPrefix()
|
|
97
|
+
|
|
98
|
+
await this.connectWithDiscovery(instance)
|
|
99
|
+
|
|
100
|
+
const call = FakeLibndx.callsToDiscoverBleUuid[0]
|
|
101
|
+
|
|
102
|
+
assert.isEqual(
|
|
103
|
+
call?.namePrefix,
|
|
104
|
+
this.namePrefix,
|
|
105
|
+
'Did not call discoverBleUuid with deviceNamePrefix!'
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
assert.isFunction(
|
|
109
|
+
call?.onDiscovered,
|
|
110
|
+
'Did not pass an onDiscovered callback to discoverBleUuid!'
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@test()
|
|
115
|
+
protected static async doesNotDiscoverUuidWhenDeviceUuidProvided() {
|
|
116
|
+
await this.connect()
|
|
117
|
+
|
|
118
|
+
assert.isEqual(
|
|
119
|
+
FakeLibndx.callsToDiscoverBleUuid.length,
|
|
120
|
+
0,
|
|
121
|
+
'Should not call discoverBleUuid when deviceUuid is provided!'
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@test()
|
|
126
|
+
protected static async usesDiscoveredUuidToCreateBleBackend() {
|
|
127
|
+
const instance = await this.BleControllerWithPrefix()
|
|
128
|
+
|
|
129
|
+
await this.connectWithDiscovery(instance)
|
|
130
|
+
|
|
131
|
+
assert.isEqualDeep(
|
|
132
|
+
FakeLibndx.callsToCreateBleBackend[0],
|
|
133
|
+
{
|
|
134
|
+
deviceUuid: this.discoveredUuid,
|
|
135
|
+
},
|
|
136
|
+
'Did not create BLE backend with the discovered uuid!'
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@test()
|
|
141
|
+
protected static async usesDiscoveredUuidToStartBleBackend() {
|
|
142
|
+
const instance = await this.BleControllerWithPrefix()
|
|
143
|
+
|
|
144
|
+
await this.connectWithDiscovery(instance)
|
|
145
|
+
|
|
146
|
+
assert.isEqual(
|
|
147
|
+
FakeLibndx.callsToStartBleBackend[0]?.deviceUuid,
|
|
148
|
+
this.discoveredUuid,
|
|
149
|
+
'Did not start BLE backend with the discovered uuid!'
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@test()
|
|
154
|
+
protected static async exposesDiscoveredUuid() {
|
|
155
|
+
const instance = await this.BleControllerWithPrefix()
|
|
156
|
+
|
|
157
|
+
await this.connectWithDiscovery(instance)
|
|
158
|
+
|
|
159
|
+
assert.isEqual(
|
|
160
|
+
instance.uuid,
|
|
161
|
+
this.discoveredUuid,
|
|
162
|
+
'Did not expose the discovered uuid!'
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@test()
|
|
167
|
+
protected static async createBleBackendThrowsOn400() {
|
|
168
|
+
this.setFake400Error()
|
|
169
|
+
|
|
170
|
+
await assert.doesThrowAsync(
|
|
171
|
+
async () => await this.instance.connect(),
|
|
172
|
+
this.fake400Error,
|
|
173
|
+
'Did not throw error!'
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@test()
|
|
178
|
+
protected static async createBleBackendThrowsOn500() {
|
|
179
|
+
this.setFake500Error()
|
|
180
|
+
|
|
181
|
+
await assert.doesThrowAsync(
|
|
182
|
+
async () => await this.instance.connect(),
|
|
183
|
+
this.fake500Error,
|
|
184
|
+
'Did not throw error!'
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@test()
|
|
189
|
+
protected static async connectCallsLibndxStartBleBackend() {
|
|
190
|
+
await this.connect()
|
|
191
|
+
|
|
192
|
+
const call = FakeLibndx.callsToStartBleBackend[0]
|
|
193
|
+
|
|
194
|
+
assert.isEqual(
|
|
195
|
+
call.deviceUuid,
|
|
196
|
+
this.uuid,
|
|
197
|
+
'Did not call startBleBackend with correct deviceUuid!'
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
assert.isEqual(
|
|
201
|
+
call.charCallbacks.length,
|
|
202
|
+
2,
|
|
203
|
+
'Did not call startBleBackend with charCallbacks!'
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
let i = 0
|
|
207
|
+
for (const charCallback of call.charCallbacks) {
|
|
208
|
+
assert.isEqual(
|
|
209
|
+
charCallback.charUuid,
|
|
210
|
+
this.charCallbacks[i].charUuid,
|
|
211
|
+
'Incorrect charUuid!'
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
assert.isEqual(
|
|
215
|
+
charCallback.charName,
|
|
216
|
+
this.charCallbacks[i].charName,
|
|
217
|
+
'Incorrect charName!'
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
assert.isFunction(
|
|
221
|
+
charCallback.onData,
|
|
222
|
+
'Callback is not a function!'
|
|
223
|
+
)
|
|
224
|
+
i++
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@test()
|
|
229
|
+
protected static async startBleBackendThrowsOn400() {
|
|
230
|
+
//@ts-ignore
|
|
231
|
+
this.instance.createBleBackend = () => {}
|
|
232
|
+
|
|
233
|
+
this.setFake400Error()
|
|
234
|
+
|
|
235
|
+
await assert.doesThrowAsync(
|
|
236
|
+
async () => await this.instance.connect(),
|
|
237
|
+
this.fake400Error,
|
|
238
|
+
'Did not throw error!'
|
|
239
|
+
)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@test()
|
|
243
|
+
protected static async startBleBackendThrowsOn500() {
|
|
244
|
+
//@ts-ignore
|
|
245
|
+
this.instance.createBleBackend = () => {}
|
|
246
|
+
|
|
247
|
+
this.setFake500Error()
|
|
248
|
+
|
|
249
|
+
await assert.doesThrowAsync(
|
|
250
|
+
async () => await this.instance.connect(),
|
|
251
|
+
this.fake500Error,
|
|
252
|
+
'Did not throw error!'
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@test()
|
|
257
|
+
protected static async connectWaitsForOnConnectedEvent() {
|
|
258
|
+
await this.connect()
|
|
259
|
+
|
|
260
|
+
assert.isTruthy(
|
|
261
|
+
this.wasConnected,
|
|
262
|
+
'Did not wait for onConnected event!'
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@test()
|
|
267
|
+
protected static async waitsAfterOnConnectedToDiscoverServices() {
|
|
268
|
+
const waitAfterMs = 20
|
|
269
|
+
BleDeviceController.waitAfterMs = waitAfterMs
|
|
270
|
+
|
|
271
|
+
await this.connect()
|
|
272
|
+
|
|
273
|
+
assert.isTruthy(
|
|
274
|
+
this.callsToSetTimeout.includes(waitAfterMs),
|
|
275
|
+
'Did not wait after on connected!'
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@test()
|
|
280
|
+
protected static async writeCharacteristicCallsLibndxBinding() {
|
|
281
|
+
await this.writeCharacteristic()
|
|
282
|
+
|
|
283
|
+
assert.isEqualDeep(
|
|
284
|
+
FakeLibndx.callsToWriteBleCharacteristic[0],
|
|
285
|
+
{
|
|
286
|
+
deviceUuid: this.uuid,
|
|
287
|
+
charUuid: this.charUuid,
|
|
288
|
+
value: this.charValueToWrite,
|
|
289
|
+
},
|
|
290
|
+
'Did not call writeBleCharacteristic as expected!'
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@test()
|
|
295
|
+
protected static async writeCharacteristicThrowsOn400() {
|
|
296
|
+
this.setFake400Error()
|
|
297
|
+
|
|
298
|
+
await assert.doesThrowAsync(
|
|
299
|
+
async () => await this.writeCharacteristic(),
|
|
300
|
+
this.fake400Error,
|
|
301
|
+
'Did not throw error!'
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
@test()
|
|
306
|
+
protected static async writeCharacteristicThrowsOn500() {
|
|
307
|
+
this.setFake500Error()
|
|
308
|
+
|
|
309
|
+
await assert.doesThrowAsync(
|
|
310
|
+
async () => await this.writeCharacteristic(),
|
|
311
|
+
this.fake500Error,
|
|
312
|
+
'Did not throw error!'
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@test()
|
|
317
|
+
protected static async subscribeCharacteristicsCallsLibndxBinding() {
|
|
318
|
+
await this.subscribeCharacteristics()
|
|
319
|
+
|
|
320
|
+
assert.isEqualDeep(
|
|
321
|
+
FakeLibndx.callsToAddBleCharCallbacks[0],
|
|
322
|
+
{
|
|
323
|
+
deviceUuid: this.uuid,
|
|
324
|
+
charCallbacks: this.extraCharCallbacks,
|
|
325
|
+
},
|
|
326
|
+
'Did not call addBleCharCallbacks as expected!'
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@test()
|
|
331
|
+
protected static async subscribeCharacteristicsMergesIntoCharCallbacks() {
|
|
332
|
+
await this.subscribeCharacteristics()
|
|
333
|
+
|
|
334
|
+
assert.isEqualDeep(
|
|
335
|
+
this.instance.getCharacteristicCallbacks(),
|
|
336
|
+
[...this.charCallbacks, ...this.extraCharCallbacks],
|
|
337
|
+
'Did not merge the newly subscribed callbacks into charCallbacks!'
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@test()
|
|
342
|
+
protected static async subscribeCharacteristicsThrowsOn400() {
|
|
343
|
+
this.setFake400Error()
|
|
344
|
+
|
|
345
|
+
await assert.doesThrowAsync(
|
|
346
|
+
async () => await this.subscribeCharacteristics(),
|
|
347
|
+
this.fake400Error,
|
|
348
|
+
'Did not throw error!'
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@test()
|
|
353
|
+
protected static async callsSetBleRssiInterval() {
|
|
354
|
+
await this.connect()
|
|
355
|
+
|
|
356
|
+
const { deviceUuid, intervalMs } =
|
|
357
|
+
FakeLibndx.callsToSetBleRssiInterval[0]
|
|
358
|
+
|
|
359
|
+
assert.isEqualDeep(
|
|
360
|
+
{ deviceUuid, intervalMs },
|
|
361
|
+
{
|
|
362
|
+
deviceUuid: this.uuid,
|
|
363
|
+
intervalMs: this.rssiIntervalMs,
|
|
364
|
+
},
|
|
365
|
+
'Did not call setBleRssiInterval as expected!'
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
@test()
|
|
370
|
+
protected static async disconnectCallsLibndxStopBleBackend() {
|
|
371
|
+
await this.disconnect()
|
|
372
|
+
|
|
373
|
+
assert.isEqualDeep(
|
|
374
|
+
FakeLibndx.callsToStopBleBackend[0],
|
|
375
|
+
{
|
|
376
|
+
deviceUuid: this.uuid,
|
|
377
|
+
},
|
|
378
|
+
'Did not call stopBleBackend!'
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@test()
|
|
383
|
+
protected static async disconnectThrowsOn400() {
|
|
384
|
+
this.setFake400Error()
|
|
385
|
+
|
|
386
|
+
await assert.doesThrowAsync(
|
|
387
|
+
async () => await this.disconnect(),
|
|
388
|
+
this.fake400Error,
|
|
389
|
+
'Did not throw error!'
|
|
390
|
+
)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@test()
|
|
394
|
+
protected static async disconnectThrowsOn500() {
|
|
395
|
+
this.setFake500Error()
|
|
396
|
+
|
|
397
|
+
await assert.doesThrowAsync(
|
|
398
|
+
async () => await this.disconnect(),
|
|
399
|
+
this.fake500Error,
|
|
400
|
+
'Did not throw error!'
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@test()
|
|
405
|
+
protected static async disconnectResetsConnectedFlag() {
|
|
406
|
+
await this.connect()
|
|
407
|
+
await this.disconnect()
|
|
408
|
+
|
|
409
|
+
assert.isFalse(
|
|
410
|
+
this.instance.getConnected(),
|
|
411
|
+
'Did not reset connected flag on disconnect!'
|
|
412
|
+
)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
@test()
|
|
416
|
+
protected static async exposesPeriperalName() {
|
|
417
|
+
await this.connect()
|
|
418
|
+
|
|
419
|
+
assert.isEqual(
|
|
420
|
+
this.instance.name,
|
|
421
|
+
this.nativePeripheral.name,
|
|
422
|
+
'Did not set peripheral name!'
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@test()
|
|
427
|
+
protected static async returnsNAIfNameNotAvailable() {
|
|
428
|
+
assert.isEqual(
|
|
429
|
+
this.instance.name,
|
|
430
|
+
'N/A',
|
|
431
|
+
'Did not set default name to N/A!'
|
|
432
|
+
)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@test()
|
|
436
|
+
protected static async throwsWithUnknownErrorIfNoError() {
|
|
437
|
+
this.setFake500ErrorWithoutError()
|
|
438
|
+
|
|
439
|
+
await assert.doesThrowAsync(
|
|
440
|
+
async () => await this.connect(),
|
|
441
|
+
'Unknown error',
|
|
442
|
+
'Did not throw error!'
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private static async connect() {
|
|
447
|
+
const promise = this.instance.connect()
|
|
448
|
+
|
|
449
|
+
const startCall = FakeLibndx.callsToStartBleBackend[0]
|
|
450
|
+
startCall?.onConnected(this.nativePeripheral)
|
|
451
|
+
|
|
452
|
+
await promise
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private static async connectWithDiscovery(instance: SpyBleController) {
|
|
456
|
+
const promise = instance.connect()
|
|
457
|
+
|
|
458
|
+
FakeLibndx.callsToDiscoverBleUuid[0]?.onDiscovered(this.discoveredUuid)
|
|
459
|
+
|
|
460
|
+
await this.waitForCall(() => FakeLibndx.callsToStartBleBackend[0])
|
|
461
|
+
|
|
462
|
+
FakeLibndx.callsToStartBleBackend[0]?.onConnected(this.nativePeripheral)
|
|
463
|
+
|
|
464
|
+
await promise
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
private static async waitForCall<T>(getCall: () => T) {
|
|
468
|
+
await new Promise<void>((resolve) => {
|
|
469
|
+
const check = () => {
|
|
470
|
+
if (getCall()) {
|
|
471
|
+
resolve()
|
|
472
|
+
} else {
|
|
473
|
+
setTimeout(check, 0)
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
check()
|
|
477
|
+
})
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private static async writeCharacteristic() {
|
|
481
|
+
await this.instance.writeCharacteristic(
|
|
482
|
+
this.charUuid,
|
|
483
|
+
this.charValueToWrite
|
|
484
|
+
)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
private static async subscribeCharacteristics() {
|
|
488
|
+
await this.instance.subscribeCharacteristics(this.extraCharCallbacks)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private static async disconnect() {
|
|
492
|
+
await this.instance.disconnect()
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
private static setFake400Error() {
|
|
496
|
+
FakeLibndx.fakeResult = {
|
|
497
|
+
status: 400,
|
|
498
|
+
error: this.fakeError,
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private static setFake500Error() {
|
|
503
|
+
FakeLibndx.fakeResult = {
|
|
504
|
+
status: 500,
|
|
505
|
+
error: this.fakeError,
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
private static setFake500ErrorWithoutError() {
|
|
510
|
+
FakeLibndx.fakeResult = {
|
|
511
|
+
status: 500,
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
private static async BleController(
|
|
516
|
+
options?: Partial<BleControllerOptions>
|
|
517
|
+
) {
|
|
518
|
+
return (await BleDeviceController.Create({
|
|
519
|
+
deviceUuid: this.uuid,
|
|
520
|
+
charCallbacks: this.charCallbacks,
|
|
521
|
+
onConnected: this.onConnected,
|
|
522
|
+
rssiIntervalMs: this.rssiIntervalMs,
|
|
523
|
+
...options,
|
|
524
|
+
})) as SpyBleController
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
private static async BleControllerWithPrefix() {
|
|
528
|
+
return (await BleDeviceController.Create({
|
|
529
|
+
deviceNamePrefix: this.namePrefix,
|
|
530
|
+
charCallbacks: this.charCallbacks,
|
|
531
|
+
onConnected: this.onConnected,
|
|
532
|
+
rssiIntervalMs: this.rssiIntervalMs,
|
|
533
|
+
} as unknown as BleControllerOptions)) as SpyBleController
|
|
534
|
+
}
|
|
535
|
+
}
|
|
@@ -386,7 +386,7 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
386
386
|
protected static async pushSampleHandlesErrorCode() {
|
|
387
387
|
let passedErrorCode: number | undefined
|
|
388
388
|
|
|
389
|
-
StreamInletWorker.
|
|
389
|
+
StreamInletWorker.handleLslError = (errorCode: number) => {
|
|
390
390
|
passedErrorCode = errorCode
|
|
391
391
|
}
|
|
392
392
|
|
|
@@ -400,7 +400,7 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
400
400
|
assert.isEqualDeep(
|
|
401
401
|
passedErrorCode,
|
|
402
402
|
FakeLiblsl.fakeErrorCode,
|
|
403
|
-
'Did not pass the expected error code to
|
|
403
|
+
'Did not pass the expected error code to handleLslError!'
|
|
404
404
|
)
|
|
405
405
|
}
|
|
406
406
|
|
|
@@ -7,7 +7,7 @@ import LslStreamOutlet, {
|
|
|
7
7
|
StreamOutletOptions,
|
|
8
8
|
} from '../../impl/LslStreamOutlet.js'
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
setOutletHandleLslError,
|
|
11
11
|
setOutletLiblslAdapter,
|
|
12
12
|
} from '../../impl/workers/outlet/LslStreamOutlet.worker.js'
|
|
13
13
|
import {
|
|
@@ -128,7 +128,7 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
128
128
|
maxBufferedMs: this.randomOutletOptions.maxBufferedMs,
|
|
129
129
|
})
|
|
130
130
|
assert.isNumber(
|
|
131
|
-
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.
|
|
131
|
+
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.timestampSec
|
|
132
132
|
)
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -148,7 +148,7 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
148
148
|
sample
|
|
149
149
|
)
|
|
150
150
|
assert.isNumber(
|
|
151
|
-
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.
|
|
151
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestampSec
|
|
152
152
|
)
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -159,13 +159,13 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
159
159
|
|
|
160
160
|
outlet.pushSample(sample)
|
|
161
161
|
const t1 =
|
|
162
|
-
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.
|
|
162
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestampSec
|
|
163
163
|
|
|
164
164
|
await this.wait(10)
|
|
165
165
|
|
|
166
166
|
outlet.pushSample(sample)
|
|
167
167
|
const t2 =
|
|
168
|
-
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.
|
|
168
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestampSec
|
|
169
169
|
|
|
170
170
|
assert.isNotEqual(t1, t2)
|
|
171
171
|
assert.isEqual(this.fakeLiblsl.localClockHitCount, 2)
|
|
@@ -227,13 +227,13 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
227
227
|
@test()
|
|
228
228
|
protected static async pushSampleAcceptsOptionalPreciseTimestamp() {
|
|
229
229
|
const outlet = await this.FloatOutlet()
|
|
230
|
-
const
|
|
230
|
+
const timestampSec = Math.random() * 10000
|
|
231
231
|
|
|
232
|
-
outlet.pushSample([1.0],
|
|
232
|
+
outlet.pushSample([1.0], timestampSec)
|
|
233
233
|
|
|
234
234
|
assert.isEqual(
|
|
235
|
-
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.
|
|
236
|
-
|
|
235
|
+
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.timestampSec,
|
|
236
|
+
timestampSec
|
|
237
237
|
)
|
|
238
238
|
}
|
|
239
239
|
|
|
@@ -241,7 +241,7 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
241
241
|
protected static async pushSampleHandlesErrorCode() {
|
|
242
242
|
let passedErrorCode: number | undefined
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
setOutletHandleLslError((errorCode: number) => {
|
|
245
245
|
passedErrorCode = errorCode
|
|
246
246
|
})
|
|
247
247
|
|
|
@@ -265,11 +265,12 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
|
|
|
265
265
|
|
|
266
266
|
@test()
|
|
267
267
|
protected static async waitsForTenMsAfterConstructionBeforeReturning() {
|
|
268
|
-
|
|
269
|
-
await this.LslStreamOutlet({ waitAfterConstructionMs: 10 })
|
|
270
|
-
const endMs = Date.now()
|
|
268
|
+
await this.LslStreamOutlet()
|
|
271
269
|
|
|
272
|
-
assert.
|
|
270
|
+
assert.isTruthy(
|
|
271
|
+
this.callsToSetTimeout.includes(10),
|
|
272
|
+
'Did not wait for 10ms after construction!'
|
|
273
|
+
)
|
|
273
274
|
}
|
|
274
275
|
|
|
275
276
|
@test()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { randomInt } from 'crypto'
|
|
1
|
+
import { randomInt } from 'node:crypto'
|
|
2
|
+
|
|
2
3
|
import { test, assert } from '@neurodevs/node-tdd'
|
|
3
4
|
|
|
4
5
|
import { StreamInletOptions } from '../../impl/LslStreamInlet.js'
|
|
@@ -152,7 +153,7 @@ export default class LslWebSocketBridgeTest extends AbstractPackageTest {
|
|
|
152
153
|
|
|
153
154
|
await assert.doesThrowAsync(async () => {
|
|
154
155
|
await this.activate()
|
|
155
|
-
}, `\n\
|
|
156
|
+
}, `\n\nCannot activate bridge after destroying it! \n\nPlease create and activate a new instance. \n`)
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
@test()
|
|
@@ -161,7 +162,7 @@ export default class LslWebSocketBridgeTest extends AbstractPackageTest {
|
|
|
161
162
|
|
|
162
163
|
assert.doesThrow(() => {
|
|
163
164
|
this.deactivate()
|
|
164
|
-
}, `\n\
|
|
165
|
+
}, `\n\nCannot deactivate bridge after destroying it! \n\nPlease create and activate a new instance. \n`)
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
@test()
|