我创建了一个小指令,可以防止传递给它的事件默认。
@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
装饰器添加的事件监听器,您可以轻松检查。
我也尝试找到方法来检索听众,但没有成功。
我在这里要做的是检查 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>);
关于angular - 如何使用 Renderer2 测试指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56737965/