@@ -10,7 +10,7 @@ import {CommonModule, Location} from '@angular/common';
1010import { SpyLocation } from '@angular/common/testing' ;
1111import { ChangeDetectionStrategy , ChangeDetectorRef , Component , Injectable , NgModule , TemplateRef , Type , ViewChild , ViewContainerRef } from '@angular/core' ;
1212import { ComponentFixture , fakeAsync , TestBed , tick } from '@angular/core/testing' ;
13- import { Resolve , Router } from '@angular/router' ;
13+ import { ChildrenOutletContexts , Resolve , Router } from '@angular/router' ;
1414import { RouterTestingModule } from '@angular/router/testing' ;
1515import { of } from 'rxjs' ;
1616import { delay , mapTo } from 'rxjs/operators' ;
@@ -339,6 +339,49 @@ describe('Integration', () => {
339339 expect ( fixture . nativeElement . innerHTML ) . toContain ( 'one' ) ;
340340 } ) ) ;
341341 } ) ;
342+
343+ it ( 'should not unregister outlet if a different one already exists #36711, 32453' , async ( ) => {
344+ @Component ( {
345+ template : `
346+ <router-outlet *ngIf="outlet1"></router-outlet>
347+ <router-outlet *ngIf="outlet2"></router-outlet>
348+ ` ,
349+ } )
350+ class TestCmp {
351+ outlet1 = true ;
352+ outlet2 = false ;
353+ }
354+
355+ @Component ( { template : '' } )
356+ class EmptyCmp {
357+ }
358+
359+ TestBed . configureTestingModule ( {
360+ imports : [ CommonModule , RouterTestingModule . withRoutes ( [ { path : '**' , component : EmptyCmp } ] ) ] ,
361+ declarations : [ TestCmp , EmptyCmp ]
362+ } ) ;
363+ const fixture = TestBed . createComponent ( TestCmp ) ;
364+ const contexts = TestBed . inject ( ChildrenOutletContexts ) ;
365+ await TestBed . inject ( Router ) . navigateByUrl ( '/' ) ;
366+ fixture . detectChanges ( ) ;
367+
368+ expect ( contexts . getContext ( 'primary' ) ) . toBeDefined ( ) ;
369+ expect ( contexts . getContext ( 'primary' ) ?. outlet ) . not . toBeNull ( ) ;
370+
371+ // Show the second outlet. Applications shouldn't really have more than one outlet but there can
372+ // be timing issues between destroying and recreating a second one in some cases:
373+ // https://github.com/angular/angular/issues/36711,
374+ // https://github.com/angular/angular/issues/32453
375+ fixture . componentInstance . outlet2 = true ;
376+ fixture . detectChanges ( ) ;
377+ expect ( contexts . getContext ( 'primary' ) ?. outlet ) . not . toBeNull ( ) ;
378+
379+ fixture . componentInstance . outlet1 = false ;
380+ fixture . detectChanges ( ) ;
381+ // Destroying the first one show not clear the outlet context because the second one takes over
382+ // as the registered outlet.
383+ expect ( contexts . getContext ( 'primary' ) ?. outlet ) . not . toBeNull ( ) ;
384+ } ) ;
342385} ) ;
343386
344387function advance < T > ( fixture : ComponentFixture < T > ) : void {
0 commit comments