@neurodevs/node-lsl 6.0.0 → 6.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.
- package/build/TimeMarkerOutlet.d.ts +6 -0
- package/build/TimeMarkerOutlet.js +19 -1
- package/build/TimeMarkerOutlet.js.map +1 -1
- package/build/__tests__/behavioral/TimeMarkerOutlet.test.d.ts +7 -1
- package/build/__tests__/behavioral/TimeMarkerOutlet.test.js +69 -8
- package/build/__tests__/behavioral/TimeMarkerOutlet.test.js.map +1 -1
- package/package.json +1 -1
- package/src/TimeMarkerOutlet.ts +27 -1
- package/src/__tests__/behavioral/TimeMarkerOutlet.test.ts +86 -8
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import LslOutletImpl, { LslOutletOptions } from './LslOutlet';
|
|
2
2
|
export default class TimeMarkerOutletImpl extends LslOutletImpl implements TimeMarkerOutlet {
|
|
3
|
+
private isPlaying;
|
|
4
|
+
private waitResolve?;
|
|
5
|
+
private timeout?;
|
|
3
6
|
static TimeMarkerOutlet(options?: Partial<LslOutletOptions>): TimeMarkerOutlet;
|
|
4
7
|
pushMarkers(markers: DurationMarker[]): Promise<void>;
|
|
5
8
|
protected wait(durationMs: number): Promise<unknown>;
|
|
9
|
+
private setTimeout;
|
|
10
|
+
stop(): void;
|
|
6
11
|
}
|
|
7
12
|
export interface DurationMarker {
|
|
8
13
|
name: string;
|
|
@@ -10,4 +15,5 @@ export interface DurationMarker {
|
|
|
10
15
|
}
|
|
11
16
|
export interface TimeMarkerOutlet {
|
|
12
17
|
pushMarkers(markers: DurationMarker[]): Promise<void>;
|
|
18
|
+
stop(): void;
|
|
13
19
|
}
|
|
@@ -5,6 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const LslOutlet_1 = __importDefault(require("./LslOutlet"));
|
|
7
7
|
class TimeMarkerOutletImpl extends LslOutlet_1.default {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.isPlaying = false;
|
|
11
|
+
}
|
|
8
12
|
static TimeMarkerOutlet(options) {
|
|
9
13
|
var _a;
|
|
10
14
|
const defaultOptions = {
|
|
@@ -23,13 +27,27 @@ class TimeMarkerOutletImpl extends LslOutlet_1.default {
|
|
|
23
27
|
return new ((_a = this.Class) !== null && _a !== void 0 ? _a : this)(Object.assign(Object.assign({}, defaultOptions), options));
|
|
24
28
|
}
|
|
25
29
|
async pushMarkers(markers) {
|
|
30
|
+
this.isPlaying = true;
|
|
26
31
|
for (let marker of markers) {
|
|
27
32
|
this.pushSample([marker.name]);
|
|
28
33
|
await this.wait(marker.durationMs);
|
|
34
|
+
if (!this.isPlaying) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
async wait(durationMs) {
|
|
32
|
-
return new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
40
|
+
return new Promise((resolve) => this.setTimeout(resolve, durationMs));
|
|
41
|
+
}
|
|
42
|
+
setTimeout(resolve, durationMs) {
|
|
43
|
+
this.waitResolve = resolve;
|
|
44
|
+
this.timeout = setTimeout(resolve, durationMs);
|
|
45
|
+
}
|
|
46
|
+
stop() {
|
|
47
|
+
var _a;
|
|
48
|
+
(_a = this.waitResolve) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
49
|
+
clearTimeout(this.timeout);
|
|
50
|
+
this.isPlaying = false;
|
|
33
51
|
}
|
|
34
52
|
}
|
|
35
53
|
exports.default = TimeMarkerOutletImpl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeMarkerOutlet.js","sourceRoot":"","sources":["../src/TimeMarkerOutlet.ts"],"names":[],"mappings":";;;;;AAAA,4DAA6D;AAE7D,MAAqB,oBACpB,SAAQ,mBAAa;
|
|
1
|
+
{"version":3,"file":"TimeMarkerOutlet.js","sourceRoot":"","sources":["../src/TimeMarkerOutlet.ts"],"names":[],"mappings":";;;;;AAAA,4DAA6D;AAE7D,MAAqB,oBACpB,SAAQ,mBAAa;IADtB;;QAIS,cAAS,GAAY,KAAK,CAAA;IAwDnC,CAAC;IApDO,MAAM,CAAC,gBAAgB,CAAC,OAAmC;;QACjE,MAAM,cAAc,GAAG;YACtB,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,CAAC,SAAS,CAAC;YACzB,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,QAAQ;YACvB,QAAQ,EAAE,cAAc;YACxB,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;SACM,CAAA;QAErB,YAAY;QACZ,OAAO,IAAI,CAAC,MAAA,IAAI,CAAC,KAAK,mCAAI,IAAI,CAAC,iCAC3B,cAAc,GACd,OAAO,EACW,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,OAAyB;QACjD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QAErB,KAAK,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;YAE9B,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;YAElC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACrB,OAAM;YACP,CAAC;QACF,CAAC;IACF,CAAC;IAES,KAAK,CAAC,IAAI,CAAC,UAAkB;QACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAA;IACtE,CAAC;IAEO,UAAU,CACjB,OAAiC,EACjC,UAAkB;QAElB,IAAI,CAAC,WAAW,GAAG,OAAc,CAAA;QACjC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAC/C,CAAC;IAEM,IAAI;;QACV,MAAA,IAAI,CAAC,WAAW,oDAAI,CAAA;QACpB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;IACvB,CAAC;CACD;AA5DD,uCA4DC"}
|
|
@@ -7,6 +7,12 @@ export default class TimeMarkerOutletTest extends AbstractSpruceTest {
|
|
|
7
7
|
protected static canOverrideDefaultOptions(): Promise<void>;
|
|
8
8
|
protected static pushingSingleMarkerIncrementsHitCountAndWaitTime(): Promise<void>;
|
|
9
9
|
protected static pushingTwoMarkersIncrementsHitCountAndWaitTimeTwice(): Promise<void>;
|
|
10
|
-
|
|
10
|
+
protected static canStopTimeMarkersMidPush(bailIdx: number): Promise<void>;
|
|
11
|
+
protected static canStartAgainAfterStopping(): Promise<void>;
|
|
12
|
+
protected static doesNotWaitIfStopped(): Promise<void>;
|
|
13
|
+
protected static clearsTheTimeoutOnStop(): Promise<void>;
|
|
14
|
+
private static setupTimeMarkerImpl;
|
|
15
|
+
private static pushTotalMarkers;
|
|
16
|
+
private static generateDurationMarkerValues;
|
|
11
17
|
private static Outlet;
|
|
12
18
|
}
|
|
@@ -66,22 +66,69 @@ class TimeMarkerOutletTest extends test_utils_1.default {
|
|
|
66
66
|
test_utils_1.assert.isEqualDeep(outlet.spyOptions, options);
|
|
67
67
|
}
|
|
68
68
|
static async pushingSingleMarkerIncrementsHitCountAndWaitTime() {
|
|
69
|
-
const markers = [this.
|
|
69
|
+
const markers = [this.generateDurationMarkerValues()];
|
|
70
70
|
await this.outlet.pushMarkers(markers);
|
|
71
71
|
test_utils_1.assert.isEqual(this.fakeLiblsl.pushSampleStrtHitCount, 1);
|
|
72
72
|
test_utils_1.assert.isEqual(this.outlet.totalWaitTimeMs, markers[0].durationMs);
|
|
73
73
|
}
|
|
74
74
|
static async pushingTwoMarkersIncrementsHitCountAndWaitTimeTwice() {
|
|
75
|
-
const markers =
|
|
76
|
-
this.generateRandomDurationMarker(),
|
|
77
|
-
this.generateRandomDurationMarker(),
|
|
78
|
-
];
|
|
79
|
-
await this.outlet.pushMarkers(markers);
|
|
75
|
+
const markers = await this.pushTotalMarkers(2);
|
|
80
76
|
test_utils_1.assert.isEqual(this.fakeLiblsl.pushSampleStrtHitCount, 2);
|
|
81
77
|
test_utils_1.assert.isEqual(this.outlet.totalWaitTimeMs, markers[0].durationMs + markers[1].durationMs);
|
|
82
78
|
}
|
|
83
|
-
static
|
|
84
|
-
|
|
79
|
+
static async canStopTimeMarkersMidPush(bailIdx) {
|
|
80
|
+
let hitCount = 0;
|
|
81
|
+
this.outlet.pushSample = () => {
|
|
82
|
+
hitCount += 1;
|
|
83
|
+
if (hitCount === bailIdx) {
|
|
84
|
+
this.outlet.stop();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
await this.pushTotalMarkers(10);
|
|
88
|
+
test_utils_1.assert.isEqual(hitCount, bailIdx);
|
|
89
|
+
}
|
|
90
|
+
static async canStartAgainAfterStopping() {
|
|
91
|
+
this.outlet.stop();
|
|
92
|
+
let hitCount = 0;
|
|
93
|
+
this.outlet.pushSample = () => {
|
|
94
|
+
hitCount++;
|
|
95
|
+
};
|
|
96
|
+
await this.pushTotalMarkers(10);
|
|
97
|
+
test_utils_1.assert.isEqual(hitCount, 10);
|
|
98
|
+
}
|
|
99
|
+
static async doesNotWaitIfStopped() {
|
|
100
|
+
this.setupTimeMarkerImpl();
|
|
101
|
+
const startMs = Date.now();
|
|
102
|
+
const promise = this.pushTotalMarkers(2, 1000);
|
|
103
|
+
this.outlet.stop();
|
|
104
|
+
await promise;
|
|
105
|
+
const endMs = Date.now();
|
|
106
|
+
test_utils_1.assert.isBelow(endMs - startMs, 10);
|
|
107
|
+
}
|
|
108
|
+
static async clearsTheTimeoutOnStop() {
|
|
109
|
+
this.setupTimeMarkerImpl();
|
|
110
|
+
const promise = this.pushTotalMarkers(2, 100);
|
|
111
|
+
this.outlet.stop();
|
|
112
|
+
this.outlet.pushSample = () => test_utils_1.assert.fail('Should not have been called');
|
|
113
|
+
await promise;
|
|
114
|
+
await this.wait(100);
|
|
115
|
+
}
|
|
116
|
+
static setupTimeMarkerImpl() {
|
|
117
|
+
TimeMarkerOutlet_1.default.Class = TimeMarkerOutlet_1.default;
|
|
118
|
+
this.outlet = this.Outlet();
|
|
119
|
+
}
|
|
120
|
+
static async pushTotalMarkers(total, durationMs) {
|
|
121
|
+
const markers = new Array(total)
|
|
122
|
+
.fill(null)
|
|
123
|
+
.map(() => this.generateDurationMarkerValues(durationMs));
|
|
124
|
+
await this.outlet.pushMarkers(markers);
|
|
125
|
+
return markers;
|
|
126
|
+
}
|
|
127
|
+
static generateDurationMarkerValues(durationMs) {
|
|
128
|
+
return {
|
|
129
|
+
name: (0, test_utils_1.generateId)(),
|
|
130
|
+
durationMs: durationMs !== null && durationMs !== void 0 ? durationMs : (0, crypto_1.randomInt)(100, 1000),
|
|
131
|
+
};
|
|
85
132
|
}
|
|
86
133
|
static Outlet(options) {
|
|
87
134
|
return TimeMarkerOutlet_1.default.TimeMarkerOutlet(options);
|
|
@@ -100,6 +147,20 @@ __decorate([
|
|
|
100
147
|
__decorate([
|
|
101
148
|
(0, test_utils_1.test)()
|
|
102
149
|
], TimeMarkerOutletTest, "pushingTwoMarkersIncrementsHitCountAndWaitTimeTwice", null);
|
|
150
|
+
__decorate([
|
|
151
|
+
(0, test_utils_1.test)('can stop on the first marker', 1),
|
|
152
|
+
(0, test_utils_1.test)('can stop on the second marker', 2),
|
|
153
|
+
(0, test_utils_1.test)('can stop on the third marker', 3)
|
|
154
|
+
], TimeMarkerOutletTest, "canStopTimeMarkersMidPush", null);
|
|
155
|
+
__decorate([
|
|
156
|
+
(0, test_utils_1.test)()
|
|
157
|
+
], TimeMarkerOutletTest, "canStartAgainAfterStopping", null);
|
|
158
|
+
__decorate([
|
|
159
|
+
(0, test_utils_1.test)()
|
|
160
|
+
], TimeMarkerOutletTest, "doesNotWaitIfStopped", null);
|
|
161
|
+
__decorate([
|
|
162
|
+
(0, test_utils_1.test)()
|
|
163
|
+
], TimeMarkerOutletTest, "clearsTheTimeoutOnStop", null);
|
|
103
164
|
class SpyTimeMarkerOutlet extends TimeMarkerOutlet_1.default {
|
|
104
165
|
constructor(options) {
|
|
105
166
|
super(options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeMarkerOutlet.test.js","sourceRoot":"","sources":["../../../src/__tests__/behavioral/TimeMarkerOutlet.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAAkC;AAClC,qEAI+B;AAC/B,kEAAyC;AACzC,0DAAqC;AAErC,8EAAyD;AACzD,yGAAgF;AAEhF,MAAqB,oBAAqB,SAAQ,oBAAkB;IAIzD,MAAM,CAAC,KAAK,CAAC,UAAU;QAChC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAA;QACxB,0BAAoB,CAAC,KAAK,GAAG,mBAAmB,CAAA;QAChD,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAU,EAAE,CAAA;QAClC,gBAAU,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACvC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IAC5B,CAAC;IAGsB,AAAb,MAAM,CAAC,KAAK,CAAC,kCAAkC;QACxD,mBAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;YAC1C,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,SAAS;YACf,YAAY,EAAE,CAAC,SAAS,CAAC;YACzB,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,QAAQ;YACvB,QAAQ,EAAE,cAAc;YACxB,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;SACd,CAAC,CAAA;IACH,CAAC;IAGsB,AAAb,MAAM,CAAC,KAAK,CAAC,yBAAyB;QAC/C,MAAM,OAAO,GAAG,IAAA,qCAA2B,GAAE,CAAA;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACnC,mBAAM,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC/C,CAAC;IAGsB,AAAb,MAAM,CAAC,KAAK,CAAC,gDAAgD;QACtE,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAA;QACrD,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"TimeMarkerOutlet.test.js","sourceRoot":"","sources":["../../../src/__tests__/behavioral/TimeMarkerOutlet.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/TimeMarkerOutlet.ts
CHANGED
|
@@ -4,6 +4,10 @@ export default class TimeMarkerOutletImpl
|
|
|
4
4
|
extends LslOutletImpl
|
|
5
5
|
implements TimeMarkerOutlet
|
|
6
6
|
{
|
|
7
|
+
private isPlaying: boolean = false
|
|
8
|
+
private waitResolve?: () => void
|
|
9
|
+
private timeout?: any
|
|
10
|
+
|
|
7
11
|
public static TimeMarkerOutlet(options?: Partial<LslOutletOptions>) {
|
|
8
12
|
const defaultOptions = {
|
|
9
13
|
name: 'Time markers',
|
|
@@ -26,14 +30,35 @@ export default class TimeMarkerOutletImpl
|
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
public async pushMarkers(markers: DurationMarker[]) {
|
|
33
|
+
this.isPlaying = true
|
|
34
|
+
|
|
29
35
|
for (let marker of markers) {
|
|
30
36
|
this.pushSample([marker.name])
|
|
37
|
+
|
|
31
38
|
await this.wait(marker.durationMs)
|
|
39
|
+
|
|
40
|
+
if (!this.isPlaying) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
32
43
|
}
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
protected async wait(durationMs: number) {
|
|
36
|
-
return new Promise((resolve) => setTimeout(resolve, durationMs))
|
|
47
|
+
return new Promise((resolve) => this.setTimeout(resolve, durationMs))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private setTimeout(
|
|
51
|
+
resolve: (value: unknown) => void,
|
|
52
|
+
durationMs: number
|
|
53
|
+
): void {
|
|
54
|
+
this.waitResolve = resolve as any
|
|
55
|
+
this.timeout = setTimeout(resolve, durationMs)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public stop(): void {
|
|
59
|
+
this.waitResolve?.()
|
|
60
|
+
clearTimeout(this.timeout)
|
|
61
|
+
this.isPlaying = false
|
|
37
62
|
}
|
|
38
63
|
}
|
|
39
64
|
|
|
@@ -44,4 +69,5 @@ export interface DurationMarker {
|
|
|
44
69
|
|
|
45
70
|
export interface TimeMarkerOutlet {
|
|
46
71
|
pushMarkers(markers: DurationMarker[]): Promise<void>
|
|
72
|
+
stop(): void
|
|
47
73
|
}
|
|
@@ -47,19 +47,17 @@ export default class TimeMarkerOutletTest extends AbstractSpruceTest {
|
|
|
47
47
|
|
|
48
48
|
@test()
|
|
49
49
|
protected static async pushingSingleMarkerIncrementsHitCountAndWaitTime() {
|
|
50
|
-
const markers = [this.
|
|
50
|
+
const markers = [this.generateDurationMarkerValues()]
|
|
51
51
|
await this.outlet.pushMarkers(markers)
|
|
52
|
+
|
|
52
53
|
assert.isEqual(this.fakeLiblsl.pushSampleStrtHitCount, 1)
|
|
53
54
|
assert.isEqual(this.outlet.totalWaitTimeMs, markers[0].durationMs)
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
@test()
|
|
57
58
|
protected static async pushingTwoMarkersIncrementsHitCountAndWaitTimeTwice() {
|
|
58
|
-
const markers =
|
|
59
|
-
|
|
60
|
-
this.generateRandomDurationMarker(),
|
|
61
|
-
]
|
|
62
|
-
await this.outlet.pushMarkers(markers)
|
|
59
|
+
const markers = await this.pushTotalMarkers(2)
|
|
60
|
+
|
|
63
61
|
assert.isEqual(this.fakeLiblsl.pushSampleStrtHitCount, 2)
|
|
64
62
|
assert.isEqual(
|
|
65
63
|
this.outlet.totalWaitTimeMs,
|
|
@@ -67,8 +65,88 @@ export default class TimeMarkerOutletTest extends AbstractSpruceTest {
|
|
|
67
65
|
)
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
@test('can stop on the first marker', 1)
|
|
69
|
+
@test('can stop on the second marker', 2)
|
|
70
|
+
@test('can stop on the third marker', 3)
|
|
71
|
+
protected static async canStopTimeMarkersMidPush(bailIdx: number) {
|
|
72
|
+
let hitCount = 0
|
|
73
|
+
|
|
74
|
+
this.outlet.pushSample = () => {
|
|
75
|
+
hitCount += 1
|
|
76
|
+
if (hitCount === bailIdx) {
|
|
77
|
+
this.outlet.stop()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await this.pushTotalMarkers(10)
|
|
82
|
+
|
|
83
|
+
assert.isEqual(hitCount, bailIdx)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@test()
|
|
87
|
+
protected static async canStartAgainAfterStopping() {
|
|
88
|
+
this.outlet.stop()
|
|
89
|
+
|
|
90
|
+
let hitCount = 0
|
|
91
|
+
|
|
92
|
+
this.outlet.pushSample = () => {
|
|
93
|
+
hitCount++
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await this.pushTotalMarkers(10)
|
|
97
|
+
|
|
98
|
+
assert.isEqual(hitCount, 10)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@test()
|
|
102
|
+
protected static async doesNotWaitIfStopped() {
|
|
103
|
+
this.setupTimeMarkerImpl()
|
|
104
|
+
|
|
105
|
+
const startMs = Date.now()
|
|
106
|
+
|
|
107
|
+
const promise = this.pushTotalMarkers(2, 1000)
|
|
108
|
+
|
|
109
|
+
this.outlet.stop()
|
|
110
|
+
|
|
111
|
+
await promise
|
|
112
|
+
|
|
113
|
+
const endMs = Date.now()
|
|
114
|
+
assert.isBelow(endMs - startMs, 10)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@test()
|
|
118
|
+
protected static async clearsTheTimeoutOnStop() {
|
|
119
|
+
this.setupTimeMarkerImpl()
|
|
120
|
+
|
|
121
|
+
const promise = this.pushTotalMarkers(2, 100)
|
|
122
|
+
|
|
123
|
+
this.outlet.stop()
|
|
124
|
+
this.outlet.pushSample = () => assert.fail('Should not have been called')
|
|
125
|
+
|
|
126
|
+
await promise
|
|
127
|
+
await this.wait(100)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private static setupTimeMarkerImpl() {
|
|
131
|
+
TimeMarkerOutletImpl.Class = TimeMarkerOutletImpl as any
|
|
132
|
+
this.outlet = this.Outlet()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private static async pushTotalMarkers(total: number, durationMs?: number) {
|
|
136
|
+
const markers = new Array(total)
|
|
137
|
+
.fill(null)
|
|
138
|
+
.map(() => this.generateDurationMarkerValues(durationMs))
|
|
139
|
+
|
|
140
|
+
await this.outlet.pushMarkers(markers)
|
|
141
|
+
|
|
142
|
+
return markers
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private static generateDurationMarkerValues(durationMs?: number) {
|
|
146
|
+
return {
|
|
147
|
+
name: generateId(),
|
|
148
|
+
durationMs: durationMs ?? randomInt(100, 1000),
|
|
149
|
+
}
|
|
72
150
|
}
|
|
73
151
|
|
|
74
152
|
private static Outlet(options?: Partial<LslOutletOptions>) {
|