@@ -21,7 +21,7 @@ import * as testData from '../tests/test_data';
21
21
import { createProjectConfig } from './project_config' ;
22
22
import { resolvablePromise } from '../utils/promise/resolvablePromise' ;
23
23
import { getMockDatafileManager } from '../tests/mock/mockDatafileManager' ;
24
- import exp from 'constants ' ;
24
+ import { wait } from '../../tests/testUtils ' ;
25
25
26
26
const cloneDeep = ( x : any ) => JSON . parse ( JSON . stringify ( x ) ) ;
27
27
@@ -30,54 +30,54 @@ describe('ProjectConfigManagerImpl', () => {
30
30
const logger = getMockLogger ( ) ;
31
31
const manager = new ProjectConfigManagerImpl ( { logger} ) ;
32
32
manager . start ( ) ;
33
- await expect ( manager . onRunning ( ) ) . rejects . toBeTruthy ( ) ;
33
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
34
34
expect ( logger . error ) . toHaveBeenCalled ( ) ;
35
35
} ) ;
36
36
37
37
it ( 'should set status to Failed if neither datafile nor a datafileManager is passed into the constructor' , async ( ) => {
38
38
const logger = getMockLogger ( ) ;
39
39
const manager = new ProjectConfigManagerImpl ( { logger} ) ;
40
40
manager . start ( ) ;
41
- await expect ( manager . onRunning ( ) ) . rejects . toBeTruthy ( ) ;
41
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
42
42
expect ( manager . getState ( ) ) . toBe ( ServiceState . Failed ) ;
43
43
} ) ;
44
44
45
- it ( 'should reject onTerminated' , async ( ) => {
45
+ it ( 'should reject onTerminated if neither datafile nor a datafileManager is passed into the constructor ' , async ( ) => {
46
46
const logger = getMockLogger ( ) ;
47
47
const manager = new ProjectConfigManagerImpl ( { logger} ) ;
48
48
manager . start ( ) ;
49
- await expect ( manager . onTerminated ( ) ) . rejects . toBeTruthy ( ) ;
49
+ await expect ( manager . onTerminated ( ) ) . rejects . toThrow ( ) ;
50
50
} ) ;
51
51
52
52
describe ( 'when constructed with only a datafile' , ( ) => {
53
53
it ( 'should reject onRunning() and log error if the datafile is invalid' , async ( ) => {
54
54
const logger = getMockLogger ( ) ;
55
55
const manager = new ProjectConfigManagerImpl ( { logger, datafile : { } } ) ;
56
56
manager . start ( ) ;
57
- await expect ( manager . onRunning ( ) ) . rejects . toBeTruthy ( ) ;
57
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
58
58
expect ( logger . error ) . toHaveBeenCalled ( ) ;
59
59
} ) ;
60
60
61
61
it ( 'should set status to Failed if the datafile is invalid' , async ( ) => {
62
62
const logger = getMockLogger ( ) ;
63
63
const manager = new ProjectConfigManagerImpl ( { logger, datafile : { } } ) ;
64
64
manager . start ( ) ;
65
- await expect ( manager . onRunning ( ) ) . rejects . toBeTruthy ( ) ;
65
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
66
66
expect ( manager . getState ( ) ) . toBe ( ServiceState . Failed ) ;
67
67
} ) ;
68
68
69
69
it ( 'should reject onTerminated if the datafile is invalid' , async ( ) => {
70
70
const logger = getMockLogger ( ) ;
71
71
const manager = new ProjectConfigManagerImpl ( { logger} ) ;
72
72
manager . start ( ) ;
73
- await expect ( manager . onTerminated ( ) ) . rejects . toBeTruthy ( ) ;
73
+ await expect ( manager . onTerminated ( ) ) . rejects . toThrow ( ) ;
74
74
} ) ;
75
75
76
76
it ( 'should fulfill onRunning() and set status to Running if the datafile is valid' , async ( ) => {
77
77
const logger = getMockLogger ( ) ;
78
78
const manager = new ProjectConfigManagerImpl ( { logger, datafile : testData . getTestProjectConfig ( ) } ) ;
79
79
manager . start ( ) ;
80
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
80
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
81
81
expect ( manager . getState ( ) ) . toBe ( ServiceState . Running ) ;
82
82
} ) ;
83
83
@@ -123,7 +123,7 @@ describe('ProjectConfigManagerImpl', () => {
123
123
manager . start ( ) ;
124
124
125
125
expect ( datafileManager . onRunning ) . toHaveBeenCalled ( ) ;
126
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
126
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
127
127
} ) ;
128
128
129
129
it ( 'should resolve onRunning() even if datafileManger.onRunning() rejects' , async ( ) => {
@@ -136,7 +136,7 @@ describe('ProjectConfigManagerImpl', () => {
136
136
manager . start ( ) ;
137
137
138
138
expect ( datafileManager . onRunning ) . toHaveBeenCalled ( ) ;
139
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
139
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
140
140
} ) ;
141
141
142
142
it ( 'should call the onUpdate handler before datafileManger.onRunning() resolves' , async ( ) => {
@@ -149,7 +149,7 @@ describe('ProjectConfigManagerImpl', () => {
149
149
const manager = new ProjectConfigManagerImpl ( { datafile : testData . getTestProjectConfig ( ) , datafileManager } ) ;
150
150
manager . start ( ) ;
151
151
manager . onUpdate ( listener ) ;
152
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
152
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
153
153
expect ( listener ) . toHaveBeenCalledWith ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
154
154
} ) ;
155
155
@@ -180,7 +180,7 @@ describe('ProjectConfigManagerImpl', () => {
180
180
const manager = new ProjectConfigManagerImpl ( { datafile : { } , datafileManager } ) ;
181
181
manager . start ( ) ;
182
182
datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
183
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
183
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
184
184
expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
185
185
} ) ;
186
186
@@ -192,10 +192,27 @@ describe('ProjectConfigManagerImpl', () => {
192
192
manager . onUpdate ( listener ) ;
193
193
194
194
datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
195
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
195
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
196
196
expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
197
197
expect ( listener ) . toHaveBeenCalledWith ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
198
198
} ) ;
199
+
200
+ it ( 'should return undefined from getConfig() before onRunning() resolves' , async ( ) => {
201
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) } ) ;
202
+ const manager = new ProjectConfigManagerImpl ( { datafile : { } , datafileManager } ) ;
203
+ manager . start ( ) ;
204
+ expect ( manager . getConfig ( ) ) . toBeUndefined ( ) ;
205
+ } ) ;
206
+
207
+ it ( 'should return the correct config from getConfig() after onRunning() resolves' , async ( ) => {
208
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) } ) ;
209
+ const manager = new ProjectConfigManagerImpl ( { datafile : { } , datafileManager } ) ;
210
+ manager . start ( ) ;
211
+
212
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
213
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
214
+ expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
215
+ } ) ;
199
216
} ) ;
200
217
} ) ;
201
218
@@ -215,10 +232,27 @@ describe('ProjectConfigManagerImpl', () => {
215
232
manager . onUpdate ( listener ) ;
216
233
217
234
datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
218
- await expect ( manager . onRunning ( ) ) . resolves . toBeUndefined ( ) ;
235
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
219
236
expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
220
237
expect ( listener ) . toHaveBeenCalledWith ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
221
238
} ) ;
239
+
240
+ it ( 'should return undefined from getConfig() before onRunning() resolves' , async ( ) => {
241
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) } ) ;
242
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
243
+ manager . start ( ) ;
244
+ expect ( manager . getConfig ( ) ) . toBeUndefined ( ) ;
245
+ } ) ;
246
+
247
+ it ( 'should return the correct config from getConfig() after onRunning() resolves' , async ( ) => {
248
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) } ) ;
249
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
250
+ manager . start ( ) ;
251
+
252
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
253
+ await expect ( manager . onRunning ( ) ) . resolves . not . toThrow ( ) ;
254
+ expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( testData . getTestProjectConfig ( ) ) ) ;
255
+ } ) ;
222
256
} ) ;
223
257
224
258
it ( 'should update the config and call onUpdate handlers when datafileManager onUpdate is fired with valid datafile' , async ( ) => {
@@ -347,6 +381,117 @@ describe('ProjectConfigManagerImpl', () => {
347
381
expect ( listener ) . toHaveBeenCalledWith ( createProjectConfig ( datafile ) ) ;
348
382
expect ( manager . getConfig ( ) ) . toEqual ( createProjectConfig ( datafile ) ) ;
349
383
} ) ;
384
+
385
+ describe ( 'stop()' , ( ) => {
386
+ it ( 'should reject onRunning() if stop is called when the datafileManager state is New' , async ( ) => {
387
+ const datafileManager = getMockDatafileManager ( { } ) ;
388
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
389
+
390
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . New ) ;
391
+ manager . stop ( ) ;
392
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
393
+ } ) ;
394
+
395
+ it ( 'should reject onRunning() if stop is called when the datafileManager state is Starting' , async ( ) => {
396
+ const datafileManager = getMockDatafileManager ( { } ) ;
397
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
398
+
399
+ manager . start ( ) ;
400
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Starting ) ;
401
+ manager . stop ( ) ;
402
+ await expect ( manager . onRunning ( ) ) . rejects . toThrow ( ) ;
403
+ } ) ;
404
+
405
+ it ( 'should call datafileManager.stop()' , async ( ) => {
406
+ const datafileManager = getMockDatafileManager ( { } ) ;
407
+ const spy = vi . spyOn ( datafileManager , 'stop' ) ;
408
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
409
+ manager . start ( ) ;
410
+ manager . stop ( ) ;
411
+ expect ( spy ) . toHaveBeenCalled ( ) ;
412
+ } ) ;
413
+
414
+ it ( 'should set status to Terminated immediately if no datafile manager is provided and resolve onTerminated' , async ( ) => {
415
+ const manager = new ProjectConfigManagerImpl ( { datafile : testData . getTestProjectConfig ( ) } ) ;
416
+ manager . stop ( ) ;
417
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Terminated ) ;
418
+ await expect ( manager . onTerminated ( ) ) . resolves . not . toThrow ( ) ;
419
+ } ) ;
420
+
421
+ it ( 'should set status to Stopping while awaiting for datafileManager onTerminated' , async ( ) => {
422
+ const datafileManagerTerminated = resolvablePromise < void > ( ) ;
423
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) , onTerminated : datafileManagerTerminated . promise } ) ;
424
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
425
+ manager . start ( ) ;
426
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
427
+ await manager . onRunning ( ) ;
428
+ manager . stop ( ) ;
429
+
430
+ for ( let i = 0 ; i < 100 ; i ++ ) {
431
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Stopping ) ;
432
+ await wait ( 0 ) ;
433
+ }
434
+ } ) ;
435
+
436
+ it ( 'should set status to Terminated and resolve onTerminated after datafileManager.onTerminated() resolves' , async ( ) => {
437
+ const datafileManagerTerminated = resolvablePromise < void > ( ) ;
438
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) , onTerminated : datafileManagerTerminated . promise } ) ;
439
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
440
+ manager . start ( ) ;
441
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
442
+ await manager . onRunning ( ) ;
443
+ manager . stop ( ) ;
444
+
445
+ for ( let i = 0 ; i < 50 ; i ++ ) {
446
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Stopping ) ;
447
+ await wait ( 0 ) ;
448
+ }
449
+
450
+ datafileManagerTerminated . resolve ( ) ;
451
+ await expect ( manager . onTerminated ( ) ) . resolves . not . toThrow ( ) ;
452
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Terminated ) ;
453
+ } ) ;
454
+
455
+ it ( 'should set status to Failed and reject onTerminated after datafileManager.onTerminated() rejects' , async ( ) => {
456
+ const datafileManagerTerminated = resolvablePromise < void > ( ) ;
457
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) , onTerminated : datafileManagerTerminated . promise } ) ;
458
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
459
+ manager . start ( ) ;
460
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
461
+ await manager . onRunning ( ) ;
462
+ manager . stop ( ) ;
463
+
464
+ for ( let i = 0 ; i < 50 ; i ++ ) {
465
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Stopping ) ;
466
+ await wait ( 0 ) ;
467
+ }
468
+
469
+ datafileManagerTerminated . reject ( ) ;
470
+ await expect ( manager . onTerminated ( ) ) . rejects . toThrow ( ) ;
471
+ expect ( manager . getState ( ) ) . toBe ( ServiceState . Failed ) ;
472
+ } ) ;
473
+
474
+ it ( 'should not call onUpdate handlers after stop is called' , async ( ) => {
475
+ const datafileManagerTerminated = resolvablePromise < void > ( ) ;
476
+ const datafileManager = getMockDatafileManager ( { onRunning : Promise . resolve ( ) , onTerminated : datafileManagerTerminated . promise } ) ;
477
+ const manager = new ProjectConfigManagerImpl ( { datafileManager } ) ;
478
+ manager . start ( ) ;
479
+ const listener = vi . fn ( ) ;
480
+ manager . onUpdate ( listener ) ;
481
+
482
+ datafileManager . pushUpdate ( testData . getTestProjectConfig ( ) ) ;
483
+ await manager . onRunning ( ) ;
484
+
485
+ expect ( listener ) . toHaveBeenCalledTimes ( 1 ) ;
486
+ manager . stop ( ) ;
487
+ datafileManager . pushUpdate ( testData . getTestProjectConfigWithFeatures ( ) ) ;
488
+
489
+ datafileManagerTerminated . resolve ( ) ;
490
+ await expect ( manager . onTerminated ( ) ) . resolves . not . toThrow ( ) ;
491
+
492
+ expect ( listener ) . toHaveBeenCalledTimes ( 1 ) ;
493
+ } ) ;
494
+ } ) ;
350
495
} ) ;
351
496
352
497
// it('should call the error handler and fulfill onReady with an unsuccessful result if the datafile JSON is malformed', function() {
0 commit comments