1- import  { inject ,  ComponentFixture ,  TestBed ,   async }  from  '@angular/core/testing' ; 
1+ import  { inject ,  ComponentFixture ,  TestBed }  from  '@angular/core/testing' ; 
22import  { 
33  NgModule , 
44  Component , 
@@ -20,13 +20,11 @@ import {DomPortalOutlet} from './dom-portal-outlet';
2020
2121describe ( 'Portals' ,  ( )  =>  { 
2222
23-   beforeEach ( async ( ( )  =>  { 
24-     TestBed . configureTestingModule ( { 
25-       imports : [ PortalModule ,  PortalTestModule ] , 
26-     } ) ; 
27- 
28-     TestBed . compileComponents ( ) ; 
29-   } ) ) ; 
23+   beforeEach ( ( )  =>  { 
24+     TestBed 
25+       . configureTestingModule ( { imports : [ PortalModule ,  PortalTestModule ] } ) 
26+       . compileComponents ( ) ; 
27+   } ) ; 
3028
3129  describe ( 'CdkPortalOutlet' ,  ( )  =>  { 
3230    let  fixture : ComponentFixture < PortalTestApp > ; 
@@ -37,28 +35,33 @@ describe('Portals', () => {
3735
3836    it ( 'should load a component into the portal' ,  ( )  =>  { 
3937      // Set the selectedHost to be a ComponentPortal. 
40-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
41-       testAppComponent . selectedPortal  =  new  ComponentPortal ( PizzaMsg ) ; 
38+       let  testAppComponent  =  fixture . componentInstance ; 
39+       let  componentPortal  =  new  ComponentPortal ( PizzaMsg ) ; 
40+       let  hostContainer  =  fixture . nativeElement . querySelector ( '.portal-container' ) ; 
41+ 
42+       testAppComponent . selectedPortal  =  componentPortal ; 
4243      fixture . detectChanges ( ) ; 
4344
4445      // Expect that the content of the attached portal is present. 
45-       let  hostContainer  =  fixture . nativeElement . querySelector ( '.portal-container' ) ; 
4646      expect ( hostContainer . textContent ) . toContain ( 'Pizza' ) ; 
47+       expect ( testAppComponent . portalOutlet . portal ) . toBe ( componentPortal ) ; 
4748    } ) ; 
4849
4950    it ( 'should load a template into the portal' ,  ( )  =>  { 
50-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
51+       let  testAppComponent  =  fixture . componentInstance ; 
5152      let  hostContainer  =  fixture . nativeElement . querySelector ( '.portal-container' ) ; 
52- 
5353      let  templatePortal  =  new  TemplatePortal ( testAppComponent . templateRef ,  null ! ) ; 
54+ 
5455      testAppComponent . selectedPortal  =  templatePortal ; 
5556      fixture . detectChanges ( ) ; 
57+ 
5658      // Expect that the content of the attached portal is present and no context is projected 
5759      expect ( hostContainer . textContent ) . toContain ( 'Banana' ) ; 
60+       expect ( testAppComponent . portalOutlet . portal ) . toBe ( templatePortal ) ; 
5861    } ) ; 
5962
6063    it ( 'should project template context bindings in the portal' ,  ( )  =>  { 
61-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
64+       let  testAppComponent  =  fixture . componentInstance ; 
6265      let  hostContainer  =  fixture . nativeElement . querySelector ( '.portal-container' ) ; 
6366
6467      // TemplatePortal without context: 
@@ -99,7 +102,7 @@ describe('Portals', () => {
99102
100103    it ( 'should dispose the host when destroyed' ,  ( )  =>  { 
101104      // Set the selectedHost to be a ComponentPortal. 
102-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
105+       let  testAppComponent  =  fixture . componentInstance ; 
103106      testAppComponent . selectedPortal  =  new  ComponentPortal ( PizzaMsg ) ; 
104107
105108      fixture . detectChanges ( ) ; 
@@ -114,7 +117,7 @@ describe('Portals', () => {
114117      let  chocolateInjector  =  new  ChocolateInjector ( fixture . componentInstance . injector ) ; 
115118
116119      // Set the selectedHost to be a ComponentPortal. 
117-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
120+       let  testAppComponent  =  fixture . componentInstance ; 
118121      testAppComponent . selectedPortal  =  new  ComponentPortal ( PizzaMsg ,  undefined ,  chocolateInjector ) ; 
119122      fixture . detectChanges ( ) ; 
120123
@@ -125,7 +128,7 @@ describe('Portals', () => {
125128    } ) ; 
126129
127130    it ( 'should load a <ng-template> portal' ,  ( )  =>  { 
128-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
131+       let  testAppComponent  =  fixture . componentInstance ; 
129132
130133      // Detect changes initially so that the component's ViewChildren are resolved. 
131134      fixture . detectChanges ( ) ; 
@@ -140,7 +143,7 @@ describe('Portals', () => {
140143    } ) ; 
141144
142145    it ( 'should load a <ng-template> portal with the `*` sugar' ,  ( )  =>  { 
143-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
146+       let  testAppComponent  =  fixture . componentInstance ; 
144147
145148      // Detect changes initially so that the component's ViewChildren are resolved. 
146149      fixture . detectChanges ( ) ; 
@@ -155,7 +158,7 @@ describe('Portals', () => {
155158    } ) ; 
156159
157160    it ( 'should load a <ng-template> portal with a binding' ,  ( )  =>  { 
158-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
161+       let  testAppComponent  =  fixture . componentInstance ; 
159162
160163      // Detect changes initially so that the component's ViewChildren are resolved. 
161164      fixture . detectChanges ( ) ; 
@@ -177,7 +180,7 @@ describe('Portals', () => {
177180    } ) ; 
178181
179182    it ( 'should load a <ng-template> portal with an inner template' ,  ( )  =>  { 
180-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
183+       let  testAppComponent  =  fixture . componentInstance ; 
181184
182185      // Detect changes initially so that the component's ViewChildren are resolved. 
183186      fixture . detectChanges ( ) ; 
@@ -199,7 +202,7 @@ describe('Portals', () => {
199202    } ) ; 
200203
201204    it ( 'should change the attached portal' ,  ( )  =>  { 
202-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
205+       let  testAppComponent  =  fixture . componentInstance ; 
203206
204207      // Detect changes initially so that the component's ViewChildren are resolved. 
205208      fixture . detectChanges ( ) ; 
@@ -219,22 +222,22 @@ describe('Portals', () => {
219222    } ) ; 
220223
221224    it ( 'should detach the portal when it is set to null' ,  ( )  =>  { 
222-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
225+       let  testAppComponent  =  fixture . componentInstance ; 
223226      testAppComponent . selectedPortal  =  new  ComponentPortal ( PizzaMsg ) ; 
224227
225228      fixture . detectChanges ( ) ; 
226229      expect ( testAppComponent . portalOutlet . hasAttached ( ) ) . toBe ( true ) ; 
227230      expect ( testAppComponent . portalOutlet . portal ) . toBe ( testAppComponent . selectedPortal ) ; 
228231
229-       testAppComponent . selectedPortal  =  null ; 
232+       testAppComponent . selectedPortal  =  null ! ; 
230233      fixture . detectChanges ( ) ; 
231234
232235      expect ( testAppComponent . portalOutlet . hasAttached ( ) ) . toBe ( false ) ; 
233236      expect ( testAppComponent . portalOutlet . portal ) . toBeNull ( ) ; 
234237    } ) ; 
235238
236239    it ( 'should set the `portal` when attaching a component portal programmatically' ,  ( )  =>  { 
237-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
240+       let  testAppComponent  =  fixture . componentInstance ; 
238241      let  portal  =  new  ComponentPortal ( PizzaMsg ) ; 
239242
240243      testAppComponent . portalOutlet . attachComponentPortal ( portal ) ; 
@@ -243,7 +246,7 @@ describe('Portals', () => {
243246    } ) ; 
244247
245248    it ( 'should set the `portal` when attaching a template portal programmatically' ,  ( )  =>  { 
246-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
249+       let  testAppComponent  =  fixture . componentInstance ; 
247250      fixture . detectChanges ( ) ; 
248251
249252      testAppComponent . portalOutlet . attachTemplatePortal ( testAppComponent . cakePortal ) ; 
@@ -252,7 +255,7 @@ describe('Portals', () => {
252255    } ) ; 
253256
254257    it ( 'should clear the portal reference on destroy' ,  ( )  =>  { 
255-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
258+       let  testAppComponent  =  fixture . componentInstance ; 
256259
257260      testAppComponent . selectedPortal  =  new  ComponentPortal ( PizzaMsg ) ; 
258261      fixture . detectChanges ( ) ; 
@@ -263,6 +266,40 @@ describe('Portals', () => {
263266
264267      expect ( testAppComponent . portalOutlet . portal ) . toBeNull ( ) ; 
265268    } ) ; 
269+ 
270+     it ( 'should not clear programmatically-attached portals on init' ,  ( )  =>  { 
271+       fixture . destroy ( ) ; 
272+ 
273+       const  unboundFixture  =  TestBed . createComponent ( UnboundPortalTestApp ) ; 
274+ 
275+       // Note: calling `detectChanges` here will cause a false positive. 
276+       // What we're testing is attaching before the first CD cycle. 
277+       unboundFixture . componentInstance . portalOutlet . attach ( new  ComponentPortal ( PizzaMsg ) ) ; 
278+       unboundFixture . detectChanges ( ) ; 
279+ 
280+       expect ( unboundFixture . nativeElement . querySelector ( '.portal-container' ) . textContent ) 
281+         . toContain ( 'Pizza' ) ; 
282+     } ) ; 
283+ 
284+     it ( 'should be considered attached when attaching using `attach`' ,  ( )  =>  { 
285+       expect ( fixture . componentInstance . portalOutlet . hasAttached ( ) ) . toBe ( false ) ; 
286+       fixture . componentInstance . portalOutlet . attach ( new  ComponentPortal ( PizzaMsg ) ) ; 
287+       expect ( fixture . componentInstance . portalOutlet . hasAttached ( ) ) . toBe ( true ) ; 
288+     } ) ; 
289+ 
290+     it ( 'should be considered attached when attaching using `attachComponentPortal`' ,  ( )  =>  { 
291+       expect ( fixture . componentInstance . portalOutlet . hasAttached ( ) ) . toBe ( false ) ; 
292+       fixture . componentInstance . portalOutlet . attachComponentPortal ( new  ComponentPortal ( PizzaMsg ) ) ; 
293+       expect ( fixture . componentInstance . portalOutlet . hasAttached ( ) ) . toBe ( true ) ; 
294+     } ) ; 
295+ 
296+     it ( 'should be considered attached when attaching using `attachTemplatePortal`' ,  ( )  =>  { 
297+       const  instance  =  fixture . componentInstance ; 
298+       expect ( instance . portalOutlet . hasAttached ( ) ) . toBe ( false ) ; 
299+       instance . portalOutlet . attachTemplatePortal ( new  TemplatePortal ( instance . templateRef ,  null ! ) ) ; 
300+       expect ( instance . portalOutlet . hasAttached ( ) ) . toBe ( true ) ; 
301+     } ) ; 
302+ 
266303  } ) ; 
267304
268305  describe ( 'DomPortalOutlet' ,  ( )  =>  { 
@@ -345,7 +382,7 @@ describe('Portals', () => {
345382    it ( 'should attach and detach a template portal with a binding' ,  ( )  =>  { 
346383      let  fixture  =  TestBed . createComponent ( PortalTestApp ) ; 
347384
348-       let  testAppComponent  =  fixture . debugElement . componentInstance ; 
385+       let  testAppComponent  =  fixture . componentInstance ; 
349386
350387      // Detect changes initially so that the component's ViewChildren are resolved. 
351388      fixture . detectChanges ( ) ; 
@@ -484,7 +521,7 @@ class PortalTestApp {
484521  @ViewChild ( CdkPortalOutlet )  portalOutlet : CdkPortalOutlet ; 
485522  @ViewChild ( 'templateRef' ,  {  read : TemplateRef  } )  templateRef : TemplateRef < any > ; 
486523
487-   selectedPortal : Portal < any > ; 
524+   selectedPortal : Portal < any > | undefined ; 
488525  fruit : string  =  'Banana' ; 
489526  fruits  =  [ 'Apple' ,  'Pineapple' ,  'Durian' ] ; 
490527
@@ -508,9 +545,27 @@ class PortalTestApp {
508545
509546} 
510547
548+ /** Test-bed component that contains a portal outlet and a couple of template portals. */ 
549+ @Component ( { 
550+   template : ` 
551+     <div class="portal-container"> 
552+       <ng-template cdkPortalOutlet></ng-template> 
553+     </div> 
554+   ` , 
555+ } ) 
556+ class  UnboundPortalTestApp  { 
557+   @ViewChild ( CdkPortalOutlet )  portalOutlet : CdkPortalOutlet ; 
558+ } 
559+ 
511560// Create a real (non-test) NgModule as a workaround for 
512561// https://github.com/angular/angular/issues/10760 
513- const  TEST_COMPONENTS  =  [ PortalTestApp ,  ArbitraryViewContainerRefComponent ,  PizzaMsg ] ; 
562+ const  TEST_COMPONENTS  =  [ 
563+   PortalTestApp , 
564+   UnboundPortalTestApp , 
565+   ArbitraryViewContainerRefComponent , 
566+   PizzaMsg 
567+ ] ; 
568+ 
514569@NgModule ( { 
515570  imports : [ CommonModule ,  PortalModule ] , 
516571  exports : TEST_COMPONENTS , 
0 commit comments