Angular 2 Karma Test 'component-name' is not a known element

Javascriptnode.jsAngularTypescriptKarma Jasmine

Javascript Problem Overview


In the AppComponent, I'm using the nav component in the HTML code. The UI looks fine. No errors when doing ng serve. and no errors in console when I look at the app.

But when I ran Karma for my project, there is an error:

Failed: Template parse errors: 
'app-nav' is not a known element:
1. If 'app-nav' is an Angular component, then verify that it is part of this module.
2. If 'app-nav' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.

In my app.module.ts:

there is:

import { NavComponent } from './nav/nav.component';

It is also in the declarations part of NgModule

@NgModule({
  declarations: [
    AppComponent,
    CafeComponent,
    ModalComponent,
    NavComponent,
    NewsFeedComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    JsonpModule,
    ModalModule.forRoot(),
    ModalModule,
    NgbModule.forRoot(),
    BootstrapModalModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

I'm using the NavComponent in my AppComponent

app.component.ts

import { Component, ViewContainerRef } from '@angular/core';
import { Overlay } from 'angular2-modal';
import { Modal } from 'angular2-modal/plugins/bootstrap';
import { NavComponent } from './nav/nav.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angela';
}

app.component.html

<app-nav></app-nav>
<div class="container-fluid">
</div>

I have seen a similar question, but the answer in that question says we should add NgModule in the nav component that has a export in that, but I'm getting compile error when I do that.

There is also: app.component.spec.ts

import {NavComponent} from './nav/nav.component';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';

Javascript Solutions


Solution 1 - Javascript

Because in unit tests you want to test the component mostly isolated from other parts of your application, Angular won't add your module's dependencies like components, services, etc. by default. So you need to do that manually in your tests. Basically, you have two options here:

A) Declare the original NavComponent in the test
describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          NavComponent
        ]
      }).compileComponents();
    }));
B) Mock the NavComponent
describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          MockNavComponent
        ]
      }).compileComponents();
    }));

// it(...) test cases 

});

@Component({
  selector: 'app-nav',
  template: ''
})
class MockNavComponent {
}

You'll find more information in the official documentation.

Solution 2 - Javascript

You can also use NO_ERRORS_SCHEMA

describe('AppComponent', () => {
beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [
      AppComponent
    ],
    schemas: [NO_ERRORS_SCHEMA]
  }).compileComponents();
}));

https://2018.ng-conf.org/mocking-dependencies-angular/

Solution 3 - Javascript

One more reason is that there can be multiple .compileComponents() for beforeEach() in your test case

for e.g.

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [TestComponent]
  }).compileComponents();
}));

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [HttpClientModule],
    declarations: [Test1Component],
    providers: [HttpErrorHandlerService]
  }).compileComponents();
});

Solution 4 - Javascript

For me importing the component in the parent resolved the issue.

describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          NavComponent
        ]
      }).compileComponents();
    }));

Add this in spec of the parent where this component is used.

Solution 5 - Javascript

Step 1: Create stubs at beginning of spec file.

@Component({selector: 'app-nav', template: ''})
class NavComponent{}

Step 2: Add stubs in component's declarations.

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

Solution 6 - Javascript

Another source for this error are the tests for the parent component, app-root, that include the tag of this component, app-nav.

Even though the message is about app-nav, the child component, the fix should be added in the tests of app-root, the parent component.

The fix can be a mock:

app.component.spec.ts:

@Component({selector: 'app-nav', template: ''})
    class NavComponentStub {
}

What happens is that you create the root component, with it's tests, they pass. Latter on you add the child component in the root component tag and now you have to update the root component tests even if you just added a tag in the template.

Also the message doesn't say which test fails and from the message you might be led to believe that it's the child component's tests, when in fact they are the parent's tests.

Solution 7 - Javascript

If you create a stub and still get the same error it might be because of --watch mode on. Try to stop it and run again.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAngela PView Question on Stackoverflow
Solution 1 - JavascriptKim KernView Answer on Stackoverflow
Solution 2 - JavascriptAdrianView Answer on Stackoverflow
Solution 3 - JavascriptDevaarthView Answer on Stackoverflow
Solution 4 - JavascriptKailasView Answer on Stackoverflow
Solution 5 - JavascriptYuvraj PatilView Answer on Stackoverflow
Solution 6 - JavascriptGoToView Answer on Stackoverflow
Solution 7 - JavascriptExperimenterView Answer on Stackoverflow