我创建了一个小指令,可防止传递给它的默认事件。
@Directive({
selector: '[sPreventDefault]'
})
export class PreventDefaultDirective {
private events: (() => void)[] = [];
@Input('sPreventDefault') set listenOn(events: string | string[]) {
this.removeListeners();
if (typeof events == 'string') {
events = [events];
}
this.registerEventListener(
events,
e => {
if (e instanceof Event) {
e.stopPropagation();
} else {
e.srcEvent.stopPropagation();
}
},
);
}
constructor(private elementRef: ElementRef<HTMLElement>, private renderer: Renderer2) {
super(elementRef, renderer);
}
protected registerEventListener(listenOn: string[], eventListener: (e: Event | HammerJSEvent) => void): void {
this.events = listenOn.map(eventName => {
return this.renderer.listen(this.elementRef.nativeElement, eventName, eventListener);
});
}
protected removeListeners(): void {
this.events.forEach(dispose => dispose());
this.events = [];
}
}
测试服
@Component({
selector: 'test-host',
template: `<div [sPreventDefault]="events">`,
})
class TestHostComponent {
@ViewChild(PreventDefaultDirective) directive!: PreventDefaultDirective;
@Input() events: PreventDefaultDirective['listenOn'] = [];
}
fdescribe('PreventDefaultDirective', () => {
let host: TestHostComponent;
let hostElement: DebugElement;
let fixture: ComponentFixture<TestHostComponent>;
let directive: PreventDefaultDirective;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
TestHostComponent,
PreventDefaultDirective,
],
}).compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
hostElement = fixture.debugElement;
host = fixture.componentInstance;
directive = host.directive;
}));
it('should create an instance', () => {
host.events = ['testEvent'];
fixture.detectChanges();
expect(directive).toBeTruthy();
});
it('should add listener', () => {
host.events = ['testEvent'];
fixture.detectChanges();
// DebugElement.listeners is null
expect(hostElement.listeners.length).toBe(1);
expect(hostElement.listeners.map(l => l.name)).toBe(host.events);
});
});
我的问题是,DebugElement
似乎不知道通过Renderer2.listen
方法注册的事件。什么是正确的测试方法?
答案 0 :(得分:1)
好吧,自从有兴趣以来,我检查了一些事情,尽管您可以找到有用的东西,但它不是直接的答案,甚至也不是解决问题的方法。
似乎hostElement.listeners
指向@HostListener
装饰器添加的事件侦听器,您可以轻松地进行检查。
我还试图找到一种方法来检索侦听器,但没有成功。
我在这里要做的是每当调用renderer.listen
时检查并把实现留在后面-这种方式对于高于“单元测试”的测试可能是错误的,因为您要检查这是否真的有效但是对于单元而言应该没事。如果您想监视Renderer2
,可以执行以下操作:
const renderer = fixture.componentRef.injector.get(Renderer2);
const listenSpy = spyOn(renderer, 'listen');
expect(listenSpy).toHaveBeenCalled();
编辑1:
由于不建议使用提供的获取Renderer2
的方法,因此应使用:
const renderer = fixture.componentRef.injector.get(Renderer2 as Type<Renderer2>);