Модульное тестирование по компонентным методам угловых 7 - PullRequest
0 голосов
/ 14 декабря 2018

Код моего компонента -

import { Component, EventEmitter, Input, OnInit, OnChanges, SimpleChanges,  Output } from '@angular/core';
import { CI, CiWithStatus } from '../ci-list.service';
import { ContextPanelApi } from '../../../../../../../../shared/shared-html/js/directives/oprContextPanel/oprContextPanel/oprContextPanelApi.service';

@Component({
  selector: 'opr-watchlist-cards',
  templateUrl: './watchlist-cards.component.html',
  styleUrls: ['./watchlist-cards.component.scss']
})
export class WatchlistCardsComponent implements OnInit, OnChanges {

  @Input() ciList: CiWithStatus[];
  @Input() itemWidth: number;
  @Input() itemHeight: number;
  @Input() zoomLevel: number;

  @Output() onSelectedCisChanged: EventEmitter<CI[]> = new EventEmitter<CI[]>();

  private _selectedItems: CI[] = [];

  constructor(private _oprContextPanelApiService: ContextPanelApi) {
  }

  ngOnInit() {
    console.debug('ciList', this.ciList);
  }

  ngOnChanges(changes: SimpleChanges): void {
    if(changes.zoomLevel) {
      this.zoomLevel = changes.zoomLevel.currentValue;
    }
  }

  onItemClick(event: MouseEvent, ci: CI) {
    if (event.ctrlKey) {
      if (this.isSelected(ci)) {
        this._selectedItems.splice(this._selectedItems.indexOf(ci), 1);
      } else {
        this._selectedItems.push(ci);
      }
    } else {
      this._selectedItems = [ci];
    }
    this.onSelectedCisChanged.emit(this._selectedItems);
  }

  onItemRightClick(event: MouseEvent, ci: CI) {
    const position = {left: event.clientX, top: event.clientY};
    const contextPanelConfig = {
      title: 'context menu dummy ' + ci.name,
      position
    };
    const contextPanelPages = [];
    this._oprContextPanelApiService.openContext(contextPanelConfig, contextPanelPages, () => {
    });
    return false; //prevent native browser context menu
  }

  isSelected(ci: CI) {
    return this._selectedItems.includes(ci);
  }
}

Код файла My Spec -

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SimpleChange } from '@angular/core';
import { WatchlistCardsComponent } from './watchlist-cards.component';
import { AppSharedModule } from '../../../../../app-shared/src/lib/app-shared.module';
import { WatchlistCardComponent } from './watchlist-card/watchlist-card.component';
import { ContextPanelApi } from 'shared/directives/oprContextPanel/oprContextPanel/oprContextPanelApi.service';

export class MockContextPanelApi {

}

describe('WatchlistCardsComponent', () => {
  let component: WatchlistCardsComponent;
  let fixture: ComponentFixture<WatchlistCardsComponent>;
  let params;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [AppSharedModule],
      declarations: [WatchlistCardComponent, WatchlistCardsComponent],
      providers: [{ provide: ContextPanelApi, useClass: MockContextPanelApi }]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(WatchlistCardsComponent);
    component = fixture.componentInstance;
    params = {
      ci: {
        global_id: "9e76bafea39c49e786360baeb2551fd7",
        icon: "/odb/icons/unix/unix_32.svg",
        id: "9e76bafea39c49e786360baeb2551fd7",
        last_changed: 1540465938749,
        long_id: "1;;9e76bafea39c49e786360baeb2551fd7",
        name: "srv0",
        status: 0,
        type: "unix",
        type_label: "Unix",
        event: "link"
      },
      event: {

      }
    };
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should call ngOnChanges', () => {
    component.zoomLevel = 3;
    component.ngOnChanges({
      zoomLevel: new SimpleChange(null, component.zoomLevel, true)
    });
    fixture.detectChanges();
  })

  it('should call the onItemClick method', async(() => {
    spyOn(component, 'onItemClick');
    component.onItemClick(params.event, params.ci);
    fixture.whenStable().then(() => {
      expect(component.onItemClick).toHaveBeenCalled();
    });
  }));

  it('should call the onItemRightClick method', async(() => {
    spyOn(component, 'onItemRightClick');
    component.onItemRightClick(params.event, params.ci);
    expect(component.onItemRightClick).toHaveBeenCalled();
  }));

  it('should call the isSelected method', async(() => {
    spyOn(component, 'isSelected');
    component.isSelected(params.ci);
    expect(component.isSelected).toHaveBeenCalled();
  }));

});

Я хотел охватить функции, я пытался сделать это в спецификации, но все равно он говорит, что функции не покрыты.

Пожалуйста, объясните мне, как я могу описать функции и операторы для методов isSelected, onItemRightClick, onItemClick

Спасибо.

1 Ответ

0 голосов
/ 14 декабря 2018

Причина - spyOn(), он заменит оригинальный метод заглушкой.Читайте об этом в Жасмин Док для шпиона .Итак, когда вы звоните component.onItemClick.Вы просто вызываете шпиона, а не исходную функцию.Следовательно, нет покрытия кода.

Исправлено: spyOn(component, 'onItemClick').and.callThrough();.Это также объясняется в документе.

Тем не менее, ИМО тесты, которые вы пишете, не очень полезны .Например:

 line 1:     component.onItemClick(params.event, params.ci);
             fixture.whenStable().then(() => {   
 line 2:    expect(component.onItemClick).toHaveBeenCalled();  

line 1 - Вы вручную набираете onRightClick().Поскольку вы вызываете функцию вручную, line 2 всегда будет истинным.Тем не менее, IRL эта функция будет срабатывать при щелчке правой кнопкой мыши / элементе в HTML.

Что вам нужно сделать, это получить ссылку на компонент, как (я не проверял этот код, это просто ссылка, и яПредположим, у вас есть элемент (кнопка), который имеет onclick):

let fixture: ComponentFixture<WatchlistCardsComponent>;    
const buttonEle: HTMLElement = fixture.nativeElement.querySelector('button');
spyOn(component, 'onItemClick');
button.click();
fixture.whenStable().then(() => {   
   expect(component.onItemClick).toHaveBeenCalled(); ...

Это создаст шпион на компоненте функции (так же, как вы сделали), разница в том, что вы не вызываете onItemClick вручную, но нажатие кнопки вызовет автоматический вызов функции, поэтому нет необходимости вызывать eventHandler вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...