Testing Angular Components with Inputs and Outputs using Jest
io.component.ts import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'app-io', template: ` My favourite color is: {{color}} `, }) export class IoComponent { @Input() color = ''; @Output() colorChange = new EventEmitter(); changeColor() { this.colorChange.emit('pink'); } } When testing Angular components with @Input() and @Output(), we need to verify they work as they would in a real app. The best way? Mock their parent (host) component. This approach lets us: Control input values passed to the component. Capture emitted events exactly like a real parent would. io-component.spec.ts import { ComponentFixture, TestBed } from '@angular/core/testing'; import { IoComponent } from './io.component'; import { Component, ViewChild } from '@angular/core'; @Component({ template: ` ` }) class HostComponent { @ViewChild(IoComponent) ioComponent!: IoComponent; hostColor = 'red'; emittedColor = ''; onColorChanged(color: string) { this.emittedColor = color; }; } describe('IoComponent', () => { let hostComponent: HostComponent; let hostFixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ declarations: [IoComponent, HostComponent] }); hostFixture = TestBed.createComponent(HostComponent); hostComponent = hostFixture.componentInstance; hostFixture.detectChanges(); }); it('should create', () => { expect(hostComponent.ioComponent).toBeTruthy(); }); describe('Input binding', () => { it('should receive initial color from host', () => { expect(hostComponent.ioComponent.color).toBe('red'); }); it('should update when host changes color', () => { hostComponent.hostColor = 'blue'; hostFixture.detectChanges(); expect(hostComponent.ioComponent.color).toBe('blue'); }); }); describe('Output binding', () => { it('should emit new color when button clicked', () => { const button = hostFixture.nativeElement.querySelector('button'); button.click(); expect(hostComponent.emittedColor).toBe('pink'); }); it('should emit through direct component call', () => { const spy = jest.spyOn(hostComponent.ioComponent.colorChange, 'emit'); hostComponent.ioComponent.changeColor(); expect(spy).toHaveBeenCalledWith('pink'); }); }); });

io.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-io',
template: `
My favourite color is: {{color}}
`
,
})
export class IoComponent {
@Input() color = '';
@Output() colorChange = new EventEmitter<string>();
changeColor() {
this.colorChange.emit('pink');
}
}
When testing Angular components with @Input()
and @Output()
, we need to verify they work as they would in a real app. The best way? Mock their parent (host) component.
This approach lets us:
- Control input values passed to the component.
- Capture emitted events exactly like a real parent would.
io-component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { IoComponent } from './io.component';
import { Component, ViewChild } from '@angular/core';
@Component({
template: `
`
})
class HostComponent {
@ViewChild(IoComponent) ioComponent!: IoComponent;
hostColor = 'red';
emittedColor = '';
onColorChanged(color: string) {
this.emittedColor = color;
};
}
describe('IoComponent', () => {
let hostComponent: HostComponent;
let hostFixture: ComponentFixture<HostComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [IoComponent, HostComponent]
});
hostFixture = TestBed.createComponent(HostComponent);
hostComponent = hostFixture.componentInstance;
hostFixture.detectChanges();
});
it('should create', () => {
expect(hostComponent.ioComponent).toBeTruthy();
});
describe('Input binding', () => {
it('should receive initial color from host', () => {
expect(hostComponent.ioComponent.color).toBe('red');
});
it('should update when host changes color', () => {
hostComponent.hostColor = 'blue';
hostFixture.detectChanges();
expect(hostComponent.ioComponent.color).toBe('blue');
});
});
describe('Output binding', () => {
it('should emit new color when button clicked', () => {
const button = hostFixture.nativeElement.querySelector('button');
button.click();
expect(hostComponent.emittedColor).toBe('pink');
});
it('should emit through direct component call', () => {
const spy = jest.spyOn(hostComponent.ioComponent.colorChange, 'emit');
hostComponent.ioComponent.changeColor();
expect(spy).toHaveBeenCalledWith('pink');
});
});
});