Andreas
Andreas

Reputation: 1776

Router Outlet not rendered in unit test

Note: I am quite new to Angular programming!

I try to write unit tests for routing.

The AppComponent renders MasterLayoutComponent in its single unnamed router outlet.

MasterLayoutComponent contains two named router outlets:

<kui-toolbar (contextmenu)="isDevMode">
    <router-outlet name="toolbar"></router-outlet>
</kui-toolbar>
<div class="content" (contextmenu)="isDevMode">
    <router-outlet name="main"></router-outlet>
</div>

This is the template of the AppListComponent that should render to the 'main' router outlet:

<p>app-list works!</p>

This is my route definition:

export const appRoutes: Route[] = [

  { path: "",   redirectTo: "appList", pathMatch: "full" },
  { path: "**", redirectTo: "appList", pathMatch: "full" },

  { path: "appList", component: MasterLayoutComponent, children: [{ path: "", component: AppListComponent, outlet: "main" }] }
];

This is my test code:

describe("App Routing", () => {

  let location: Location;
  let router: Router;
  let fixture: ComponentFixture<MasterLayoutComponent>;
  let masterLayoutComponent: MasterLayoutComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        CommonModule,
        RouterTestingModule.withRoutes(appRoutes),
        NgxsModule.forRoot(),
        KuiCommonModule,
        KuiBaseComponentsModule,
        LocalizationModule,
        HttpClientModule,
      ],
      providers: [
        AppConfigurationService,
      ],
      declarations: [
        AppListComponent
      ],
    }).compileComponents();

    router = TestBed.get(Router);
    location = TestBed.get(Location);
    fixture = TestBed.createComponent(MasterLayoutComponent);
    masterLayoutComponent = fixture.componentInstance;

    router.initialNavigation();
  });


  it("should navigate to '' on path \"\"", fakeAsync(() => {
    // Trigger the router to navigate to path ""
    router.navigate([""]);
    // Wait for the router to do its work
    tick();

    fixture.detectChanges();

    expect(location.path()).toBe("");
  }));
});

The test succeeds.

When I break on the expectation and look at the value of fixture.nativeElement.innerHTML I can see the following result:

<kui-toolbar _ngcontent-c0="" _nghost-c1="">
   <kui-breadcrumb _ngcontent-c1="" _nghost-c2="" ng-reflect-navigation-items="[object Object]">
      <div _ngcontent-c2="" class="wrapper">
         <div _ngcontent-c2="" class="links">
            <!--bindings={
               "ng-reflect-ng-for-of": "[object Object]"
               }-->
            <div _ngcontent-c2="" class="link">
               <button _ngcontent-c2="" disabled="" title="Home">
                  <!--bindings={
                     "ng-reflect-ng-if": "true"
                     }-->
                  <div _ngcontent-c2="" class="icon" style="-webkit-mask-image: url(&quot;assets/svg/Icon.Home.svg&quot;);"></div>
               </button>
            </div>
         </div>
      </div>
   </kui-breadcrumb>
   <div _ngcontent-c1="" class="additional-content">
      <router-outlet _ngcontent-c0="" name="toolbar"></router-outlet>
   </div>
</kui-toolbar>
<div _ngcontent-c0="" class="content">
   <router-outlet _ngcontent-c0="" name="main"></router-outlet>
</div>

The 'main' router outlet is not replaced by the expected HTML of the AppListComponent.

What am I doing wrong? What am I missing?

Upvotes: 1

Views: 1458

Answers (1)

Amit Chigadani
Amit Chigadani

Reputation: 29715

RouterTestingModule probably does spy on the routes, which will actually not navigate to the url but assures that it would have navigated to it. Hence the component AppListComponent is not rendered.

This is fine for unit testing because you only concentrate on testing the parent component (MasterLayoutComponent).

Instead you could verify the router navigation as follows

expect(router.navigate).toHaveBeenCalledWith(['new-path'])

Upvotes: 4

Related Questions