Объект события Angular2 + Jasmine

У меня есть этот простой метод, который нужно проверить:

  public onLayerContainerClick(event: Event): void {
    event.stopPropagation();
    event.preventDefault();
    if (event.srcElement.classList.contains('dpm-info__layerContainer')) {
     this.closeInfoLayer(event);
    }
  }

Моя цель на самом деле состоит в том, чтобы увеличить покрытие кода для компонента. Если я тестирую так:

  it( 'should close on info container click', () => {
    spyOn( component, 'onLayerContainerClick' );
    const el: DebugElement = fixture.debugElement.query( By.css( '.dpm-info__layerContainer' ) );
    el.triggerEventHandler( 'click', null );
    expect( component.onLayerContainerClick ).toHaveBeenCalled();
  } );

тест в порядке, но в Стамбуле написано «функция не покрыта». Итак, я думаю, мне нужно явно вызвать функцию? Для этого мне нужен полный объект события, включая (как минимум) свойство srcTarget. Как определить такое событие в модульном тесте?


person pop    schedule 08.12.2017    source источник


Ответы (2)


Вы должны вызвать функцию с имитированным событием в тесте. component.onLayerContainerClick({ srcElement: { value: 'mock_value' } });

А затем напишите, что вы ожидаете

expect( component.closeInfoLayer ).toHaveBeenCalled();

Возможно, этот https://angular.io/guide/testing#triggereventhandler также может помочь.

person DrNio    schedule 08.12.2017
comment
Проблема заключается в Typescript, который ожидает, что аргумент, переданный в onLayerContainerClick, будет иметь тип Event. Просто передать объект со свойством srcTarget не получится - я получаю ошибку типа. - person pop; 08.12.2017
comment
ок, а можешь также опубликовать beforeEach в начале каждого теста? кстати, если вы попробуете component.onLayerContainerClick(‹any›{ srcElement: { value: 'mock_value' } }); или ‹Событие› вы получаете ошибки? - person DrNio; 08.12.2017
comment
@pop Не проблема. Типы существуют, чтобы помочь вам, а не создавать препятствия. Вы можете передать любой аргумент, который вам нужен, с помощью <any>arg или <Event><any>arg. - person Estus Flask; 08.12.2017
comment
да, для имитации входных данных это не должно быть проблемой - person DrNio; 08.12.2017
comment
Что ж, я преодолел первое препятствие и могу создать объект типа Event, как вы, ребята, говорите. Однако (здесь мы идем), эта строка в компоненте event.srcElement.classList.contains ожидает, что classList будет иметь тип DOMTokenList, который имеет свои собственные методы и свойства (см. здесь stackoverflow.com/questions/29172515/). - person pop; 08.12.2017

Благодаря estus и DrNio я придумал этот тест, который делает стамбульское покрытие кода удовлетворительным и не имеет проблем с типами:

  it( 'should close on info container click', () => {
    spyOn( component, 'closeInfoLayer' );
    const el: HTMLElement = fixture.debugElement.query(By.css('.dpm-info__layerContainer')).nativeElement;
    const mockEvent: Event = <Event><any>{
      srcElement: {
        classList: el.classList
      },
      stopPropagation: <any>( ( e: any ) => { /**/ }),
      preventDefault: <any>( ( e: any ) => { /**/ }),
    };

    component.onLayerContainerClick( mockEvent );
    expect( component.closeInfoLayer ).toHaveBeenCalled();
  } );
person pop    schedule 08.12.2017
comment
я думаю, что вам не нужно spyOn( component, 'closeInfoLayer' );. Я думаю, что это используется в основном, когда вы хотите проверить вызовы функций внешних служб, например: spyOn(myService, 'aMethodThere'); - person DrNio; 08.12.2017
comment
хорошо, мне нужно кое-что еще раз протестировать. в этом методе не задана переменная, и единственным результатом является вызов функции. так это то, что я тестирую - это называется. как еще? - person pop; 08.12.2017
comment
если вы удалите spyOn( component, 'closeInfoLayer' );, это должно сработать, потому что он передаст оператор if, так как вы издеваетесь над событием. попробуйте и дайте нам знать - person DrNio; 08.12.2017
comment
что мне expect тогда? просто удаление spyOn и оставление expect вызовет ошибку. - person pop; 08.12.2017
comment
можешь написать ошибку сюда? я думаю, если он выдает ошибку, это означает, что он не передал оператор if и closeInfoLayer не был вызван - person DrNio; 08.12.2017