@neurodevs/node-lsl 8.0.1 → 8.0.3
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/settings.json +17 -20
- package/build/.spruce/errors/errors.types.js +0 -2
- package/build/.spruce/errors/errors.types.js.map +1 -1
- package/build/__tests__/behavioral/LslOutlet.test.js +9 -14
- package/build/__tests__/behavioral/LslOutlet.test.js.map +1 -1
- package/build/__tests__/behavioral/TimeMarkerOutlet.test.js.map +1 -1
- package/build/__tests__/implementation/Liblsl.test.js +17 -4
- package/build/__tests__/implementation/Liblsl.test.js.map +1 -1
- package/build/__tests__/support/consts.js.map +1 -1
- package/build/__tests__/support/generateRandomOutletOptions.js.map +1 -1
- package/build/assertions.js.map +1 -1
- package/build/consts.js.map +1 -1
- package/build/errors/SpruceError.d.ts +1 -1
- package/build/errors/SpruceError.js.map +1 -1
- package/build/errors/failedToLoadLiblsl.builder.js.map +1 -1
- package/build/implementations/Liblsl.js +22 -6
- package/build/implementations/Liblsl.js.map +1 -1
- package/build/implementations/LslOutlet.js +6 -14
- package/build/implementations/LslOutlet.js.map +1 -1
- package/build/implementations/TimeMarkerOutlet.js +4 -1
- package/build/implementations/TimeMarkerOutlet.js.map +1 -1
- package/build/nodeLsl.types.d.ts +2 -2
- package/build/testDoubles/FakeLiblsl.js.map +1 -1
- package/build/testDoubles/MockTimeMarkerOutlet.js.map +1 -1
- package/build/testDoubles/SpyExtendsTimeMarkerOutlet.js.map +1 -1
- package/build/testDoubles/SpyImplementsTimeMarkerOutlet.js.map +1 -1
- package/build/validations.js.map +1 -1
- package/eslint.config.mjs +3 -0
- package/package.json +26 -26
- package/src/.spruce/errors/errors.types.ts +0 -3
- package/src/__tests__/behavioral/LslOutlet.test.ts +272 -267
- package/src/__tests__/behavioral/TimeMarkerOutlet.test.ts +144 -141
- package/src/__tests__/implementation/Liblsl.test.ts +461 -438
- package/src/__tests__/support/consts.ts +22 -22
- package/src/__tests__/support/generateRandomOutletOptions.ts +13 -13
- package/src/assertions.ts +39 -39
- package/src/consts.ts +16 -16
- package/src/errors/SpruceError.ts +16 -16
- package/src/errors/failedToLoadLiblsl.builder.ts +8 -8
- package/src/implementations/Liblsl.ts +205 -181
- package/src/implementations/LslOutlet.ts +114 -114
- package/src/implementations/TimeMarkerOutlet.ts +50 -50
- package/src/nodeLsl.types.ts +60 -63
- package/src/testDoubles/FakeLiblsl.ts +58 -56
- package/src/testDoubles/MockTimeMarkerOutlet.ts +56 -56
- package/src/testDoubles/SpyExtendsTimeMarkerOutlet.ts +11 -11
- package/src/testDoubles/SpyImplementsTimeMarkerOutlet.ts +28 -28
- package/src/validations.ts +6 -6
- package/tsconfig.json +3 -4
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -3
package/package.json
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neurodevs/node-lsl",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.3",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/neurodevs/node-lsl.git"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build.ci": "yarn build.tsc && yarn build.resolve-paths && yarn lint",
|
|
11
|
-
"build.dev": "yarn build.tsc --sourceMap ; yarn resolve-paths.lint",
|
|
10
|
+
"build.ci": "yarn run build.tsc && yarn run build.resolve-paths && yarn run lint",
|
|
11
|
+
"build.dev": "yarn run build.tsc --sourceMap ; yarn run resolve-paths.lint",
|
|
12
12
|
"build.copy-files": "mkdir -p build && rsync -avzq --exclude='*.ts' ./src/ ./build/",
|
|
13
13
|
"build.resolve-paths": "resolve-path-aliases --target build --patterns '**/*.js,**/*.d.ts'",
|
|
14
|
-
"build.tsc": "yarn build.copy-files && tsc",
|
|
15
|
-
"clean": "yarn clean.build",
|
|
16
|
-
"clean.all": "yarn clean.dependencies && yarn clean.build",
|
|
14
|
+
"build.tsc": "yarn run build.copy-files && tsc",
|
|
15
|
+
"clean": "yarn run clean.build",
|
|
16
|
+
"clean.all": "yarn run clean.dependencies && yarn run clean.build",
|
|
17
17
|
"clean.build": "rm -rf build/",
|
|
18
18
|
"clean.dependencies": "rm -rf node_modules/ package-lock.json yarn.lock",
|
|
19
19
|
"fix.lint": "eslint --fix --cache '**/*.ts'",
|
|
20
20
|
"lint": "eslint --cache '**/*.ts'",
|
|
21
21
|
"lint.tsc": "tsc -p . --noEmit",
|
|
22
|
-
"post.watch.build": "yarn build.copy-files && yarn build.resolve-paths",
|
|
23
|
-
"rebuild": "yarn clean.all && yarn && yarn build.dev",
|
|
24
|
-
"update.dependencies": "yarn clean.dependencies && yarn",
|
|
25
|
-
"resolve-paths.lint": "yarn build.resolve-paths ; yarn lint",
|
|
22
|
+
"post.watch.build": "yarn run build.copy-files && yarn run build.resolve-paths",
|
|
23
|
+
"rebuild": "yarn run clean.all && yarn install && yarn run build.dev",
|
|
24
|
+
"update.dependencies": "yarn run clean.dependencies && yarn",
|
|
25
|
+
"resolve-paths.lint": "yarn run build.resolve-paths ; yarn run lint",
|
|
26
26
|
"test": "jest",
|
|
27
|
-
"watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn post.watch.build'",
|
|
27
|
+
"watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn run post.watch.build'",
|
|
28
28
|
"watch.lint": "concurrently 'yarn lint' \"chokidar 'src/**/*' -c 'yarn lint.tsc'\"",
|
|
29
|
-
"watch.rebuild": "yarn clean.all && yarn && yarn watch.build.dev",
|
|
29
|
+
"watch.rebuild": "yarn run clean.all && yarn install && yarn run watch.build.dev",
|
|
30
30
|
"watch.tsc": "tsc -w",
|
|
31
31
|
"test.rs": "node build/test.js"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@sprucelabs/jest-json-reporter": "^
|
|
35
|
-
"@sprucelabs/resolve-path-aliases": "^
|
|
36
|
-
"@sprucelabs/test": "^
|
|
37
|
-
"@sprucelabs/test-utils": "^
|
|
34
|
+
"@sprucelabs/jest-json-reporter": "^8.0.24",
|
|
35
|
+
"@sprucelabs/resolve-path-aliases": "^2.0.20",
|
|
36
|
+
"@sprucelabs/test": "^9.0.13",
|
|
37
|
+
"@sprucelabs/test-utils": "^5.0.27",
|
|
38
38
|
"@types/ffi-napi": "^4.0.10",
|
|
39
|
-
"@types/node": "^20.11
|
|
39
|
+
"@types/node": "^20.12.11",
|
|
40
40
|
"chokidar-cli": "^3.0.0",
|
|
41
41
|
"concurrently": "^8.2.2",
|
|
42
|
-
"eslint": "^
|
|
43
|
-
"eslint-config-spruce": "^
|
|
42
|
+
"eslint": "^9.2.0",
|
|
43
|
+
"eslint-config-spruce": "^11.2.17",
|
|
44
44
|
"jest": "^29.7.0",
|
|
45
45
|
"jest-circus": "^29.7.0",
|
|
46
46
|
"prettier": "^3.2.5",
|
|
47
47
|
"ts-node": "^10.9.2",
|
|
48
48
|
"tsc-watch": "^6.2.0",
|
|
49
|
-
"typescript": "^5.4.
|
|
49
|
+
"typescript": "^5.4.5"
|
|
50
50
|
},
|
|
51
51
|
"description": "Lab Streaming Layer (LSL) bindings for Node",
|
|
52
52
|
"skill": {
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@sprucelabs/error": "^
|
|
78
|
-
"@sprucelabs/schema": "^
|
|
79
|
-
"@sprucelabs/spruce-core-schemas": "^
|
|
80
|
-
"@sprucelabs/spruce-skill-utils": "^
|
|
81
|
-
"ffi-rs": "^1.0.
|
|
77
|
+
"@sprucelabs/error": "^6.0.23",
|
|
78
|
+
"@sprucelabs/schema": "^30.0.36",
|
|
79
|
+
"@sprucelabs/spruce-core-schemas": "^40.0.30",
|
|
80
|
+
"@sprucelabs/spruce-skill-utils": "^31.0.39",
|
|
81
|
+
"ffi-rs": "^1.0.74",
|
|
82
82
|
"node-gyp": "^10.1.0",
|
|
83
83
|
"ref-array-napi": "^1.2.2",
|
|
84
84
|
"ref-napi": "^3.0.3"
|
|
85
85
|
}
|
|
86
|
-
}
|
|
86
|
+
}
|
|
@@ -1,282 +1,287 @@
|
|
|
1
1
|
import AbstractSpruceTest, {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
test,
|
|
3
|
+
assert,
|
|
4
|
+
errorAssert,
|
|
5
|
+
generateId,
|
|
6
6
|
} from '@sprucelabs/test-utils'
|
|
7
7
|
import LiblslImpl from '../../implementations/Liblsl'
|
|
8
8
|
import LslOutlet from '../../implementations/LslOutlet'
|
|
9
9
|
import { LslOutletOptions, LslSample } from '../../nodeLsl.types'
|
|
10
10
|
import FakeLiblsl from '../../testDoubles/FakeLiblsl'
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
TEST_CHANNEL_FORMATS_MAP,
|
|
13
|
+
TEST_SUPPORTED_CHANNEL_FORMATS,
|
|
14
|
+
TEST_UNSUPPORTED_CHANNEL_FORMATS,
|
|
15
|
+
TestChannelFormat,
|
|
16
16
|
} from '../support/consts'
|
|
17
17
|
import generateRandomOutletOptions from '../support/generateRandomOutletOptions'
|
|
18
18
|
|
|
19
19
|
export default class LslOutletTest extends AbstractSpruceTest {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
20
|
+
private static fakeLiblsl: FakeLiblsl
|
|
21
|
+
private static randomOutletOptions: LslOutletOptions
|
|
22
|
+
private static channelFormatIdx: number
|
|
23
|
+
|
|
24
|
+
protected static async beforeEach() {
|
|
25
|
+
await super.beforeEach()
|
|
26
|
+
delete LslOutlet.Class
|
|
27
|
+
this.randomOutletOptions = generateRandomOutletOptions()
|
|
28
|
+
|
|
29
|
+
const channelFormat = this.randomOutletOptions.channelFormat
|
|
30
|
+
this.channelFormatIdx = TEST_CHANNEL_FORMATS_MAP[channelFormat]
|
|
31
|
+
this.fakeLiblsl = new FakeLiblsl()
|
|
32
|
+
LiblslImpl.setInstance(this.fakeLiblsl)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@test()
|
|
36
|
+
protected static async throwsWhenMissingRequiredParams() {
|
|
37
|
+
//@ts-ignore
|
|
38
|
+
const err = assert.doesThrow(() => new LslOutlet())
|
|
39
|
+
errorAssert.assertError(err, 'MISSING_PARAMETERS', {
|
|
40
|
+
parameters: [
|
|
41
|
+
'name',
|
|
42
|
+
'type',
|
|
43
|
+
'channelNames',
|
|
44
|
+
'sampleRate',
|
|
45
|
+
'channelFormat',
|
|
46
|
+
'sourceId',
|
|
47
|
+
'manufacturer',
|
|
48
|
+
'unit',
|
|
49
|
+
'chunkSize',
|
|
50
|
+
'maxBuffered',
|
|
51
|
+
],
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@test()
|
|
56
|
+
protected static async throwsWithInvalidChannelNames() {
|
|
57
|
+
this.assertThrowsInvalidChannelNames(0)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@test()
|
|
61
|
+
protected static async throwsWithInvalidSampleRate() {
|
|
62
|
+
this.Outlet({ sampleRate: 0 })
|
|
63
|
+
this.assertThrowsInvalidSampleRate(-1)
|
|
64
|
+
this.assertThrowsInvalidSampleRate(-1.5)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@test()
|
|
68
|
+
protected static async throwsWithInvalidChannelFormat() {
|
|
69
|
+
//@ts-ignore
|
|
70
|
+
this.assertDoesThrowInvalidParameters({ channelFormat: generateId() }, [
|
|
71
|
+
'channelFormat',
|
|
72
|
+
])
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@test()
|
|
76
|
+
protected static async throwsWithInvalidChunkSize() {
|
|
77
|
+
this.Outlet({ chunkSize: 0 })
|
|
78
|
+
this.assertThrowsInvalidChunkSize(-1)
|
|
79
|
+
this.assertThrowsInvalidChunkSize(-1.5)
|
|
80
|
+
this.assertThrowsInvalidChunkSize(1.5)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@test()
|
|
84
|
+
protected static async throwsWithInvalidMaxBuffered() {
|
|
85
|
+
this.Outlet({ maxBuffered: 0 })
|
|
86
|
+
this.assertThrowsInvalidMaxBuffered(-1)
|
|
87
|
+
this.assertThrowsInvalidMaxBuffered(-1.5)
|
|
88
|
+
this.assertThrowsInvalidMaxBuffered(1.5)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@test()
|
|
92
|
+
protected static async throwsWithUnsupportedType() {
|
|
93
|
+
for (let unsupportedType of TEST_UNSUPPORTED_CHANNEL_FORMATS) {
|
|
94
|
+
assert.doesThrow(
|
|
95
|
+
() => this.Outlet({ channelFormat: unsupportedType }),
|
|
96
|
+
`This method currently does not support the ${unsupportedType} type! Please implement it.`
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@test()
|
|
102
|
+
protected static async supportsAllKnownChannelFormats() {
|
|
103
|
+
for (const format of TEST_SUPPORTED_CHANNEL_FORMATS) {
|
|
104
|
+
this.Outlet({ channelFormat: format as TestChannelFormat })
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@test('pushing [1, 2] sample sends to LSL', [1.0, 2.0])
|
|
109
|
+
@test('pushing [1] sample sends to LSL', [1.0])
|
|
110
|
+
protected static async canPushFloatSampleToLsl(sample: LslSample) {
|
|
111
|
+
const outlet = this.FloatOutlet()
|
|
112
|
+
outlet.pushSample(sample)
|
|
113
|
+
|
|
114
|
+
assert.isEqual(
|
|
115
|
+
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.outlet,
|
|
116
|
+
this.fakeLiblsl.outlet
|
|
117
|
+
)
|
|
118
|
+
assert.isEqualDeep(
|
|
119
|
+
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.sample,
|
|
120
|
+
sample
|
|
121
|
+
)
|
|
122
|
+
assert.isEqualDeep(this.fakeLiblsl.lastCreateOutletOptions, {
|
|
123
|
+
info: this.fakeLiblsl.streamInfo,
|
|
124
|
+
chunkSize: this.randomOutletOptions.chunkSize,
|
|
125
|
+
maxBuffered: this.randomOutletOptions.maxBuffered,
|
|
126
|
+
})
|
|
127
|
+
assert.isNumber(
|
|
128
|
+
this.fakeLiblsl.lastPushSampleFloatTimestampOptions?.timestamp
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@test()
|
|
133
|
+
protected static async canPushStringSampleToLsl() {
|
|
134
|
+
const sample = [generateId()]
|
|
135
|
+
const outlet = this.StringOutlet()
|
|
136
|
+
|
|
137
|
+
outlet.pushSample(sample)
|
|
138
|
+
|
|
139
|
+
assert.isEqual(
|
|
140
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.outlet,
|
|
141
|
+
this.fakeLiblsl.outlet
|
|
142
|
+
)
|
|
143
|
+
assert.isEqualDeep(
|
|
144
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.sample,
|
|
145
|
+
sample
|
|
146
|
+
)
|
|
147
|
+
assert.isNumber(
|
|
148
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestamp
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@test()
|
|
153
|
+
protected static async pushingStringTwiceGivesDifferentTimestamps() {
|
|
154
|
+
const outlet = this.StringOutlet()
|
|
155
|
+
const sample = [generateId()]
|
|
156
|
+
|
|
157
|
+
outlet.pushSample(sample)
|
|
158
|
+
const t1 =
|
|
159
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestamp
|
|
160
|
+
|
|
161
|
+
await this.wait(10)
|
|
162
|
+
|
|
163
|
+
outlet.pushSample(sample)
|
|
164
|
+
const t2 =
|
|
165
|
+
this.fakeLiblsl.lastPushSampleStringTimestampOptions?.timestamp
|
|
166
|
+
|
|
167
|
+
assert.isNotEqual(t1, t2)
|
|
168
|
+
assert.isEqual(this.fakeLiblsl.localClockHitCount, 2)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@test()
|
|
172
|
+
protected static async constructionCreatesStreamInfo() {
|
|
173
|
+
this.Outlet()
|
|
174
|
+
|
|
175
|
+
const { ...options } = this.randomOutletOptions as any
|
|
176
|
+
|
|
177
|
+
options.channelCount = options.channelNames.length
|
|
178
|
+
|
|
179
|
+
delete options.manufacturer
|
|
180
|
+
delete options.unit
|
|
181
|
+
delete options.chunkSize
|
|
182
|
+
delete options.maxBuffered
|
|
183
|
+
delete options.channelNames
|
|
184
|
+
|
|
185
|
+
assert.isEqualDeep(this.fakeLiblsl.lastCreateStreamInfoOptions, {
|
|
186
|
+
...options,
|
|
187
|
+
channelFormat: this.channelFormatIdx,
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@test()
|
|
192
|
+
protected static async canOverrideClassInstantiatedInFactory() {
|
|
193
|
+
LslOutlet.Class = CheckingOutlet
|
|
194
|
+
const instance = this.Outlet()
|
|
195
|
+
|
|
196
|
+
assert.isInstanceOf(instance, CheckingOutlet)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@test('can add one label to channels', [generateId()])
|
|
200
|
+
@test('can add two labels to channels', [generateId(), generateId()])
|
|
201
|
+
protected static async appendsChannelsBasedOnCount(labels: string[]) {
|
|
202
|
+
const type = generateId()
|
|
203
|
+
const unit = generateId()
|
|
204
|
+
|
|
205
|
+
this.Outlet({ channelNames: labels, type, unit })
|
|
206
|
+
|
|
207
|
+
assert.isEqualDeep(
|
|
208
|
+
this.fakeLiblsl.lastAppendChannelsToStreamInfoOptions,
|
|
209
|
+
{
|
|
210
|
+
info: this.fakeLiblsl.streamInfo,
|
|
211
|
+
channels: labels.map((label) => ({
|
|
212
|
+
label,
|
|
213
|
+
type,
|
|
214
|
+
unit,
|
|
215
|
+
})),
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@test()
|
|
221
|
+
protected static async canDestroyOutlet() {
|
|
222
|
+
const outlet = this.Outlet()
|
|
223
|
+
outlet.destroy()
|
|
224
|
+
|
|
225
|
+
assert.isEqual(this.fakeLiblsl.destroyOutletHitCount, 1)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@test()
|
|
229
|
+
protected static async pushSampleShouldNotCreateMultipleOutlets() {
|
|
230
|
+
const outlet = this.FloatOutlet()
|
|
231
|
+
outlet.pushSample([1.0])
|
|
232
|
+
outlet.pushSample([2.0])
|
|
233
|
+
outlet.pushSample([3.0])
|
|
234
|
+
|
|
235
|
+
assert.isEqual(this.fakeLiblsl.createStreamInfoHitCount, 1)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private static assertThrowsInvalidMaxBuffered(maxBuffered: number) {
|
|
239
|
+
this.assertDoesThrowInvalidParameters({ maxBuffered }, ['maxBuffered'])
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private static assertThrowsInvalidChunkSize(chunkSize: number) {
|
|
243
|
+
this.assertDoesThrowInvalidParameters({ chunkSize }, ['chunkSize'])
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private static assertThrowsInvalidSampleRate(sampleRate: number) {
|
|
247
|
+
this.assertDoesThrowInvalidParameters({ sampleRate }, ['sampleRate'])
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private static assertThrowsInvalidChannelNames(count: number) {
|
|
251
|
+
this.assertDoesThrowInvalidParameters(
|
|
252
|
+
{ channelNames: new Array(count).fill(generateId()) },
|
|
253
|
+
['channelNames']
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private static assertDoesThrowInvalidParameters(
|
|
258
|
+
options: Partial<LslOutletOptions>,
|
|
259
|
+
parameters: string[]
|
|
260
|
+
) {
|
|
261
|
+
const err = assert.doesThrow(() => this.Outlet(options))
|
|
262
|
+
errorAssert.assertError(err, 'INVALID_PARAMETERS', {
|
|
263
|
+
parameters,
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private static Outlet(options?: Partial<LslOutletOptions>) {
|
|
268
|
+
return LslOutlet.Outlet({
|
|
269
|
+
...this.randomOutletOptions,
|
|
270
|
+
...options,
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private static StringOutlet() {
|
|
275
|
+
return this.Outlet({ channelFormat: 'string' })
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private static FloatOutlet() {
|
|
279
|
+
return this.Outlet({ channelFormat: 'float32' })
|
|
280
|
+
}
|
|
276
281
|
}
|
|
277
282
|
|
|
278
283
|
class CheckingOutlet extends LslOutlet {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
284
|
+
public constructor(options: LslOutletOptions) {
|
|
285
|
+
super(options)
|
|
286
|
+
}
|
|
282
287
|
}
|