【发布时间】:2019-12-24 17:50:05
【问题描述】:
我有一个附加到元素上的事件的角度指令:
@Directive({
selector: '[myDirective]'
})
export class MyDirective {
@HostListener('click', ['$event']) click(event: Event): void {
debugger;
console.log(event); // <-- this is null in unit tests, MouseEvent when running the app normally
}
}
这很好用,但由于某种原因,在对指令进行单元测试时,事件参数是null。
我的 Karma Jasmine 单元测试设置:
import { CommonModule } from '@angular/common';
import { Component, DebugElement, ElementRef, Injector } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
@Component({
selector: 'host-component',
template: `
<input type="text" myDirective id="findMe"/>
`
})
class HostComponent {
}
describe(`MyDirective`, () => {
let host: HostComponent;
let fixture: ComponentFixture<HostComponent>;
let debugElement: DebugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CommonModule
],
declarations: [
HostComponent, MyDirective
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HostComponent);
host = fixture.componentInstance;
debugElement = fixture.debugElement.query(By.css('#findMe'))
fixture.autoDetectChanges();
});
describe(`should listen to the events`, () => {
it(`should listen to the click event`, () => {
fixture..triggerEventHandler('click', null);
fixture.detectChanges();
// expect...
});
});
});
现在,问题是:该指令在单元测试中被命中,但没有event 作为参数发送。
我遵循了这个例子:https://codecraft.tv/courses/angular/unit-testing/directives/ 但不幸的是它没有使用事件参数。
编辑
我还按照this example 将参数传递给@HostListener() 装饰器:
@HostListener('mouseenter', ['$event.target.id'])
onMouseEnter(id: string) {
// Logs the id of the element
// where the event is originally invoked.
console.log(id);
}
编辑 2
似乎 DebugElement 引发的事件并不能真正代表 DOM 元素的实际事件侦听器?
根据 Hojou 所说的on this angular github issue,如果您从 nativeElement 触发事件,它就会起作用。所以下面的代码确实通过事件发送到指令,只是不太确定它是否是正确的方式:
describe(`should listen to the events`, () => {
it(`should listen to the click event`, () => {
// fixture.triggerEventHandler('click', null);
debugElement.nativeElement.dispatchEvent(newEvent('click'));
fixture.detectChanges();
// expect...
});
});
function newEvent(eventName: string) {
const customEvent: CustomEvent<any> = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
customEvent.initCustomEvent(eventName, false, false, null);
return customEvent;
}
【问题讨论】:
标签: angular unit-testing karma-jasmine angular-directive