Skip to content
Snippets Groups Projects
products.component.spec.ts 15 KiB
Newer Older
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';

import {ProductsComponent} from './products.component';
import {Component, DebugElement, Input} from "@angular/core";
import {Product} from "../model/product";
import {ProductsService} from "../services/products.service";
import {ReactiveFormsModule} from "@angular/forms";
import {ActivatedRoute, convertToParamMap, ParamMap, Params} from "@angular/router";
import {of, ReplaySubject} from "rxjs";
import {By} from "@angular/platform-browser";

// mock the child component
@Component({
  selector: 'app-product',
  template: '<p>Mock child component</p>'
})
class MockChildComponent {
  @Input() product: Product;
  @Input() type: number;
  @Input() queues: Array<any>;
}

// mock the ActivatedRoute
class MockActivatedRoute {

  private paramsSubject = new ReplaySubject<Params>();
  private paramMapSubject = new ReplaySubject<ParamMap>();
  private queryParamsSubject = new ReplaySubject<Params>();
  private queryParamMapSubject = new ReplaySubject<ParamMap>();

  readonly params = this.paramsSubject.asObservable();
  readonly paramMap = this.paramMapSubject.asObservable();
  readonly queryParams = this.queryParamsSubject.asObservable();
  readonly queryParamMap = this.queryParamMapSubject.asObservable();

  setParams(params: Params) {
    this.paramsSubject.next(params);
    this.paramMapSubject.next(convertToParamMap(params));
  }

  setQueryParams(params: Params) {
    this.queryParamsSubject.next(params);
    this.queryParamMapSubject.next(convertToParamMap(params));
  }

}

describe('ProductsComponent', () => {
  let component: ProductsComponent;
  let fixture: ComponentFixture<ProductsComponent>;
  let productsServiceSpy: {
    getRecordCount: jasmine.Spy,
    getPage: jasmine.Spy,
    getPageInfo: jasmine.Spy,
    getProductById: jasmine.Spy
  };
  let mockActivatedRoute: MockActivatedRoute;

  beforeEach(async(() => {
    productsServiceSpy = jasmine.createSpyObj(
      'ProductsService',
      ['getRecordCount', 'getPage', 'getPageInfo', 'getProductById']
    );

    TestBed.configureTestingModule({
      declarations: [ProductsComponent, MockChildComponent],
      providers: [
        {provide: ProductsService, useValue: productsServiceSpy},
        {provide: ActivatedRoute, useValue: new MockActivatedRoute()}
      ],
      imports: [ReactiveFormsModule]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ProductsComponent);
    component = fixture.componentInstance;
    productsServiceSpy = TestBed.get(ProductsService);
    mockActivatedRoute = TestBed.get(ActivatedRoute);

    productsServiceSpy.getRecordCount.and.returnValue(of(123));
    productsServiceSpy.getPage.and.returnValue(of([]));
    productsServiceSpy.getPageInfo.and.returnValue(of([]));
    productsServiceSpy.getProductById.and.returnValue(of({}));
  });

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

  it('should call getPageInfoAndProduct() on Init', fakeAsync(() => {
    let pageInfoProductSpy = spyOn(component, 'getPageInfoAndProduct');
    fixture.detectChanges(); // ngInit
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(1);
  }));

  it('should set pattern when pattern query parameter exists', fakeAsync(() => {
    mockActivatedRoute.setQueryParams({pattern: 'T01'});

    expect(component.pattern).toEqual('', 'pattern starts empty');
    fixture.detectChanges(); // ngInit
    expect(component.pattern).toEqual('T01', 'pattern set from query param');
    expect(productsServiceSpy.getRecordCount).toHaveBeenCalledWith(1, 1, 'T01');
  }));

  it('should set epoch when epoch query parameter exists', fakeAsync(() => {
    mockActivatedRoute.setQueryParams({epoch: -1});

    expect(component.epoch).toEqual(1, 'epoch starts at 1');
    fixture.detectChanges(); // ngInit
    expect(component.epoch).toEqual(-1, 'epoch set from query param');
    expect(productsServiceSpy.getRecordCount).toHaveBeenCalledWith(-1, 1, '');
  }));

  it('should set type when type query parameter exists', fakeAsync(() => {
    mockActivatedRoute.setQueryParams({type: 'schedblock'});

    expect(component.type).toEqual('calibration', 'type starts with calibration');
    fixture.detectChanges(); // ngInit
    expect(component.type).toEqual('schedblock', 'type set from query param');
    expect(productsServiceSpy.getRecordCount).toHaveBeenCalledWith(1, 11, '');
  }));

  it('should update pattern and call getPageInfoAndProduct() with pattern formcontrol changes', fakeAsync(() => {
    let pattern_inputDe: DebugElement = fixture.debugElement.query(By.css('#pattern'));
    let pattern_inputEl: HTMLInputElement = pattern_inputDe.nativeElement;

    let pageInfoProductSpy = spyOn(component, 'getPageInfoAndProduct');

    expect(component.pattern).toEqual('', 'pattern starts empty');
    fixture.detectChanges(); // ngInit
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(1);
    expect(pattern_inputEl.value).toEqual('', 'pattern control is null');

    pattern_inputEl.value = 'T01';
    pattern_inputEl.dispatchEvent(new Event('input'));
    tick(500); // for the debounce
    fixture.detectChanges();
    expect(component.pattern).toEqual('T01', 'input updated pattern');
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(2);
  }));

  it('should update epoch and call getPageInfoAndProduct() with drop down selection', fakeAsync(() => {
    let dropdownButtonDe: DebugElement = fixture.debugElement.query(By.css('#epoch-select'));
    let dropdownButtonEl: HTMLButtonElement = dropdownButtonDe.nativeElement;
    let changeEpochButtonDe: DebugElement = fixture.debugElement.query(By.css('#epoch-select-list li button'));
    let changeEpochButtonEl: HTMLButtonElement = changeEpochButtonDe.nativeElement;

    let pageInfoProductSpy = spyOn(component, 'getPageInfoAndProduct');

    expect(component.epoch).toEqual(1, 'epoch default value');
    fixture.detectChanges(); // ngInit();
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(1);
    expect(dropdownButtonEl.textContent).toEqual('Epoch: Epoch 1', 'UI button default text');

    changeEpochButtonEl.click();
    fixture.detectChanges();

    expect(component.epoch).toEqual(-1, 'update epoch value');
    expect(dropdownButtonEl.textContent).toEqual('Epoch: Tests', 'UI button text updated');
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(2);
  }));

  it('should update type and call getPageInfoAndProduct() with drop down selection', fakeAsync(() => {
    let dropdownButtonDe: DebugElement = fixture.debugElement.query(By.css('#type-select'));
    let dropdownButtonEl: HTMLButtonElement = dropdownButtonDe.nativeElement;
    let changeTypeButtonDe: DebugElement = fixture.debugElement.query(By.css('#type-select-list li button'));
    let changeTypeButtonEl: HTMLButtonElement = changeTypeButtonDe.nativeElement;

    let pageInfoProductSpy = spyOn(component, 'getPageInfoAndProduct');

    expect(component.type).toEqual('calibration', 'epoch default value');
    fixture.detectChanges(); // ngInit();
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(1);
    expect(dropdownButtonEl.textContent).toEqual('Type: calibration', 'UI button default text');

    changeTypeButtonEl.click();
    fixture.detectChanges();

    expect(component.type).toEqual('schedblock', 'update epoch value');
    expect(dropdownButtonEl.textContent).toEqual('Type: schedblock', 'UI button text updated');
    expect(pageInfoProductSpy).toHaveBeenCalledTimes(2);
  }));

  it('getEpochName() should translate numbers to names', () => {
    expect(component.getEpochName(-1)).toEqual('Tests');
    expect(component.getEpochName(0)).toEqual('Pilot');
    expect(component.getEpochName(1)).toEqual('Epoch 1');
  });

  it('getTypeId() should translate names to numbers and toggle value for showImageDetails', () => {
    expect(component.showImageDetails).toBeFalsy('showImageDetails starts false');

    expect(component.getTypeId('schedblock')).toEqual(11);
    expect(component.showImageDetails).toBeFalsy('showImageDetails is false for schedblock');

    expect(component.getTypeId('calibration')).toEqual(1);
    expect(component.showImageDetails).toBeFalsy('showImageDetails is false for calibration');

    expect(component.getTypeId('quicklook')).toEqual(4);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for quicklook');

    expect(component.getTypeId('image')).toEqual(1);
    expect(component.showImageDetails).toBeFalsy('showImageDetails is false for image');

    expect(component.getTypeId('cube')).toEqual(2);
    expect(component.showImageDetails).toBeFalsy('showImageDetails is false for cube');

    expect(component.getTypeId('se_calibration')).toEqual(14);
    expect(component.showImageDetails).toBeFalsy('showImageDetails is false for se_calibration');

    expect(component.getTypeId('se_cont')).toEqual(17);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for se_cont');

    expect(component.getTypeId('se_coarse_cube_image')).toEqual(18);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for _cube_image');

    expect(component.getTypeId('se_coarse_plane_image')).toEqual(19);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for se_coarse_plane_image');

    expect(component.getTypeId('se_coarse_plane_I_image')).toEqual(22);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for se_coarse_plane_I_image');

    expect(component.getTypeId('se_coarse_plane_Q_image')).toEqual(23);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for se_coarse_plane_Q_image');

    expect(component.getTypeId('se_coarse_plane_U_image')).toEqual(24);
    expect(component.showImageDetails).toBeTruthy('showImageDetails is true for se_coarse_plane_U_image');

  });

  it('goToPage() should detect edges, set page paramenter and call getProducts()', () => {
    let getProductsSpy = spyOn(component, "getProducts");
    getProductsSpy.and.returnValue('');

    component.currentPage = 1;
    component.pages = 5;

    expect(component.goToPage(1)).toBeFalsy('return false for request to go to current page');
    expect(getProductsSpy).toHaveBeenCalledTimes(0);
    component.goToPage(6);
    expect(component.currentPage).toEqual(5, 'send to last page if requested to go to a page beyond it');
    expect(getProductsSpy).toHaveBeenCalledTimes(1);
    component.goToPage(3);
    expect(component.currentPage).toEqual(3, 'set current page');
    expect(getProductsSpy).toHaveBeenCalledTimes(2);
  });

  it('getPages() should return an sequential array of integers the size of pages', () => {
    component.pages = 5;
    expect(component.getPages().length).toEqual(5, 'returns array for pages');
  });

  it('getProducts() should set products from service and call getPageInfo()', fakeAsync(() => {
    let expectedPageResult = [{
      category: "CALIBRATION",
      completed: false,
      configurations: [],
      epoch: 1,
      epochHalf: 2,
      extraInfoForJobName: "T13t02.T13t08.T12t08",
      fileNames: ["PPR.xml"],
      id: 18469,
      latestProductVersion: {present: true},
      minitiles: [],
      name: "T13t02.T13t08.T12t08",
      notes: null,
      preRequisites: [],
      status: "COMPLETED",
      tags: [],
      typeId: 1,
      typeName: "calibration",
      versions: []
    } as Product];
    productsServiceSpy.getPage.and.returnValue(of(expectedPageResult));

    let getPageInfoSpy = spyOn(component, "getPageInfo");

    expect(component.products).toEqual([], 'start with empty products array');
    expect(component.queues).toEqual([], 'start with empty queues array');

    component.getProducts(1);
    tick();
    expect(component.products).toEqual(expectedPageResult, 'set products from service results');
    expect(productsServiceSpy.getPage).toHaveBeenCalledTimes(1);
    expect(getPageInfoSpy).toHaveBeenCalledTimes(1);

  }));

  it('getPageInfo()  should call a service and set the queues', fakeAsync(() => {

    let expectedPageInfoResult = ["calibration", "compression"];
    productsServiceSpy.getPageInfo.and.returnValue(of(expectedPageInfoResult));

    expect(component.products).toEqual([], 'start with empty products array');
    expect(component.queues).toEqual([], 'start with empty queues array');

    component.getPageInfo();
    tick();
    expect(productsServiceSpy.getPageInfo).toHaveBeenCalledTimes(1);
    expect(component.queues).toEqual(expectedPageInfoResult, 'set queues from product service');

  }));

  it('getProductById() should call a service, and set products, numResults, pages, and current page', fakeAsync(() => {
    let expectedProductResult = {
      category: "CALIBRATION",
      completed: false,
      configurations: [],
      epoch: 1,
      epochHalf: 2,
      extraInfoForJobName: "T13t02.T13t08.T12t08",
      fileNames: ["PPR.xml"],
      id: 18469,
      latestProductVersion: {present: true},
      minitiles: [],
      name: "T13t02.T13t08.T12t08",
      notes: null,
      preRequisites: [],
      status: "COMPLETED",
      tags: [],
      typeId: 1,
      typeName: "calibration",
      versions: []
    } as Product;
    productsServiceSpy.getProductById.and.returnValue(of(expectedProductResult));

    expect(component.products).toEqual([], 'products start empty');
    expect(component.numResults).toEqual(0, 'numResults start empty');
    expect(component.pages).toEqual(1, 'pages start at 1');
    expect(component.currentPage).toEqual(1, 'currentPage start at 1');

    // just to check to make sure the changes occur
    component.pages = 0;
    component.currentPage = 0;

    component.getProductById('123');
    tick();
    expect(productsServiceSpy.getProductById).toHaveBeenCalledWith('123');
    expect(component.products).toEqual([expectedProductResult], 'products set with service');
    expect(component.numResults).toEqual(1, 'numResults set to 1');
    expect(component.pages).toEqual(1, 'pages set to 1');
    expect(component.currentPage).toEqual(1, 'currentPage set to 1');
  }));

  it('getPageInfoAndProdct() should determin which retreival functions to call', fakeAsync(() => {
    let getPageCountSpy = spyOn(component, "getPageCount");
    let getProductsSpy = spyOn(component, "getProducts");
    let getProductByIdSpy = spyOn(component, "getProductById");
    let getPageInfoSpy = spyOn(component, "getPageInfo");

    component.pattern = '';
    component.getPageInfoAndProduct();
    expect(getPageCountSpy).toHaveBeenCalledTimes(1);
    expect(getProductsSpy).toHaveBeenCalledTimes(1);
    expect(getProductByIdSpy).toHaveBeenCalledTimes(0);
    expect(getPageInfoSpy).toHaveBeenCalledTimes(1);

    component.pattern = 'ABC';
    component.getPageInfoAndProduct();
    expect(getPageCountSpy).toHaveBeenCalledTimes(2);
    expect(getProductsSpy).toHaveBeenCalledTimes(2);
    expect(getProductByIdSpy).toHaveBeenCalledTimes(0);
    expect(getPageInfoSpy).toHaveBeenCalledTimes(2);

    component.pattern = '123';
    component.getPageInfoAndProduct();
    expect(getPageCountSpy).toHaveBeenCalledTimes(2);
    expect(getProductsSpy).toHaveBeenCalledTimes(2);
    expect(getProductByIdSpy).toHaveBeenCalledTimes(1);
    expect(getPageInfoSpy).toHaveBeenCalledTimes(3);
  }));

});