Angular2 unit test with @Input()
this is from official documentation https://angular.io/docs/ts/latest/guide/testing.html#!#component-fixture. So you can create new input object expectedHero and pass it to the component comp.hero = expectedHero
Also make sure to call fixture.detectChanges();
last, otherwise property will not be bound to component.
Working Example
// async beforeEachbeforeEach( async(() => { TestBed.configureTestingModule({ declarations: [ DashboardHeroComponent ], }) .compileComponents(); // compile template and css}));// synchronous beforeEachbeforeEach(() => { fixture = TestBed.createComponent(DashboardHeroComponent); comp = fixture.componentInstance; heroEl = fixture.debugElement.query(By.css('.hero')); // find hero element // pretend that it was wired to something that supplied a hero expectedHero = new Hero(42, 'Test Name'); comp.hero = expectedHero; fixture.detectChanges(); // trigger initial data binding});
If you use TestBed.configureTestingModule
to compile your test component, here's another approach. It's basically the same as the accepted answer, but may be more similar to how angular-cli generates the specs. FWIW.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import { async, ComponentFixture, TestBed } from '@angular/core/testing';import { DebugElement } from '@angular/core';describe('ProductThumbnail', () => { let component: ProductThumbnail; let fixture: ComponentFixture<TestComponentWrapper>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ TestComponentWrapper, ProductThumbnail ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) .compileComponents(); fixture = TestBed.createComponent(TestComponentWrapper); component = fixture.debugElement.children[0].componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); });});@Component({ selector: 'test-component-wrapper', template: '<product-thumbnail [product]="product"></product-thumbnail>'})class TestComponentWrapper { product = new Product()}
You need to set the product
value on the component instance after it has been loaded within your test.
As a sample here is a simple component within an input that you can use as a foundation for your use case:
@Component({ selector: 'dropdown', directives: [NgClass], template: ` <div [ngClass]="{open: open}"> </div> `,})export class DropdownComponent { @Input('open') open: boolean = false; ngOnChanges() { console.log(this.open); }}
And the corresponding test:
it('should open', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => { return tcb.createAsync(DropdownComponent) .then(fixture => { let el = fixture.nativeElement; let comp: DropdownComponent = fixture.componentInstance; expect(el.className).toEqual(''); // Update the input comp.open = true; // <----------- // Apply fixture.detectChanges(); // <----------- var div = fixture.nativeElement.querySelector('div'); // Test elements that depend on the input expect(div.className).toEqual('open'); });}));
See this plunkr as a sample: https://plnkr.co/edit/YAVD4s?p=preview.