Как проверить директиву с Renderer2? - PullRequest
0 голосов
/ 24 июня 2019

Я создал небольшую директиву, которая предотвращает передачу по умолчанию событий, переданных ей.

@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. Как правильно проверить это?

1 Ответ

1 голос
/ 24 июня 2019

Хорошо, так как заинтересовался, я проверил некоторые вещи, но это не будет прямым ответом или даже решением вашей проблемы, хотя вы можете найти что-то полезное.

Похоже, что 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>);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...