I have a little directive that detects if the user has clicked outside the HTML element that the directive has been attached to, it looks like this, nothing special:
@Directive({
selector: '[vcrClickOutside]'
})
export class ClickOutsideDirective {
constructor(private elementRef: ElementRef) { }
@Output()
clickOutside = new EventEmitter();
@HostListener('document:click', ['$event.target'])
onClick(targetElement): void {
const clickedInside = this.elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this.clickOutside.emit(targetElement);
}
}
}
Now it is time to test my directive so I created a test file, introduce a Mock Component, attach the directive and within my test I click the Mock Component's Template and try to catch the emitter, here's the test:
// Mock Component
@Component({
template: '<div (clickOutside)="toggleClick($event)"><div vcrClickOutside>Oh I just love writing tests</div></div>'
})
class MockComponent {
constructor() { }
hasBeenClicked = false;
toggleClick(ev): void {
this.hasBeenClicked = !this.hasBeenClicked;
}
}
describe('ClickOutsideDirective', () => {
let component: MockComponent;
let fixture: ComponentFixture<MockComponent>;
let element: HTMLElement;
let outSideDiv: HTMLElement;
let insideDiv: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
MockComponent,
ClickOutsideDirective
]
});
fixture = TestBed.createComponent(MockComponent);
component = fixture.componentInstance;
element = fixture.debugElement.nativeElement;
outSideDiv = element.querySelectorAll('div')[0];
insideDiv = element.querySelectorAll('div')[1];
fixture.detectChanges();
});
it('click the outer div thus emitting the clickOutside and toggle the component value', () => {
outSideDiv.click();
fixture.detectChanges();
expect(component.hasBeenClicked).toBeTruthy();
});
Everything seems fine but when I click the outside div, even though I know that the directive is emitting the @Output
on the outer div isn't being raised, so looking at the code (clickOutside)
isn't invoked and thus the method toggleClick($event)
isn't ran, what am I doing wrong?
*** UPDATE ****
I had the output on the wrong div! I am an idiot!
As answered in my comments - I put the emitter in the wrong location!
@Component({
template: '<div><div vcrClickOutside (clickOutside)="toggleClick($event)">Oh I just love writing tests</div></div>'
})