Модульное тестирование с использованием Jasmine / Karma на угловом компоненте Google Charts - PullRequest
0 голосов
/ 14 декабря 2018

Я не нашел никакого способа провести юнит-тест с Jasmine / Karma для компонента Angular2, который визуализирует график из Google Charts.Поэтому я предлагаю свои собственные вопросы и ответы в надежде, что это может помочь другим людям также протестировать его:

Что может быть хорошим способом написания надежного теста для компонента, подобного приведенному в примере ниже,у которого есть функция обновления вида диаграммы при изменении размера окна?

import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';

declare var google: any;

@Component({
  selector: 'app-chart',
  templateUrl: './chart.component.html',
  styleUrls: ['./chart.component.scss'],
})
export class ChartComponent implements OnInit {
  @Input()
  chartData: string[][];

  options: {} = {
    height: 320,
  };

  constructor(private router: Router) {}

  ngOnInit() {
    google.charts.load('current', { packages: ['corechart'] });
    google.charts.setOnLoadCallback(() => this.drawChart(this.chartData));
    window.addEventListener('resize', () => {
      if (this.router.url === '/chart') {
        return this.drawChart(this.chartData);
      }
    });
  }

  drawChart(chartData) {
    const data = google.visualization.arrayToDataTable(chartData);
    const chart = new google.visualization.LineChart(
      document.querySelector('#chart'),
    );
    chart.draw(data, this.options);
  }
}

Ответы [ 2 ]

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

Вам нужно внести одно изменение в свой макет google методов, и тогда этот обратный вызов будет протестирован.Измените ваш текущий код:

window['google'] = {
  charts: {
    load: function(): void {},
    setOnLoadCallback: function(callback: Function): Observable<any> {
      return Observable.create();
    },
  },

на:

window['google'] = {
  charts: {
    load: function(): void {},
    setOnLoadCallback: callback => callback(),
  },

Это заставит макет setOnLoadCallback() фактически вызвать предоставленный обратный вызов.

Тогда вы можете написать спецификацию, такую ​​как следующее, чтобы убедиться, что она работает:

it('should call the callback() method onInit', () => {
  const callBackSpy = spyOn(component, 'drawChart');
  component.ngOnInit();
  expect(callBackSpy).toHaveBeenCalled();
});

Я настроил все это в Stackblitz , чтобы показать, что он работает.

Надеюсь, это поможет.

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

Следующий фрагмент будет корректно проверять все функциональные возможности, проверяя методы рендеринга Google Charts на Angular, а также функциональность для обновления диаграммы при изменении размера окна:

import {
  TestBed,
  ComponentFixture,
  async,
  fakeAsync,
  tick,
} from '@angular/core/testing';
import { ChartComponent } from './chart2';
import { GoogleChartsModule } from 'angular-google-charts';
import { Observable } from 'rxjs';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';

@Component({
  template: '',
})
class DummyComponent {}

const mockChartData = [
  ['Date', 'Variable X', 'Variable Y'],
  ['29/sep.', '30', '29'],
  ['30/sep.', '30', '29'],
  ['01/oct.', '30', '29'],
  ['02/oct.', '30', '29'],
  ['03/oct.', '30', '29'],
  ['04/oct.', '30', '28'],
];

fdescribe('ChartComponent', () => {
  let component: ChartComponent;
  let fixture: ComponentFixture<ChartComponent>;
  let dom: HTMLElement;
  let location: Location;
  let router: Router;
  let dataSentToGoogleChartDrawMethod: [[], {}];
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ChartComponent, DummyComponent],
      imports: [
        GoogleChartsModule,
        RouterTestingModule,
        RouterTestingModule.withRoutes([
          {
            path: 'chart',
            component: DummyComponent,
          },
          {
            path: 'any-other-page',
            component: DummyComponent,
          },
        ]),
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ChartComponent);
    component = fixture.componentInstance;
    dom = fixture.debugElement.nativeElement;
    router = TestBed.get(Router);
    location = TestBed.get(Location);
    component.chartData = mockChartData;
    component.options = { options: 'custom options' };
    window['google'] = {
      charts: {
        load: function(): void {},
        setOnLoadCallback: function(callback: Function): Observable<any> {
          return Observable.create();
        },
      },
      visualization: {
        arrayToDataTable: function(data: string[][]): string[][] {
          return data;
        },
        LineChart: class {
          dataReceived: any;
          constructor(data: string[][]) {
            this.dataReceived = data;
          }
          draw = function(data: any, options: {}) {
            dataSentToGoogleChartDrawMethod = [data, options];
          };
        },
      },
    };
    fixture.detectChanges();
  });

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

  it('should call a Google Chart draw method onInit', async () => {
    const spySetOnLoadCallback = spyOn(
      google['charts'],
      'setOnLoadCallback',
    ).and.callThrough();
    component.ngOnInit();
    expect(spySetOnLoadCallback).toHaveBeenCalled();
  });

  it('should call Google Chart methods to build charts when drawChart is called', () => {
    component.drawChart(mockChartData);
    expect(dataSentToGoogleChartDrawMethod).toEqual([
      mockChartData,
      { options: 'custom options' },
    ]);
  });

  it('should re-render Chart when window is resized when on /charts page', fakeAsync(() => {
    router.navigate(['/chart']);
    tick();
    const spyOnDrawChart = spyOn(component, 'drawChart');
    expect(location.path()).toBe('/chart');
    window.dispatchEvent(new Event('resize'));
    expect(spyOnDrawChart).toHaveBeenCalled();
  }));

  it('should NOT try to re-render chart when window is resized on other pages than /chart', fakeAsync(() => {
    router.navigate(['/any-other-page']);
    tick();
    const spyOnDrawChart = spyOn(component, 'drawChart');
    expect(location.path()).toBe('/any-other-page');
    window.dispatchEvent(new Event('resize'));
    expect(spyOnDrawChart).not.toHaveBeenCalled();
  }));
});

Есть одна недостаток:оставляет функцию обратного вызова вне проверки и достигает только 94,44% покрытия.

Часть, которую я не смог проверить, была this.drawChart(this.chartData) запущена как обратный вызов google.charts.setOnLoadCallback.

Таким образом, любойпомощь в достижении упомянутого обратного вызова и достижении покрытия 100% была бы очень признательна.:)

...