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

mounika20
  • 213
  • 2
  • 9

2 Answers2

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

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • 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)` – mounika20 Oct 03 '16 at 08:32
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

irhetoric
  • 362
  • 2
  • 9