[英]How test directive with Renderer2?
I have created a small directive that prevents default of event(s) passed to it. 我创建了一个小指令,以防止传递给它的默认事件。
@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 = [];
}
}
Test suit 测试服
@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);
});
});
My problem is, that DebugElement
, does not seems to know about events registered via Renderer2.listen
method. 我的问题是,
DebugElement
似乎不了解通过Renderer2.listen
方法注册的事件。 What is the right way to test this? 什么是正确的测试方法?
Ok since got interested I checked some things but it won't be straight answer or even solution to your problem although you can find something useful. 好吧,自从有兴趣以来,我检查了一些事情,尽管您可以找到有用的东西,但它不是直截了当的答案,甚至也无法解决您的问题。
It looks like hostElement.listeners
points to event listeners added by @HostListener
decorator, you can easily check that. 看起来
hostElement.listeners
指向@HostListener
装饰器添加的事件侦听器,您可以轻松地进行检查。 I've also try to find way to retrieve listeners but without success. 我也尝试寻找方法来检索侦听器,但没有成功。
What I would do here is to check whenever renderer.listen
was called and leave implementation behind - this way could be wrong for testing higher than "unit tests" since you want to check if this really works but for unit it should be fine. 我在这里要做的是检查何时调用
renderer.listen
并把实现留在后面-这种方式对于高于“单元测试”的测试可能是错误的,因为您要检查这是否确实有效,但对于单元来说应该没问题。 If you want to spy on Renderer2
you can do this: 如果要监视
Renderer2
,可以执行以下操作:
const renderer = fixture.componentRef.injector.get(Renderer2);
const listenSpy = spyOn(renderer, 'listen');
expect(listenSpy).toHaveBeenCalled();
Edit 1: Since provided way of getting Renderer2
is deprecated this should be used: 编辑1:由于不建议使用提供
Renderer2
方式,因此应使用:
const renderer = fixture.componentRef.injector.get(Renderer2 as Type<Renderer2>);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.