testing router-outlet component in angular2
Asked Answered
V

2

10

i have a homecomponent where the html is

//home.component.html

<router-outlet></router-outlet>

//home.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { HomeService} from './shared/services/home.service';

@Component({
  // moduleId: module.id,
  selector: 'app-home',
  templateUrl: 'home.component.html',
  styleUrls: ['home.component.css'],
  providers:[HomeService]
})
export class HomeComponent implements OnInit {

  constructor(private service:HomeService , private route:Router) { }

  ngOnInit() {
    if(this.service.isAuthenticated()){
      this.route.navigateByUrl('dashboard/main');
    }
  }
}

//home.component.spec.ts

import { ComponentFixture, TestBed  } from '@angular/core/testing';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';
import { async, inject } from '@angular/core/testing';
import { HomeComponent } from './home.component';
import { Router} from '@angular/router';
import { HomeService } from './shared/services/home.service';

class RouterStub {
    navigateByUrl(url: string) { return url }
}

class MockHomeService {
    isAuthenticated() {
        return true
    }
}

let comp: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;


describe('Component: HomeComponent', () => {


    beforeEach(() => {
        TestBed.configureTestingModule({

            declarations: [HomeComponent],
            providers: [
                { provide: Router, useClass: RouterStub },
                { provide: HomeService, useClass: MockHomeService },
            ]
        });

        fixture = TestBed.createComponent(HomeComponent);
        comp = fixture.componentInstance;

    });

    it('should tell ROUTER to navigate to dashboard/main if authencated',
        inject([Router, HomeService], (router: Router, homeservice: HomeService) => {
            const spy = spyOn(router, 'navigateByUrl');
            comp.ngOnInit();
            if (homeservice.isAuthenticated()) {
                const navArgs = spy.calls.first().args[0];
                expect(navArgs).toBe('dashboard/main');
            }


        }));
});

I am getting the following error

    Error: Template parse errors:
        'router-outlet' is not a known element:
        1. If 'router-outlet' is an Angular component, then verify that it is pa
rt of this module.
        2. If 'router-outlet' is a Web Component then add "CUSTOM_ELEMENTS_SCHEM
A" to the '@NgModule.schema' of this component to suppress this message. ("<div
class="">
            [ERROR ->]<router-outlet></router-outlet>
        </div>
        "): HomeComponent@1:4
            at TemplateParser.parse (http://localhost:9876/_karma_webpack_/0.bun
dle.js:21444:19)
            at RuntimeCompiler._compileTemplate (http://localhost:9876/_karma_we
bpack_/0.bundle.js:6569:51)
            at http://localhost:9876/_karma_webpack_/0.bundle.js:6492:83
            at Set.forEach (native)
            at compile (http://localhost:9876/_karma_webpack_/0.bundle.js:6492:4
7)
            at RuntimeCompiler._compileComponents (http://localhost:9876/_karma_
webpack_/0.bundle.js:6494:13)
            at RuntimeCompiler._compileModuleAndAllComponents (http://localhost:
9876/_karma_webpack_/0.bundle.js:6411:37)
            at RuntimeCompiler.compileModuleAndAllComponentsSync (http://localho
st:9876/_karma_webpack_/0.bundle.js:6399:21)
            at TestingCompilerImpl.compileModuleAndAllComponentsSync (http://loc
alhost:9876/_karma_webpack_/0.bundle.js:10203:35)
            at TestBed._initIfNeeded (webpack:///D:/myapp/transfer(9)/transfer/~
/@angular/core/bundles/core-testing.umd.js:1059:0 <- src/test.ts:4943:40)

what is the mistake i am doing ?

Thanks in advance

Vilayet answered 30/9, 2016 at 13:30 Comment(1)
Kindly update your answer with the routing code and also appComponent code. It will help identify issue.Extradition
T
11

The error is because the <router-outlet> in part of the RouterModule1, which is not imported into your test bed configuration.

If you don't care to test any actual real routing (I notice the mock router), then you can just make Angular ignore the <router-outlet> element by adding the following into your test bed configuration.

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

TestBed.configureTestingModule({
  schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
});

And just a suggestion. You want to test the behavior on the component, and the behavior is that when the component is created and the user authenticated, then the router navigate method should be called. So we should test that the navigate method is called. How do we do that? With Spies. You can make a spy from the navigateByUrl method, then you can check with jasmine if that method was called

import { getTestBed } from '@angular/core/testing';

class RouterStub {
  navigateByUrl = jasmine.createSpy('navigateByUrl');
}

it('should navigate', () => {
  fixture.detectChanges();
  let router: Router = getTestBed().get(Router);
  expect(router.navigateByUrl).toHaveBeenCalledWith('dashboard/main');
});

UPDATE

Now you are getting a missing Http provider error.

Because you have providers:[HomeService] on your @Component, it overrides the one in the test module configuration (which is the mock). You should override the component providers the in this case

TestBed.configureTestingModule({});
TestBed.overrideComponent(HomeComponent, {
  set: {
    providers: [
      { provide: HomeService, useClass: MockHomeService }
    ]
  }
})

1 - For testing it should actually be the RouterTestingModule, as mentioned here

Tribute answered 30/9, 2016 at 14:23 Comment(1)
Thanks, I imported CUSTOM_ELEMENTS_SCHEMA and included schemas: [ CUSTOM_ELEMENTS_SCHEMA ] in testbed configuration ,but getting the following error te:0:0 caused by: No provider for Http! Error: No provider for Http! at NoProviderError.Error (native) at NoProviderError.BaseError [as constructor] (webpack:///D:/myfolder/t ransfer(9)/transfer/~/@angular/core/src/facade/errors.js:24:0 <- src/test.ts: 2:34) at NoProviderError .AbstractProviderError [as constructor] (webpack:///D:/myfolder/transfer(9)/transfer/~/@angular/core/src/di/reflective_errors.js:42:0 <- src/test.ts:28434:16)Vilayet
A
2

If you don't want to test routing but want to test the functionality of the component, you can just add

  <!-- app.component.spec.ts -->
  import { RouterTestingModule } from '@angular/router/testing';

  TestBed.configureTestingModule({
    imports: [RouterTestingModule],
    declarations: [AppComponent],
  });

This allows your test to run without disabling CUSTOM_ELEMENTS_SCHEMA

Anemo answered 23/6, 2017 at 21:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.