4

I have several components (about,service,dashboard, etc) in which a header component is added. The application is running fine. However, I am getting errors when testing.

import { Component } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { SettingsPage } from './settings.page';

describe('SettingsPage', () => {
  let component: SettingsPage;
  let fixture: ComponentFixture<SettingsPage>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [ SettingsPage,MockHeaderComponent ],
      imports: [IonicModule.forRoot()]
    }).compileComponents();

    fixture = TestBed.createComponent(SettingsPage);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }));

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
@Component({
  selector: 'app-header',
  template: ''
})
class MockHeaderComponent {
}

First Error

Chrome 93.0.4577.82 (Windows 10): Executed 22 of 26 (1 FAILED) (0 secs / 5.88 secs)
ERROR: 'NG0303: Can't bind to 'headline' since it isn't a known property of 'app-header'.'

headline is a variable that I declared in my header component and use in my components to give me the correct title.

Of course, I already looked for solutions on the Internet and came across the following Stack Overflow post: Unit test Angular with Jasmine and Karma, Error:Can't bind to 'xxx' since it isn't a known property of 'xxxxxx'. Therefore, I have imported and declared my HeaderComponent.

import { Component } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { HeaderComponent } from '../header/header.component';

import { SettingsPage } from './settings.page';

describe('SettingsPage', () => {
  let component: SettingsPage;
  let fixture: ComponentFixture<SettingsPage>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [ SettingsPage,HeaderComponent,MockHeaderComponent ],
      imports: [IonicModule.forRoot()]
    }).compileComponents();

    fixture = TestBed.createComponent(SettingsPage);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }));

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
@Component({
  selector: 'app-header',
  template: ''
})
class MockHeaderComponent {
}

Unfortunately, the following error occurred.

Chrome 93.0.4577.82 (Windows 10) SettingsPage should create FAILED
        Failed: NG0300: Multiple components match node with tagname app-header. Find more at https://angular.io/errors/NG0300
        error properties: Object({ code: '300' })
        Error: NG0300: Multiple components match node with tagname app-header. Find more at https://angular.io/errors/NG0300
            at throwMultipleComponentError (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:6779:1)
            at findDirectiveDefMatches (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10344:1)
            at resolveDirectives (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10158:1)
            at elementStartFirstCreatePass (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14772:1)
            at ɵɵelementStart (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14809:1)
            at ɵɵelement (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:14888:1)
            at SettingsPage_Template (ng:///SettingsPage.js:8:9)
            at executeTemplate (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9600:1)
            at renderView (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9404:1)
            at renderComponent (node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:10684:1)
        Error: Expected undefined to be truthy.
            at <Jasmine>
            at UserContext.<anonymous> (src/app/components/settings/settings.page.spec.ts:24:23)
            at ZoneDelegate.invoke (node_modules/zone.js/dist/zone-evergreen.js:364:1)
            at ProxyZoneSpec.push.QpwO.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/zone-testing.js:292:1)
Chrome 93.0.4577.82 (Windows 10): Executed 26 of 26 (7 FAILED) (1.712 secs / 1.658 secs)

Can anyone tell me what I am doing wrong?

UPDATE 1: My ComponentsModule class in which I integrate all reusable components:

import {NgModule} from '@angular/core';
import {HeaderComponent} from './header/header.component';
import { FooterComponent } from './footer/footer.component';
@NgModule({
    declarations: [HeaderComponent, FooterComponent],
    exports: [HeaderComponent, FooterComponent]
})
export class ComponentsModule{}

My html:

<ion-header>
  <app-header [headline]="headlines.settings"></app-header>
</ion-header>

<ion-content>

</ion-content>

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { SettingsPageRoutingModule } from './settings-routing.module';

import { SettingsPage } from './settings.page';
import { ComponentsModule } from '../components.module';
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    ComponentsModule,
    SettingsPageRoutingModule
  ],
  declarations: [SettingsPage]
})
export class SettingsPageModule {}

setting.page.ts

import { Component, OnInit } from '@angular/core';
import { lablesHeadlines } from 'src/environments/lables';

@Component({
  selector: 'app-settings',
  templateUrl: './settings.page.html',
  styleUrls: ['./settings.page.scss'],
})
export class SettingsPage implements OnInit {

  lablesHeadlines = lablesHeadlines;
  headlines = lablesHeadlines;

  constructor() { }

  ngOnInit() {
  }

}

setting.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { SettingsPageRoutingModule } from './settings-routing.module';

import { SettingsPage } from './settings.page';
import { ComponentsModule } from '../components.module';
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    ComponentsModule,
    SettingsPageRoutingModule
  ],
  declarations: [SettingsPage]
})
export class SettingsPageModule {}

Doncarlito87
  • 359
  • 1
  • 8
  • 25
  • Does this answer your question? [Error: Multiple components match node with tagname app-contact](https://stackoverflow.com/questions/61794081/error-multiple-components-match-node-with-tagname-app-contact) –  Sep 23 '21 at 11:47
  • Unfortunately, not really. I don't have console.log() in my constructors. Furthermore I don't have any methods that I can use in ngOnInit(). – Doncarlito87 Sep 23 '21 at 11:58
  • I would suggest posting the code for the unit under test as well. There is not enough here to properly answer the question. –  Sep 23 '21 at 12:54
  • Okay, you're right. In update 1 I added all the classes from Setting. – Doncarlito87 Sep 23 '21 at 13:05

1 Answers1

6

Problem Solved. https://testing-angular.com/testing-components-with-children/#testing-components-with-children showed me the solution. That I write unit tests, I can do with schemas: [NO_ERRORS_SCHEMA] to ignore the components in the top-level components. The low-level components are ready checked in their own tests. I strongly advise to use the link above if you want to learn about testing in Angular.

Here is my Updated Sourcecode:

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { AboutClientServiceService } from 'src/app/services/about-client-service.service';
import { AppComponent } from 'src/app/app.component';
import { MockAboutClientService } from 'src/app/Mock/MockAboutClientService';
import { AboutPage } from './about.page';
import { Component } from '@angular/core';
import { NO_ERRORS_SCHEMA } from '@angular/core';

describe('AboutPage', () => {
  let component: AboutPage;
  let fixture: ComponentFixture<AboutPage>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [ AboutPage, MockHeaderComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [IonicModule, HttpClientTestingModule],
      providers: [AppComponent, AboutClientServiceService]
    }).compileComponents();

    TestBed.overrideComponent(
      AboutPage,
      {
        set: {
          providers: [
            { provide: AboutClientServiceService, useClass: MockAboutClientService }]
        }
      });

    fixture = TestBed.createComponent(AboutPage);
    component = fixture.componentInstance;
    fixture.detectChanges();

  }));

  it('should create', (done) => {
    expect(component).toBeTruthy();
    expect(component.version).toBeDefined();
    done();
  });
});
@Component({
  selector: 'app-header',
  template: ''
})
class MockHeaderComponent {
}
Doncarlito87
  • 359
  • 1
  • 8
  • 25