我创建了一个小指令,以防止事件传递给它。
@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
方法注册的事件。测试此问题的正确方法是什么?
好的,因为有兴趣,我检查了一些东西,但这并不是直接的答案甚至解决问题,尽管您可以找到有用的东西。
看来hostElement.listeners
指向@HostListener
Decorator添加的事件侦听器,您可以轻松地检查。我也尝试找到检索听众但没有成功的方式。
我在这里要做的是检查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>);