1
1
// tslint:disable:no-invalid-template-strings
2
+ import { EMPTY , Subject } from 'rxjs' ;
3
+ import { BeforeModelDestroyedEvent } from '../../model/events/before-model-destroyed-event' ;
2
4
import { ModelChangedEvent } from '../../model/events/model-changed-event' ;
3
5
import { ModelManager } from '../../model/manager/model-manager' ;
4
6
import { PropertyLocation } from '../../model/property/property-location' ;
@@ -11,13 +13,15 @@ describe('Variable manager', () => {
11
13
let mockLogger : Partial < Logger > ;
12
14
let mockModelManager : Partial < ModelManager > ;
13
15
let mockModelChangedEvent : Partial < ModelChangedEvent > ;
16
+ let mockBeforeModelDestroyedEvent : Partial < BeforeModelDestroyedEvent > ;
14
17
const model = { } ;
15
18
const parent = { } ;
16
19
const root = { } ;
17
20
18
21
beforeEach ( ( ) => {
19
22
mockLogger = {
20
- warn : jest . fn ( )
23
+ warn : jest . fn ( ) ,
24
+ error : jest . fn ( )
21
25
} ;
22
26
mockModelChangedEvent = {
23
27
publishChange : jest . fn ( )
@@ -35,10 +39,15 @@ describe('Variable manager', () => {
35
39
} )
36
40
} ;
37
41
42
+ mockBeforeModelDestroyedEvent = {
43
+ getBeforeDestructionObservable : jest . fn ( )
44
+ } ;
45
+
38
46
manager = new VariableManager (
39
47
mockLogger as Logger ,
40
48
mockModelManager as ModelManager ,
41
- mockModelChangedEvent as ModelChangedEvent
49
+ mockModelChangedEvent as ModelChangedEvent ,
50
+ mockBeforeModelDestroyedEvent as BeforeModelDestroyedEvent
42
51
) ;
43
52
} ) ;
44
53
@@ -106,6 +115,7 @@ describe('Variable manager reference tracking', () => {
106
115
let mockLogger : PartialObjectMock < Logger > ;
107
116
let mockModelManager : PartialObjectMock < ModelManager > ;
108
117
let mockModelChangedEvent : PartialObjectMock < ModelChangedEvent > ;
118
+ let mockBeforeModelDestroyedEvent : Partial < BeforeModelDestroyedEvent > ;
109
119
110
120
let mockParentLocation : PartialObjectMock < PropertyLocation > ;
111
121
const parent = { } ;
@@ -132,6 +142,10 @@ describe('Variable manager reference tracking', () => {
132
142
)
133
143
} ;
134
144
145
+ mockBeforeModelDestroyedEvent = {
146
+ getBeforeDestructionObservable : jest . fn ( ) . mockReturnValue ( EMPTY )
147
+ } ;
148
+
135
149
mockModelLocation = {
136
150
parentModel : model ,
137
151
setProperty : jest . fn ( ) ,
@@ -147,7 +161,8 @@ describe('Variable manager reference tracking', () => {
147
161
manager = new VariableManager (
148
162
mockLogger as Logger ,
149
163
mockModelManager as ModelManager ,
150
- mockModelChangedEvent as ModelChangedEvent
164
+ mockModelChangedEvent as ModelChangedEvent ,
165
+ mockBeforeModelDestroyedEvent as BeforeModelDestroyedEvent
151
166
) ;
152
167
} ) ;
153
168
@@ -323,4 +338,45 @@ describe('Variable manager reference tracking', () => {
323
338
'Attempted to resolve reference at modelProp which does not contain a registered reference'
324
339
) ;
325
340
} ) ;
341
+
342
+ test ( 'removes dangling references after a model is destroyed' , ( ) => {
343
+ const destroySubject = new Subject ( ) ;
344
+ mockBeforeModelDestroyedEvent . getBeforeDestructionObservable = jest
345
+ . fn ( )
346
+ . mockReturnValue ( destroySubject . asObservable ( ) ) ;
347
+
348
+ manager . registerReference ( mockModelLocation as PropertyLocation , '${test}' ) ;
349
+ manager . set ( 'test' , 'foo' , parent ) ;
350
+
351
+ destroySubject . next ( model ) ;
352
+ destroySubject . complete ( ) ;
353
+
354
+ // Reference should no longer be tracked
355
+ expect ( manager . isVariableReference ( mockModelLocation as PropertyLocation ) ) . toBe ( false ) ;
356
+
357
+ // Setting a value should not call model manager or set property
358
+ ( mockModelManager . getParent as jest . Mock ) . mockClear ( ) ;
359
+ manager . set ( 'test' , 'bar' , parent ) ;
360
+
361
+ expect ( mockModelManager . getParent ) . not . toHaveBeenCalled ( ) ;
362
+ expect ( mockModelLocation . setProperty ) . not . toHaveBeenCalledWith ( 'bar' ) ;
363
+ } ) ;
364
+
365
+ test ( 'dangling reference removal handles case where reference previously removed' , ( ) => {
366
+ const destroySubject = new Subject ( ) ;
367
+ mockBeforeModelDestroyedEvent . getBeforeDestructionObservable = jest
368
+ . fn ( )
369
+ . mockReturnValue ( destroySubject . asObservable ( ) ) ;
370
+
371
+ manager . registerReference ( mockModelLocation as PropertyLocation , '${test}' ) ;
372
+ manager . set ( 'test' , 'foo' , parent ) ;
373
+ manager . deregisterReference ( mockModelLocation as PropertyLocation ) ;
374
+
375
+ // Reference should no longer be tracked
376
+ expect ( manager . isVariableReference ( mockModelLocation as PropertyLocation ) ) . toBe ( false ) ;
377
+
378
+ destroySubject . next ( model ) ;
379
+ destroySubject . complete ( ) ;
380
+ expect ( mockLogger . error ) . not . toHaveBeenCalled ( ) ;
381
+ } ) ;
326
382
} ) ;
0 commit comments