Reputation: 175
I'm trying to unit test a directive in Angular 11 with Jest 28. I need to simulate a click on an image, so I'm using the following code to mock the mouse event:
import { HTMLClickDirective } from "./html-click.directive";
describe('HTMLClickDirective', () => {
it('should open a lightbox for images', () => {
const directive = new HTMLClickDirective(null);
const image = new HTMLImageElement;
image.setAttribute('src','foo');
let click = {target: image} as unknown as MouseEvent;
directive.onClick(click);
expect(directive.openLightbox).toHaveBeenCalled();
});
});
Typescript doesn't flag anything as amiss, but Jest complains: "TypeError: Invalid constructor, the constructor is not part of the custom element registry".
Same complaint when I just try to make an HTMLElement
and cast it to HTMLImageElement
. If I just try to make a new Element
for later type coercion, it complains, "TypeError: Illegal constructor".
Same thing happens when I move the variable assignment out of the describe block.
Maybe a JSDOM thing?
Edit: Directive being tested:
import { Directive, HostListener } from "@angular/core"
import { BsModalRef, BsModalService } from "ngx-bootstrap/modal"
import { ModalLightboxComponent } from "../components/shared/modal-lightbox/modal-lightbox.component";
/**
* Handle click events on HTML elements inside a safe HTML content projection.
*
* @example
* ```html
* <div [innerHtml]="..." HTMLClick></div>
* ```
*/
@Directive({
selector: "[HTMLClick]",
})
export class HTMLClickDirective {
modalRef: BsModalRef;
constructor(
private modalService: BsModalService,
) {}
/**
* Listener for click events in any HTMLElement.
*/
@HostListener("click", ["$event"])
onClick($event: MouseEvent) {
const target = $event.target as any
switch (target.constructor) {
case HTMLImageElement:
$event.preventDefault()
this.handleImageElement(target)
break;
case HTMLElement:
$event.preventDefault()
this.handleElement(target)
break;
default:
break;
}
}
openLightbox(img: string) {
this.modalRef = this.modalService.show(ModalLightboxComponent, {
animated: false,
class: 'lightbox',
initialState: {
modalPath: img,
closeModal: this.closeModal.bind(this),
}
});
}
closeModal() {
this.modalRef?.hide();
}
private async handleImageElement(target: HTMLImageElement): Promise<void> {
this.openLightbox(target.getAttribute('src'));
}
private async handleElement(target: HTMLElement): Promise<void> {
console.log(target)
if(target.nodeName === 'STRONG') document.querySelector('[id="' + target.innerText.toLowerCase() + '"]').scrollIntoView();
}
}
Upvotes: 1
Views: 2197