import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpResponse } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormBuilder } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { of, Subject, from } from 'rxjs';

import { IPeriod } from 'app/entities/period/period.model';
import { PeriodService } from 'app/entities/period/service/period.service';
import { IPeriodVersion } from 'app/entities/period-version/period-version.model';
import { PeriodVersionService } from 'app/entities/period-version/service/period-version.service';
import { IOrganization } from 'app/entities/organization/organization.model';
import { OrganizationService } from 'app/entities/organization/service/organization.service';
import { IInputDataUpload } from '../input-data-upload.model';
import { InputDataUploadService } from '../service/input-data-upload.service';
import { InputDataUploadFormService } from './input-data-upload-form.service';

import { InputDataUploadUpdateComponent } from './input-data-upload-update.component';

describe('InputDataUpload Management Update Component', () => {
  let comp: InputDataUploadUpdateComponent;
  let fixture: ComponentFixture<InputDataUploadUpdateComponent>;
  let activatedRoute: ActivatedRoute;
  let inputDataUploadFormService: InputDataUploadFormService;
  let inputDataUploadService: InputDataUploadService;
  let periodService: PeriodService;
  let periodVersionService: PeriodVersionService;
  let organizationService: OrganizationService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule, InputDataUploadUpdateComponent],
      providers: [
        FormBuilder,
        {
          provide: ActivatedRoute,
          useValue: {
            params: from([{}]),
          },
        },
      ],
    })
      .overrideTemplate(InputDataUploadUpdateComponent, '')
      .compileComponents();

    fixture = TestBed.createComponent(InputDataUploadUpdateComponent);
    activatedRoute = TestBed.inject(ActivatedRoute);
    inputDataUploadFormService = TestBed.inject(InputDataUploadFormService);
    inputDataUploadService = TestBed.inject(InputDataUploadService);
    periodService = TestBed.inject(PeriodService);
    periodVersionService = TestBed.inject(PeriodVersionService);
    organizationService = TestBed.inject(OrganizationService);

    comp = fixture.componentInstance;
  });

  describe('ngOnInit', () => {
    it('Should call Period query and add missing value', () => {
      const inputDataUpload: IInputDataUpload = { id: 456 };
      const period: IPeriod = { id: 11829 };
      inputDataUpload.period = period;

      const periodCollection: IPeriod[] = [{ id: 7640 }];
      jest.spyOn(periodService, 'query').mockReturnValue(of(new HttpResponse({ body: periodCollection })));
      const additionalPeriods = [period];
      const expectedCollection: IPeriod[] = [...additionalPeriods, ...periodCollection];
      jest.spyOn(periodService, 'addPeriodToCollectionIfMissing').mockReturnValue(expectedCollection);

      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      expect(periodService.query).toHaveBeenCalled();
      expect(periodService.addPeriodToCollectionIfMissing).toHaveBeenCalledWith(
        periodCollection,
        ...additionalPeriods.map(expect.objectContaining),
      );
      expect(comp.periodsSharedCollection).toEqual(expectedCollection);
    });

    it('Should call PeriodVersion query and add missing value', () => {
      const inputDataUpload: IInputDataUpload = { id: 456 };
      const periodVersion: IPeriodVersion = { id: 26730 };
      inputDataUpload.periodVersion = periodVersion;

      const periodVersionCollection: IPeriodVersion[] = [{ id: 18123 }];
      jest.spyOn(periodVersionService, 'query').mockReturnValue(of(new HttpResponse({ body: periodVersionCollection })));
      const additionalPeriodVersions = [periodVersion];
      const expectedCollection: IPeriodVersion[] = [...additionalPeriodVersions, ...periodVersionCollection];
      jest.spyOn(periodVersionService, 'addPeriodVersionToCollectionIfMissing').mockReturnValue(expectedCollection);

      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      expect(periodVersionService.query).toHaveBeenCalled();
      expect(periodVersionService.addPeriodVersionToCollectionIfMissing).toHaveBeenCalledWith(
        periodVersionCollection,
        ...additionalPeriodVersions.map(expect.objectContaining),
      );
      expect(comp.periodVersionsSharedCollection).toEqual(expectedCollection);
    });

    it('Should call Organization query and add missing value', () => {
      const inputDataUpload: IInputDataUpload = { id: 456 };
      const owner: IOrganization = { id: 24978 };
      inputDataUpload.owner = owner;

      const organizationCollection: IOrganization[] = [{ id: 32111 }];
      jest.spyOn(organizationService, 'query').mockReturnValue(of(new HttpResponse({ body: organizationCollection })));
      const additionalOrganizations = [owner];
      const expectedCollection: IOrganization[] = [...additionalOrganizations, ...organizationCollection];
      jest.spyOn(organizationService, 'addOrganizationToCollectionIfMissing').mockReturnValue(expectedCollection);

      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      expect(organizationService.query).toHaveBeenCalled();
      expect(organizationService.addOrganizationToCollectionIfMissing).toHaveBeenCalledWith(
        organizationCollection,
        ...additionalOrganizations.map(expect.objectContaining),
      );
      expect(comp.organizationsSharedCollection).toEqual(expectedCollection);
    });

    it('Should update editForm', () => {
      const inputDataUpload: IInputDataUpload = { id: 456 };
      const period: IPeriod = { id: 3902 };
      inputDataUpload.period = period;
      const periodVersion: IPeriodVersion = { id: 7134 };
      inputDataUpload.periodVersion = periodVersion;
      const owner: IOrganization = { id: 5813 };
      inputDataUpload.owner = owner;

      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      expect(comp.periodsSharedCollection).toContain(period);
      expect(comp.periodVersionsSharedCollection).toContain(periodVersion);
      expect(comp.organizationsSharedCollection).toContain(owner);
      expect(comp.inputDataUpload).toEqual(inputDataUpload);
    });
  });

  describe('save', () => {
    it('Should call update service on save for existing entity', () => {
      // GIVEN
      const saveSubject = new Subject<HttpResponse<IInputDataUpload>>();
      const inputDataUpload = { id: 123 };
      jest.spyOn(inputDataUploadFormService, 'getInputDataUpload').mockReturnValue(inputDataUpload);
      jest.spyOn(inputDataUploadService, 'update').mockReturnValue(saveSubject);
      jest.spyOn(comp, 'previousState');
      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      // WHEN
      comp.save();
      expect(comp.isSaving).toEqual(true);
      saveSubject.next(new HttpResponse({ body: inputDataUpload }));
      saveSubject.complete();

      // THEN
      expect(inputDataUploadFormService.getInputDataUpload).toHaveBeenCalled();
      expect(comp.previousState).toHaveBeenCalled();
      expect(inputDataUploadService.update).toHaveBeenCalledWith(expect.objectContaining(inputDataUpload));
      expect(comp.isSaving).toEqual(false);
    });

    it('Should call create service on save for new entity', () => {
      // GIVEN
      const saveSubject = new Subject<HttpResponse<IInputDataUpload>>();
      const inputDataUpload = { id: 123 };
      jest.spyOn(inputDataUploadFormService, 'getInputDataUpload').mockReturnValue({ id: null });
      jest.spyOn(inputDataUploadService, 'create').mockReturnValue(saveSubject);
      jest.spyOn(comp, 'previousState');
      activatedRoute.data = of({ inputDataUpload: null });
      comp.ngOnInit();

      // WHEN
      comp.save();
      expect(comp.isSaving).toEqual(true);
      saveSubject.next(new HttpResponse({ body: inputDataUpload }));
      saveSubject.complete();

      // THEN
      expect(inputDataUploadFormService.getInputDataUpload).toHaveBeenCalled();
      expect(inputDataUploadService.create).toHaveBeenCalled();
      expect(comp.isSaving).toEqual(false);
      expect(comp.previousState).toHaveBeenCalled();
    });

    it('Should set isSaving to false on error', () => {
      // GIVEN
      const saveSubject = new Subject<HttpResponse<IInputDataUpload>>();
      const inputDataUpload = { id: 123 };
      jest.spyOn(inputDataUploadService, 'update').mockReturnValue(saveSubject);
      jest.spyOn(comp, 'previousState');
      activatedRoute.data = of({ inputDataUpload });
      comp.ngOnInit();

      // WHEN
      comp.save();
      expect(comp.isSaving).toEqual(true);
      saveSubject.error('This is an error!');

      // THEN
      expect(inputDataUploadService.update).toHaveBeenCalled();
      expect(comp.isSaving).toEqual(false);
      expect(comp.previousState).not.toHaveBeenCalled();
    });
  });

  describe('Compare relationships', () => {
    describe('comparePeriod', () => {
      it('Should forward to periodService', () => {
        const entity = { id: 123 };
        const entity2 = { id: 456 };
        jest.spyOn(periodService, 'comparePeriod');
        comp.comparePeriod(entity, entity2);
        expect(periodService.comparePeriod).toHaveBeenCalledWith(entity, entity2);
      });
    });

    describe('comparePeriodVersion', () => {
      it('Should forward to periodVersionService', () => {
        const entity = { id: 123 };
        const entity2 = { id: 456 };
        jest.spyOn(periodVersionService, 'comparePeriodVersion');
        comp.comparePeriodVersion(entity, entity2);
        expect(periodVersionService.comparePeriodVersion).toHaveBeenCalledWith(entity, entity2);
      });
    });

    describe('compareOrganization', () => {
      it('Should forward to organizationService', () => {
        const entity = { id: 123 };
        const entity2 = { id: 456 };
        jest.spyOn(organizationService, 'compareOrganization');
        comp.compareOrganization(entity, entity2);
        expect(organizationService.compareOrganization).toHaveBeenCalledWith(entity, entity2);
      });
    });
  });
});
