Angular2 unit test with @Input()
Solution 1:
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 beforeEach
beforeEach( async(() => {
TestBed.configureTestingModule({
declarations: [ DashboardHeroComponent ],
})
.compileComponents(); // compile template and css
}));
// synchronous beforeEach
beforeEach(() => {
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
});
Solution 2:
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()
}
Solution 3:
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.