@@ -8,16 +8,15 @@ class LifeCycleHooksTest extends RenderingTest {
8
8
super ( ) ;
9
9
this . hooks = [ ] ;
10
10
this . components = { } ;
11
+ this . teardownAssertions = [ ] ;
11
12
}
12
13
13
14
teardown ( ) {
14
- super ( ) ;
15
- this . assertHooks (
16
- 'destroy' ,
17
- [ 'the-top' , 'willDestroyElement' ] ,
18
- [ 'the-middle' , 'willDestroyElement' ] ,
19
- [ 'the-bottom' , 'willDestroyElement' ]
20
- ) ;
15
+ super . teardown ( ) ;
16
+
17
+ for ( let i = 0 ; i < this . teardownAssertions . length ; i ++ ) {
18
+ this . teardownAssertions [ i ] ( ) ;
19
+ }
21
20
}
22
21
23
22
/* abstract */
@@ -51,49 +50,90 @@ class LifeCycleHooksTest extends RenderingTest {
51
50
this . hooks . push ( hook ( name , hookName , args ) ) ;
52
51
} ;
53
52
53
+ let assertParentView = ( hookName , instance ) => {
54
+ if ( ! instance . parentView ) {
55
+ this . assert . ok ( false , `parentView should be present in ${ hookName } ` ) ;
56
+ }
57
+ } ;
58
+
59
+ let assertElement = ( hookName , instance ) => {
60
+ if ( instance . tagName === '' ) { return ; }
61
+
62
+ if ( ! instance . element ) {
63
+ this . assert . ok ( false , `element property should be present on ${ instance } during ${ hookName } ` ) ;
64
+ }
65
+
66
+ let inDOM = this . $ ( `#${ instance . elementId } ` ) [ 0 ] ;
67
+ if ( ! inDOM ) {
68
+ this . assert . ok ( false , `element for ${ instance } should be in the DOM during ${ hookName } ` ) ;
69
+ }
70
+ } ;
71
+
72
+ let assertNoElement = ( hookName , instance ) => {
73
+ if ( instance . element ) {
74
+ this . assert . ok ( false , `element should not be present in ${ hookName } ` ) ;
75
+ }
76
+ } ;
77
+
54
78
let ComponentClass = this . ComponentClass . extend ( {
55
79
init ( ) {
56
80
expectDeprecation ( ( ) => { this . _super ( ...arguments ) ; } ,
57
81
/ d i d I n i t A t t r s c a l l e d / ) ;
58
82
59
83
pushHook ( 'init' ) ;
60
84
pushComponent ( this ) ;
85
+ assertParentView ( 'init' , this ) ;
86
+ assertNoElement ( 'init' , this ) ;
61
87
} ,
62
88
63
89
didInitAttrs ( options ) {
64
90
pushHook ( 'didInitAttrs' , options ) ;
91
+ assertParentView ( 'didInitAttrs' , this ) ;
92
+ assertNoElement ( 'didInitAttrs' , this ) ;
65
93
} ,
66
94
67
95
didUpdateAttrs ( options ) {
68
96
pushHook ( 'didUpdateAttrs' , options ) ;
97
+ assertParentView ( 'didUpdateAttrs' , this ) ;
69
98
} ,
70
99
71
100
willUpdate ( options ) {
72
101
pushHook ( 'willUpdate' , options ) ;
102
+ assertParentView ( 'willUpdate' , this ) ;
73
103
} ,
74
104
75
105
didReceiveAttrs ( options ) {
76
106
pushHook ( 'didReceiveAttrs' , options ) ;
107
+ assertParentView ( 'didReceiveAttrs' , this ) ;
77
108
} ,
78
109
79
110
willRender ( ) {
80
111
pushHook ( 'willRender' ) ;
112
+ assertParentView ( 'willRender' , this ) ;
81
113
} ,
82
114
83
115
didRender ( ) {
84
116
pushHook ( 'didRender' ) ;
117
+ assertParentView ( 'didRender' , this ) ;
118
+ assertElement ( 'didRender' , this ) ;
85
119
} ,
86
120
87
121
didInsertElement ( ) {
88
122
pushHook ( 'didInsertElement' ) ;
123
+ assertParentView ( 'didInsertElement' , this ) ;
124
+ assertElement ( 'didInsertElement' , this ) ;
89
125
} ,
90
126
91
127
didUpdate ( options ) {
92
128
pushHook ( 'didUpdate' , options ) ;
129
+ assertParentView ( 'didUpdate' , this ) ;
130
+ assertElement ( 'didUpdate' , this ) ;
93
131
} ,
94
132
95
133
willDestroyElement ( ) {
96
134
pushHook ( 'willDestroyElement' ) ;
135
+ assertParentView ( 'willDestroyElement' , this ) ;
136
+ assertElement ( 'willDestroyElement' , this ) ;
97
137
}
98
138
} ) ;
99
139
@@ -341,6 +381,15 @@ class LifeCycleHooksTest extends RenderingTest {
341
381
[ 'the-top' , 'didRender' ]
342
382
343
383
) ;
384
+
385
+ this . teardownAssertions . push ( ( ) => {
386
+ this . assertHooks (
387
+ 'destroy' ,
388
+ [ 'the-top' , 'willDestroyElement' ] ,
389
+ [ 'the-middle' , 'willDestroyElement' ] ,
390
+ [ 'the-bottom' , 'willDestroyElement' ]
391
+ ) ;
392
+ } ) ;
344
393
}
345
394
346
395
[ '@test passing values through attrs causes lifecycle hooks to fire if the attribute values have changed' ] ( ) {
@@ -504,8 +553,105 @@ class LifeCycleHooksTest extends RenderingTest {
504
553
} else {
505
554
this . assertHooks ( 'after no-op rernder (root)' ) ;
506
555
}
556
+
557
+ this . teardownAssertions . push ( ( ) => {
558
+ this . assertHooks (
559
+ 'destroy' ,
560
+ [ 'the-top' , 'willDestroyElement' ] ,
561
+ [ 'the-middle' , 'willDestroyElement' ] ,
562
+ [ 'the-bottom' , 'willDestroyElement' ]
563
+ ) ;
564
+ } ) ;
507
565
}
508
566
567
+ [ '@test components rendered from `{{each}}` have correct life-cycle hooks to be called' ] ( ) {
568
+ let { invoke } = this . boundHelpers ;
569
+
570
+ this . registerComponent ( 'an-item' , { template : strip `
571
+ <div>Item: {{count}}</div>
572
+ ` } ) ;
573
+
574
+ this . registerComponent ( 'no-items' , { template : strip `
575
+ <div>Nothing to see here</div>
576
+ ` } ) ;
577
+
578
+ this . render ( strip `
579
+ {{#each items as |item|}}
580
+ ${ invoke ( 'an-item' , { count : expr ( 'item' ) } ) }
581
+ {{else}}
582
+ ${ invoke ( 'no-items' ) }
583
+ {{/each}}
584
+ ` , {
585
+ items : [ 1 , 2 , 3 , 4 , 5 ]
586
+ } ) ;
587
+
588
+ this . assertText ( 'Item: 1Item: 2Item: 3Item: 4Item: 5' ) ;
589
+
590
+ let initialHooks = ( count ) => {
591
+ return [
592
+ [ 'an-item' , 'init' ] ,
593
+ [ 'an-item' , 'didInitAttrs' , { attrs : { count } } ] ,
594
+ [ 'an-item' , 'didReceiveAttrs' , { newAttrs : { count } } ] ,
595
+ [ 'an-item' , 'willRender' ]
596
+ ] ;
597
+ } ;
598
+
599
+ let initialAfterRenderHooks = ( count ) => {
600
+ return [
601
+ [ 'an-item' , 'didInsertElement' ] ,
602
+ [ 'an-item' , 'didRender' ]
603
+ ] ;
604
+ } ;
605
+
606
+ this . assertHooks (
607
+
608
+ 'after initial render' ,
609
+
610
+ // Sync hooks
611
+ ...initialHooks ( 1 ) ,
612
+ ...initialHooks ( 2 ) ,
613
+ ...initialHooks ( 3 ) ,
614
+ ...initialHooks ( 4 ) ,
615
+ ...initialHooks ( 5 ) ,
616
+
617
+ // Async hooks
618
+ ...initialAfterRenderHooks ( 5 ) ,
619
+ ...initialAfterRenderHooks ( 4 ) ,
620
+ ...initialAfterRenderHooks ( 3 ) ,
621
+ ...initialAfterRenderHooks ( 2 ) ,
622
+ ...initialAfterRenderHooks ( 1 )
623
+ ) ;
624
+
625
+ this . runTask ( ( ) => set ( this . context , 'items' , [ ] ) ) ;
626
+
627
+ this . assertText ( 'Nothing to see here' ) ;
628
+
629
+ this . assertHooks (
630
+ 'reset to empty array' ,
631
+
632
+ [ 'an-item' , 'willDestroyElement' ] ,
633
+ [ 'an-item' , 'willDestroyElement' ] ,
634
+ [ 'an-item' , 'willDestroyElement' ] ,
635
+ [ 'an-item' , 'willDestroyElement' ] ,
636
+ [ 'an-item' , 'willDestroyElement' ] ,
637
+
638
+ [ 'no-items' , 'init' ] ,
639
+ [ 'no-items' , 'didInitAttrs' , { attrs : { } } ] ,
640
+ [ 'no-items' , 'didReceiveAttrs' , { newAttrs : { } } ] ,
641
+ [ 'no-items' , 'willRender' ] ,
642
+
643
+ [ 'no-items' , 'didInsertElement' ] ,
644
+ [ 'no-items' , 'didRender' ]
645
+ ) ;
646
+
647
+ this . teardownAssertions . push ( ( ) => {
648
+ this . assertHooks (
649
+ 'destroy' ,
650
+
651
+ [ 'no-items' , 'willDestroyElement' ]
652
+ ) ;
653
+ } ) ;
654
+ }
509
655
}
510
656
511
657
moduleFor ( 'Components test: lifecycle hooks (curly components)' , class extends LifeCycleHooksTest {
0 commit comments