Angular Test error -- Can't bind to 'items' since it isn't a known property of 'app-dropdown'

Sasha

Just want to say that I recognize that there are many SO posts related to "Can't bind to X since it isn't a known property of Y" errors. I've looked at a ton of them, and have found a number of answers which solve the specific problems, but which I've had trouble translating to my case, which I actually think is quite general, and relates to a fundamental misunderstanding of how I should be solving my use case.

I'm creating an Angular (7) app, which I've separated into components and routes. The components are modular pieces (dropdowns, modals, buttons, whatever), and the routes are individual pages in the app. The terming is a little convoluted, because both are technically Angular components. In other words, the structure (within src/) looks like this:

- app
  - components
    - dropdown
      - dropdown.component.ts
      - dropdown.component.html
      - dropdown.component.scss
      - dropdown.component.spec.ts
  - routes
    - library
      - library.component.ts
      - library.component.html
      - library.component.scss
      - library.component.spec.ts
  ...

So I have a Library route, which is just an Angular component which imports a Dropdown component and looks like this:

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

import { DropdownComponent } from '../../components/dropdown/dropdown.component';

@Component({
  selector: 'app-library',
  templateUrl: './library.component.html',
  styleUrls: ['./library.component.scss']
})
export class LibraryComponent implements OnInit {
  pickItem($event) {
    console.log($event.item, $event.index);
  }

  constructor() { }

  ngOnInit() {}
}

The relevant Library HTML file:

<div class="library row py4">
  <h3 class="typ--geo-bold typ--caps mb5">Style Library</h3>

  <div class="mb4" style="max-width: 35rem;">
    <p class="typ--geo-bold typ--caps">Dropdowns</p>
    <app-dropdown
      [items]="['One', 'Two', 'Three']"
      (pick)="pickItem($event)"
      title="Default dropdown"
    ></app-dropdown>
    <br />
    <app-dropdown
      [items]="['One', 'Two', 'Three']"
      (pick)="pickItem($event)"
      title="Inline dropdown"
      class="dropdown--inline"
    ></app-dropdown>
  </div>
</div>

The dropdown component is a basic component, following a similar structure. I won't paste it here unless asked, because I'm not sure it'd be additive. (Suffice it to say that it does accept items as an Input -- relevant to the below error).

This works perfectly in the browser, and builds correctly in production.

When I run my library.components.spec.ts test, though, I run into the following error:

Failed: Template parse errors:
Can't bind to 'items' since it isn't a known property of 'app-dropdown'.
1. If 'app-dropdown' is an Angular component and it has 'items' input, then verify that it is part of this module.
2. If 'app-dropdown' 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. ("
    <p class="typ--geo-bold typ--caps">Dropdowns</p>
    <app-dropdown
      [ERROR ->][items]="['One', 'Two', 'Three']"
      (pick)="pickItem($event)"
      title="Default dropdown"

Here's the basic Library spec file:

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { LibraryComponent } from './library.component';

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

  it('should create the component', () => {
    const fixture = TestBed.createComponent(LibraryComponent);
    const lib = fixture.debugElement.componentInstance;
    expect(lib).toBeTruthy();
  });
});

Neither the Library component nor the Dropdown component have associated modules. My understanding is that this error may relate to the fact that I haven't imported the Dropdown component into the Library module, or something, but

  • A) I'm not sure how to do that,
  • B) I'm then not sure how to incorporate that module into the app at large, and
  • C) I'm not sure what the value of that is, outside of getting the test to work.

Is there a way to get the test to work without converting these components to modules? Should all route components be modules?

EDIT

Adding The dropdown component, if relevant:

<div
  class="dropdown"
  [ngClass]="{ open: open }"
  tab-index="-1"
  [class]="class"
  #dropdown
>
  <div class="dropdown__toggle" (click)="onTitleClick(dropdown)">
    <span class="dropdown__title">{{ finalTitle() }}</span>
    <span class="dropdown__icon icon-arrow-down"></span>
  </div>
  <div *ngIf="open" class="dropdown__menu">
    <ul>
      <li
        *ngFor="let item of items; let ind = index"
        class="dropdown__item"
        [ngClass]="{ selected: selectedIndex === ind }"
        (click)="onItemClick(dropdown, item, ind)"
      >
        <span class="dropdown__label">{{ item }}</span>
      </li>
    </ul>
  </div>
</div>

And:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

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

  @Input() items: Array<string>;
  @Input() public selectedIndex: number = null;
  @Input() public title = 'Select one';
  @Input() public open = false;
  @Input() public class = '';

  @Output() pick = new EventEmitter();

  constructor() { }

  ngOnInit() {}

  finalTitle () {
    return typeof this.selectedIndex === 'number'
      ? this.items[this.selectedIndex]
      : this.title;
  }

  onItemClick(dropdown, item, index) {
    this._blur(dropdown);
    this.selectedIndex = index;
    this.open = false;
    this.pick.emit({ item, index });
  }

  onTitleClick(dropdown) {
    this._blur(dropdown);
    this.open = !this.open;
  }

  _blur(dropdown) {
    if (dropdown && dropdown.blur) { dropdown.blur(); }
  }
}
dmcgrandle

Updated to more clearly answer your 3 questions

A) There are many ways to accomplish this without creating new modules. You could simply import the DropdownComponent into your test module as André suggests below. I outline another method below in this answer that stubs the DropdownComponent, just for the purpose of testing LibraryComponent. Hopefully this answers the question of "how to do that".

B) The stub I suggest isn't a module - it is barely even a component. There is no need to incorporate the stub into the app at large, it's only purpose is to test LibraryComponent.

C) The value of this stub is only to test LibraryComponent, that is why it is a good idea to keep it as simple as possible.

This is one way of getting the test to work without converting your components to modules.

Stubbing DropdownComponent:

Below is a method to stub the DropdownComponent that you are attempting to use inside of LibraryComponent. Your error that you detail in your question is directly related to the fact that you have no 'app-dropdown' selector defined, yet your LibraryComponent is attempting to bind to it. Assuming you want to only test LibraryComponent within the library.component.spec.ts file, I suggest stubbing the DropdownComponent functionality rather than importing the actual component into the test. I created a Stackblitz to show what I mean.

From the Stackblitz, here is a snip from the library.component.spec.ts file:

@Component({
    selector: 'app-dropdown',
    template: `<h5>Dropdown</h5>`
})
class TestDropdownComponent {
    @Input() items;
    @Input() title;
    @Output() pick = new EventEmitter<any>();
}

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

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [ RouterTestingModule ],
            declarations: [ 
                TestDropdownComponent,
                LibraryComponent
            ]
        }).compileComponents();
        fixture = TestBed.createComponent(LibraryComponent);
    }));
    it('should create the component', () => {
      const fixture = TestBed.createComponent(LibraryComponent);
      const lib = fixture.debugElement.componentInstance;
      expect(lib).toBeTruthy();
    });
});

Note - If you want to reproduce the error you detail in your question within the Stackblitz, simply comment out the line for TestDropdownComponent in the declarations of the TestBed so it looks like so:

TestBed.configureTestingModule({
    imports: [ RouterTestingModule ],
    declarations: [ 
        // TestDropdownComponent,
        LibraryComponent
    ]
}).compileComponents();

And you will once again be testing just your component without a mock/stub of DropdownComponent to bind to.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Unit test Angular with Jasmine and Karma, Error:Can't bind to 'xxx' since it isn't a known property of 'xxxxxx'.

Angular unit test error - Can't bind to 'formGroup' since it isn't a known property of 'form'

Angular Can't bind to 'dirUnless' since it isn't a known property

Error: Can't bind to 'ngModel' since it isn't a known property of

Angular Karma Jasmine test "Can't bind to 'ngIf' since it isn't a known property"

Can't bind to '(ngModel' since it isn't a known property of 'input' in angular unit test case

Angular 4. Error "Can't bind to 'ngModule' since it isn't a known property of" but FormsModule is imported in app.module.shared.ts

Can't bind to 'data' since it isn't a known property of 'app-child'. (angular 12)

Angular 2 *ngFor error: Can't bind to 'menuitemtype' since it isn't a known property of 'div'

Angular 7 compilation error NG8002 can't bind object since it isn't a known property

Angular error: "Can't bind to 'ngModel' since it isn't a known property of 'input'"

Angular error : Can't bind to 'ngForFrom' since it isn't a known property of 'a'

ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

Angular2 unit testing error: Can't bind to 'routerLink' since it isn't a known property of 'a'

Angular: ternary operator in ngFor throw error Can't bind to 'ngFor' since it isn't a known property of 'div'

Angular 5 Error:Can't bind to 'ngForFor' since it isn't a known property of 'li'

error NG8002: Can't bind to 'formGroup' since it isn't a known property of 'form'. In Angular 9

Angular error message: Can't bind to 'formGroup' since it isn't a known property of 'form'

Angular: call of componenr error : can't bind to xxx since it isn't a known property of yyy

Error: Can't bind to 'routerLink' since it isn't a known property of 'a'. with standalone component in Angular 15

Can't bind to property since it isn't a known property of a component

Can't bind to 'property' since it isn't a known property of 'component'

Can't bind to 'value' since it isn't a known property of 'ngx-select-dropdown'

Can't bind to 'placeholder' since it isn't a known property of 'ng-multiselect-dropdown'

Can't bind to 'zIndex' since it isn't a known property of 'ng2-dropdown-menu'

Can't bind to 'startingCategory' since it isn't a known property of 'div'

Can't bind to 'mdDatepicker' since it isn't a known property of 'input'

Can't bind to 'ngModel' since it isn't a known property of 'input'?

Can't bind to 'formControl' since it isn't a known property of 'select'

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive