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

import {ProductComponent} from './product.component';
import {Component, ViewChild} from "@angular/core";
import {Product, ProductPreRequisites, ProductVersion} from "../../model/product";
import {ProductsService} from "../../services/products.service";
import {JobsService} from "../../services/jobs.service";
import {ReactiveFormsModule} from "@angular/forms";
import {of} from "rxjs";
import {By} from "@angular/platform-browser";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";

// mock a host container
@Component({
  template: '<app-product [product]="product" [type]="type" [queues]="queues"></app-product>'
})

class HostComponent {
  product: Product = {
    category: "CALIBRATION",
    completed: false,
    configurations: [],
    epoch: 1,
    epochHalf: 2,
    extraInfoForJobName: "",
    fileNames: ["PPR.xml"],
    id: 18469,
    latestProductVersion: {present: true},
    minitiles: [],
    name: "ProductName",
    notes: null,
    preRequisites: [{
      archiveIds: {},
      id: 345,
      name: 'preReq',
      ready: true,
      requiredProduct: {
        category: "CALIBRATION",
        completed: false,
        configurations: [],
        epoch: 1,
        epochHalf: 2,
        extraInfoForJobName: "",
        fileNames: ["PPR.xml"],
        id: 987654,
        latestProductVersion: {present: true},
        minitiles: [],
        name: "ProductName2",
        notes: null,
        preRequisites: [],
        status: "READY",
        tags: [],
        typeId: 1,
        typeName: "calibration",
        phaseCenterRA: '1.23456789',
        phaseCenterDec: '1.23456789',
        imageSizeX: '1.23456789',
        imageSizeY: '1.23456789',
        fluxCalibrators: [],
        fluxPosition: '',
        lstEnd: null,
        lstStart: null,
        optId: 321,
        phaseCalibrators: [],
        polCalibrators: [],
        submitted: '',
        versions: [{
          archiveIds: {},
          configurations: [],
          id: 456,
          jobSpecifications: {},
          notes: '',
          productEpoch: 1,
          productId: 852,
          productName: 'ProductName3',
          productType: 1,
          status: 'READY',
          versionNumber: 1
        } as ProductVersion, {
          archiveIds: {},
          configurations: [],
          id: 753,
          jobSpecifications: {},
          notes: '',
          productEpoch: 1,
          productId: 951,
          productName: 'ProductName4',
          productType: 1,
          status: 'READY',
          versionNumber: 2
        } as ProductVersion]
      } as Product
    } as ProductPreRequisites
    ],
    status: "COMPLETED",
    tags: [],
    typeId: 1,
    typeName: "calibration",
    phaseCenterRA: '1.23456789',
    phaseCenterDec: '1.23456789',
    imageSizeX: '1.23456789',
    imageSizeY: '1.23456789',
    fluxCalibrators: [],
    fluxPosition: '',
    lstEnd: null,
    lstStart: null,
    optId: 123,
    phaseCalibrators: [],
    polCalibrators: [],
    submitted: '',
    versions: []
  };
  type: number = 1;

  queues: Array<any> = ["calibration", "compression"];

  @ViewChild(ProductComponent, /* TODO: add static flag */ {})
  productComponent
    :
    ProductComponent;
}

describe('ProductComponent', () => {
  let component: HostComponent;
  let fixture: ComponentFixture<HostComponent>;
  let productServiceSpy: { getProductTypeConfig: jasmine.Spy, getProductConfig: jasmine.Spy, updateProductStatus: jasmine.Spy };
  let jobServiceSpy: { createJob: jasmine.Spy };

  beforeEach(async(() => {
    productServiceSpy = jasmine.createSpyObj('ProductService', ['getProductTypeConfig', 'getProductConfig', 'updateProductStatus']);
    jobServiceSpy = jasmine.createSpyObj('JobService', ['createJob']);
    TestBed.configureTestingModule({
      declarations: [HostComponent, ProductComponent],
      providers: [
        {provide: ProductsService, useValue: productServiceSpy},
        {provide: JobsService, useValue: jobServiceSpy}
      ],
      imports: [ReactiveFormsModule, BrowserAnimationsModule]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(HostComponent);
    component = fixture.componentInstance;
    productServiceSpy = TestBed.get(ProductsService);
    jobServiceSpy = TestBed.get(JobsService);
  });

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

  it('getName() should return the product name', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getName()).toEqual('ProductName', 'returns product.name');
    component.productComponent.product.typeName = 'schedblock';
    expect(component.productComponent.getName()).toEqual('ProductName (123)', 'returns product.name + product.optId');
  });

  it('getStatusBadgeClass() should return the correct class by product.status', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getStatusBadgeClass()).toEqual('badge-success', 'badge-success returned for COMPLETED status');
    component.productComponent.product.status = 'READY';
    expect(component.productComponent.getStatusBadgeClass()).toEqual('badge-info', 'badge-info returned for READY status');
    component.productComponent.product.status = 'PROCESSING';
    expect(component.productComponent.getStatusBadgeClass()).toEqual('badge-light', 'badge-light returned for other statuses');
  });

  it('showImageDetails() should return true for image types', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.showImageDetails()).toBeFalsy('returns false for non-image type');
    component.productComponent.product.typeName = 'quicklook';
    expect(component.productComponent.showImageDetails()).toBeTruthy('returns true for image type');
  });

  it('getPhaseCenterRA() should return a string version of the number with a set precision', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getPhaseCenterRA()).toEqual('1.2346');
  });

  it('getPhaseCenterDec() should return a string version of the number with a set precision', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getPhaseCenterDec()).toEqual('1.2346');
  });

  it('getImageSizeX() should return a string version of the number with a set precision', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getImageSizeX()).toEqual('1.2346');
  });

  it('getImageSizeY() should return a string version of the number with a set precision', () => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.getImageSizeY()).toEqual('1.2346');
  });

  it('showDetails() should call the productService to get details and toggle the detailsExposed value', fakeAsync(() => {
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.detailsExposed).toBeFalsy('detailsExposed starts false');
    component.productComponent.showDetails();
    expect(productServiceSpy.getProductTypeConfig).toHaveBeenCalledTimes(1);
    expect(productServiceSpy.getProductConfig).toHaveBeenCalledTimes(2);
    expect(component.productComponent.detailsExposed).toBeTruthy('detailsExposed set to true');
  }));

  it('hideDetails() should toggle the detailsExposed value', () => {
    component.productComponent.detailsExposed = true;
    fixture.detectChanges(); //ngOnInit
    component.productComponent.hideDetails();
    expect(component.productComponent.detailsExposed).toBeFalsy('detailsExposed set to false');
  });

  it('updateStatus() should call product service and update the product status', fakeAsync(() => {
    let newStatus = 'PROCESSING';
    productServiceSpy.updateProductStatus.and.returnValue(of(newStatus));
    fixture.detectChanges(); //ngOnInit
    expect(component.productComponent.formGroup.get('status').value).toEqual(component.productComponent.product.status, 'form control holds products status');
    component.productComponent.updateStatus();
    expect(productServiceSpy.updateProductStatus).toHaveBeenCalledTimes(0);
    component.productComponent.formGroup.get('status').setValue(newStatus);
    component.productComponent.updateStatus();
    expect(productServiceSpy.updateProductStatus).toHaveBeenCalledTimes(1);
    expect(component.productComponent.formGroup.get('status').value).toEqual(component.productComponent.product.status, 'form control holds products status');
  }));

  it('createJob() should call the job service with the right parameters', fakeAsync(() => {
    jobServiceSpy.createJob.and.returnValue(of('Response'));
    fixture.detectChanges(); // ngOnInit
    expect(component.productComponent.jobFormGroup.get('queue').value).toEqual(component.productComponent.queues[0], 'jobForm queue starts with first queue value');
    component.productComponent.createJob();
    expect(jobServiceSpy.createJob).toHaveBeenCalledWith(component.productComponent.product.id, component.productComponent.queues[0], 1);
  }));

  it('the more button should call showDetails()', fakeAsync(() => {
    let showDetailSpy = spyOn(component.productComponent, 'showDetails');
    fixture.detectChanges(); // ngOnInit
    let moreButton: HTMLButtonElement = fixture.debugElement.query(By.css('.more_button')).nativeElement;
    moreButton.click();
    fixture.detectChanges();
    expect(showDetailSpy).toHaveBeenCalledTimes(1);

  }));

  it('the less button should call hideDetails()', fakeAsync(() => {
    component.productComponent.detailsExposed = true;
    let hideDetailSpy = spyOn(component.productComponent, 'hideDetails');
    fixture.detectChanges(); // ngOnInit
    let lessButton: HTMLButtonElement = fixture.debugElement.query(By.css('.less_button')).nativeElement;
    lessButton.click();
    fixture.detectChanges();
    expect(hideDetailSpy).toHaveBeenCalled();
  }));

  it('the change status form should call updateStatus()', () => {
    component.productComponent.detailsExposed = true;
    let updateStatusSpy = spyOn(component.productComponent, 'updateStatus');
    fixture.detectChanges(); //ngOnInit
    let submitButton: HTMLButtonElement = fixture.debugElement.query(By.css('.status_change_btn')).nativeElement;
    submitButton.click();
    expect(updateStatusSpy).toHaveBeenCalled();
  });

  it('the create job button should call createJob()', () => {
    component.productComponent.detailsExposed = true;
    component.productComponent.showProductForm = true;
    component.product.status = 'READY';
    let createJobSpy = spyOn(component.productComponent, 'createJob');
    fixture.detectChanges(); //ngOnInit
    let createJobButton: HTMLButtonElement = fixture.debugElement.query(By.css('.create_job_btn')).nativeElement;
    createJobButton.click();
    expect(createJobSpy).toHaveBeenCalled();
  });

});