Reputation: 17904
This seems like it should be simple, but I'm having trouble verifying that a click handler is invoked on my component.
header.component.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
@Output() hamburgerToggle = new EventEmitter<void>();
constructor() {}
ngOnInit(): void {}
hamburgerClicked(): void {
this.hamburgerToggle.emit();
}
}
header.component.html
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<div class="hamburger header-toggle">
<button (click)="hamburgerClicked()" class="btn btn-link btn-sm order-first order-first header-toggle" id="sidebarToggle" href="/">
<i class="material-icons header-toggle">menu</i>
</button>
</div>
</nav>
header.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HeaderComponent]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('clicking the toggle button invoke our click handler', () => {
const fixture = TestBed.createComponent(HeaderComponent);
const clickSpy = spyOn(component, 'hamburgerClicked');
const toggleButton = fixture.debugElement.query(By.css('#sidebarToggle'));
toggleButton.triggerEventHandler('click', toggleButton);
fixture.detectChanges();
expect(clickSpy).toHaveBeenCalledTimes(1);
});
});
The error message given is:
Expected spy hamburgerClicked to have been called once. It was called 0 times.
I've also tried this inside an async block, but received the same result:
fit('clicking the toggle button invoke our click handler', fakeAsync(() => {
const fixture = TestBed.createComponent(HeaderComponent);
const clickSpy = spyOn(component, 'hamburgerClicked');
const toggleButton = fixture.nativeElement.querySelector('#sidebarToggle');
toggleButton.click();
tick();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(clickSpy).toHaveBeenCalledTimes(1);
});
}));
I've been at this for hours and can't figure out what I'm missing. Any help is much appreciated.
Upvotes: 0
Views: 201
Reputation: 102457
You create a new fixture
(component instance) in each test case. But you spy the component which created in beforeEach
. So, you are triggering the click event on each new component instance, they are not the same component.
You should add a spy, query DOM element, and trigger the click event on the same component instance.
Remove the below statement in each test case will work:
const fixture = TestBed.createComponent(HeaderComponent);
header.component.ts
:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { HeaderComponent } from './header.component';
fdescribe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HeaderComponent],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('clicking the toggle button invoke our click handler', () => {
const clickSpy = spyOn(component, 'hamburgerClicked');
const toggleButton = fixture.debugElement.query(By.css('#sidebarToggle'));
toggleButton.triggerEventHandler('click', toggleButton);
expect(clickSpy).toHaveBeenCalledTimes(1);
});
it('clicking the toggle button invoke our click handler', () => {
const clickSpy = spyOn(component, 'hamburgerClicked');
const toggleButton = fixture.nativeElement.querySelector('#sidebarToggle');
toggleButton.click();
expect(clickSpy).toHaveBeenCalledTimes(1);
});
});
unit test result:
Chrome 80.0.3987.87 (Mac OS 10.13.6): Executed 2 of 17 (skipped 15) SUCCESS (0.1 secs / 0.045 secs)
TOTAL: 2 SUCCESS
✔ Browser application bundle generation complete.
✔ Browser application bundle generation complete.
Upvotes: 2