3

I have an angular application with multiple components and modules. Here, I have tried to simplify and minimize the structure to help understand the issue.
App Structure

-app
  -Core
    -donut-card
      -donut-card-component.html
      -donut-card-component.spec.ts
      -donut-card-component.ts
     -core.module.ts
  -app.module.ts
  -......
  -......

donut-card.component.html

<div class="card-pf" *ngIf="donutConfig && chartData">
  <!-- If a titleLink is provided, wrap the h2 with an anchor tag -->
  <a *ngIf="titleLink; else cardTitle" [routerLink]="titleLink">
    <ng-container *ngTemplateOutlet="cardTitle"></ng-container>
  </a>
  <ng-template #cardTitle>
    <h2 class="card-pf-title">{{ chartTitle }}</h2>
  </ng-template>

  <p class="card-pf-utilization-details"></p>
  <div class="card-pf-body">
    <pfng-donut-chart [chartData]=chartData
                      [config]=donutConfig>
    </pfng-donut-chart>
  </div>
</div>

donut-card.component.spec.ts


import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';

import { DonutCardComponent } from './donut-card.component';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [ DonutCardComponent ]
    })
    .compileComponents();

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

donut-card.component.ts

import { Component, Input } from '@angular/core';
import { DonutChartConfig } from 'patternfly-ng/chart';

@Component({
  selector: 'ssc-donut-card',
  templateUrl: './donut-card.component.html'
})
export class DonutCardComponent {
  @Input() chartTitle: string;
  @Input() titleLink: Array<string>;
  @Input() donutConfig: DonutChartConfig;
  @Input() chartData: Array<any>;
}

core.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';

import { DonutCardComponent } from './donut-card/donut-card.component';

@NgModule({
  imports: [
    BrowserModule,
    DonutChartModule,
    RouterModule
  ],
  declarations: [
    DonutCardComponent
  ],
  exports: [
    DonutCardComponent
  ]
})
export class CoreModule {}

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    CoreModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }

The unit tests fail due to property binding issue throughout the application. I have referred to quite few solutions and checks available from stack overflow regarding the same but nothing so far worked for me.

    Failed: Template parse errors:
    Can't bind to 'chartTitle' since it isn't a known property of 'ssc-donut-card'.
    1. If 'ssc-donut-card' is an Angular component and it has 'chartTitle' input, then verify that it is part of this module.
    2. If 'ssc-donut-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("<ssc-donut-card
      [ERROR ->][chartTitle]="chartTitle"
      [titleLink]="titleLink"
      [chartData]="chartData"
    "): ng:///DynamicTestModule/ScoresDonutCardComponent.html@1:2
    Can't bind to 'titleLink' since it isn't a known property of 'ssc-donut-card'.
    1. If 'ssc-donut-card' is an Angular component and it has 'titleLink' input, then verify that it is part of this module.
    2. If 'ssc-donut-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("<ssc-donut-card
      [chartTitle]="chartTitle"
      [ERROR ->][titleLink]="titleLink"
      [chartData]="chartData"
      [donutConfig]="donutConfig"
    "): ng:///DynamicTestModule/ScoresDonutCardComponent.html@2:2
    Can't bind to 'chartData' since it isn't a known property of 'ssc-donut-card'.
    1. If 'ssc-donut-card' is an Angular component and it has 'chartData' input, then verify that it is part of this module.
    2. If 'ssc-donut-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
      [chartTitle]="chartTitle"
      [titleLink]="titleLink"
      [ERROR ->][chartData]="chartData"
      [donutConfig]="donutConfig"
</ssc-donut-card>
    "): ng:///DynamicTestModule/ScoresDonutCardComponent.html@3:2
    Can't bind to 'donutConfig' since it isn't a known property of 'ssc-donut-card'.
    1. If 'ssc-donut-card' is an Angular component and it has 'donutConfig' input, then verify that it is part of this module.
    2. If 'ssc-donut-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
    3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
      [titleLink]="titleLink"
      [chartData]="chartData"
      [ERROR ->][donutConfig]="donutConfig"
</ssc-donut-card>
    "): ng:///DynamicTestModule/ScoresDonutCardComponent.html@4:2
    'ssc-donut-card' is not a known element:
    1. If 'ssc-donut-card' is an Angular component, then verify that it is part of this module.
    2. If 'ssc-donut-card' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("[ERROR ->]<ssc-donut-card
      [chartTitle]="chartTitle"
      [titleLink]="titleLink"
    "): ng:///DynamicTestModule/ScoresDonutCardComponent.html@0:0


Nirzari
  • 79
  • 1
  • 6
  • in every component’s spec testbed you need to import the donutcard component – bodorgergely Jan 19 '19 at 00:38
  • @bodorgergelyI don't think that's how the structure is supposed to be in a big sized angular application. The imports work based on hierarchy of the components. I have another application up and running with the similar hierarchy import structure. – Nirzari Jan 20 '19 at 21:24
  • The log you show us doesn't tell us where the error originates from. But I assume it's from one of your component where you would use the ssc-donut-card component. In that test, you need to add the DonutCardComponent in the testbed's declarations, or if it has a module where you export said component, then import that. – bodorgergely Jan 21 '19 at 22:23
  • There are no other components where I am using ssc-donut-card component. Core module is the only place and it is already declared and exported by it and then the core module imported by higher level module in the hierarchy. Also, as I mentioned the property binding is failing throughout the project and not just for this component. – Nirzari Jan 22 '19 at 15:06
  • I was missing few dependencies here and there. For example, with this component, I was missing **DonutChartModule** in my spec file. **donut-card.component.specs.ts** ` import { DonutChartModule } from 'patternfly-ng'; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ DonutChartModule, RouterTestingModule ] }) ` Tip: Make sure to follow your typescript file and unit test output console line by line to list and import/declare/provide all dependencies. – Nirzari Jan 22 '19 at 21:50

0 Answers0