0

I was trying to reload a page after a set of instructions and after a certain delay. The code works however when I test my TS file below

    import { DatePipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { NumeroModeleGabaritEnum } from '../../../../../../core/models/offre/offre-detail/document/numero-modele-gabarit-enum';
import { DocumentSommaire } from '../../../../../../core/models/offre/offre-detail/document/document-sommaire';
import { Model } from '../../../../../../core/models/offre/offre-detail/document/model';
import { ModelsRequest } from '../../../../../../core/models/offre/offre-detail/document/modelsRequest';
import { OffreDetail } from '../../../../../../core/models/offre/offre-detail/offre-detail';
import { ModeleDocumentService } from '../../../../../../core/services/modele-document.service';
import { OffreService } from '../../../../../../core/services/offre.service';
import { DocumentsSharedService } from '../../../common/documents-shared.service';
import { OffreDetailsSharedService } from '../../../common/offre-details-shared.service';


@Component({
  selector: 'app-modeles-documents',
  templateUrl: './modeles-documents.component.html',
  styleUrls: ['./modeles-documents.component.scss']
})
export class ModelesDocumentsComponent implements OnInit {
  modelesDocument: Model[];
  documentSelected: DocumentSommaire;
  documentDetail: DocumentSommaire;
  offreDetail: OffreDetail;
  dateEntenteTemps: Date;
  dateEntenteStr: string;
  afficherCalendrierDateEntente = false;
  dateEntenteAAfficher: Date;
  maxDate: Date;
  minDate: Date = new Date();
  formModel: FormGroup;
  afficherCrayonDateEntente = true;
  hasReloaded: boolean;

  constructor(
    private readonly modeleService: ModeleDocumentService,
    private readonly offreService: OffreService,
    private readonly _datePipe: DatePipe,
    private readonly documentsSharedService: DocumentsSharedService,
    private readonly offreDetailSharedService: OffreDetailsSharedService,
    private readonly fb: FormBuilder) {

  }

  ngOnInit(): void {
    this.formModel = this.fb.group({
      modelRadio: [],
      dateEntenteCalendrier: []
    });

    this.documentsSharedService.conventionDetail.subscribe(document => {
      this.documentDetail = document;
    });

    this.documentsSharedService.documentSelected.subscribe(documentSelected => {
      this.documentSelected = documentSelected;


      if (this.estConvention372(this.documentSelected?.model?.numeroFormulaire)) {
        this.afficherCrayonDateEntente = true;
      }
      else {
        this.afficherCrayonDateEntente = false;
      }

      this.offreDetailSharedService.sharedoffreDetail.subscribe(o => {
        this.offreDetail = o

        if (o) {
          this.dateEntenteAAfficher = new Date(this._datePipe.transform(this.offreDetail.dateEntente, 'yyyy-MM-dd'));
          this.dateEntenteAAfficher.setHours(this.dateEntenteAAfficher.getUTCHours());

          this.maxDate = new Date(o.dateEntente);
          this.maxDate.setFullYear(this.maxDate.getFullYear() + 1);

          this.formModel.controls.dateEntenteCalendrier.setValue(this.dateEntenteAAfficher);

          this.dateEntenteStr = this._datePipe.transform(this.dateEntenteAAfficher, "dd MMM. y");

          this.chargerModelsDocument();
        }
      });
    });

    this.formModel.controls.modelRadio.valueChanges.subscribe(value => {
      this.updateModelDocument(value);
    });
  }

  dateEntenteChange(event: any) {
    this.afficherCalendrierDateEntente = false;
    this.offreService.updateDateEntente(event.value, this.offreDetail.id).subscribe(
      () => {
        this.offreDetail.dateEntente = new Date(this._datePipe.transform(event.value, 'yyyy-MM-dd'));
        this.offreDetail.dateEntente.setHours(this.offreDetail.dateEntente.getUTCHours());
        this.offreDetailSharedService.updateOffreDetail(this.offreDetail);
      },
      err => {
        this.formModel.controls.dateEntenteCalendrier.setValue(this.dateEntenteAAfficher);
      }

    );

  }

  chargerModelsDocument() {
    if (this.offreDetail?.infosCommunes && this.documentSelected?.documentType) {

      const modelsRequest: ModelsRequest = {
        documentType: this.documentSelected.documentType,
        typeOffre: this.offreDetail.typeOffre,
        nrInst: this.offreDetail.infosCommunes.numeroInstitution,
        langue: this.offreDetail.membreClient.codeLangue.toUpperCase()
      }

      this.modeleService.getModelesDocuments(modelsRequest).subscribe(modelesDocument => {
        this.modelesDocument = modelesDocument;

        if (this.documentSelected?.model?.numeroFormulaire) {
          this.formModel.controls.modelRadio.setValue(this.documentSelected.model.numeroFormulaire);
        } else {
          this.formModel.controls.modelRadio.setValue(null);
        }
      });

    }
  }

  updateModelDocument(value: any) {
    if (value !== this.documentSelected?.model?.numeroFormulaire) {
      if (this.estConvention372(value)) {
        this.afficherCrayonDateEntente = true;
      }
      else {
        this.afficherCrayonDateEntente = false;
      }

      if (this.isConvention(this.documentSelected)) {
        this.modeleService.updateModelConvention(this.documentSelected.idOffre, this.documentSelected.id, value).subscribe(
          convention => {
           this.documentsSharedService.updateConventionDetail(convention);
            this.documentSelected.model = this.modelesDocument.find(
              m => m.numeroFormulaire === value
            );
            this.documentsSharedService.updateDocumentSelected(this.documentSelected);
            this.reloadPage();
          },
          err => {
            this.formModel.controls.modelRadio.setValue(this.documentSelected?.model?.numeroFormulaire)
          }
        );
      }

      if (this.isLettre(this.documentSelected)) {
        this.modeleService.updateModelLettre(this.documentSelected.idOffre, this.documentSelected.id, value).subscribe(
          lettre => {
          this.documentsSharedService.updateLettreDetail(lettre);
            this.documentSelected.model = this.modelesDocument.find(
              m => m.numeroFormulaire === value
            );
            this.documentsSharedService.updateDocumentSelected(this.documentSelected);
            this.reloadPage();
          },
          err => {
            this.formModel.controls.modelRadio.setValue(this.documentSelected.model.numeroFormulaire)
          }
        );
      }

    }
  }

  isConvention(documentSelected: DocumentSommaire): boolean {
    return this.estNonVideDocument(documentSelected) && documentSelected.documentType === 'CONVENTION';
  }

  estNonVideDocument(documentSelected: DocumentSommaire): boolean {
    return documentSelected !== null && documentSelected.idOffre !== null && documentSelected.id !== null;
  }

  isLettre(documentSelected: DocumentSommaire): boolean {
    return this.estNonVideDocument(documentSelected) && documentSelected.documentType === 'LETTRE';
  }

  isDisabled(model: Model) : boolean {
    if (this.documentSelected.documentType === 'CONVENTION') {
      return this.documentDetail !== null && this.documentDetail !== undefined
      && this.documentDetail?.paiementIrreguliers !== null && this.documentDetail?.paiementIrreguliers !== undefined
      && (this.documentDetail?.paiementIrreguliers?.length > 0)
      && (this.estConvention374(model.numeroFormulaire));
    }
    return false;
  }

  estConvention372(numeroFormulaire: string) : boolean {
    return (numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_372 ||
      numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_372A ||
      numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_372_CL ||
      numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_372A_CL);
  }

  estConvention374(numeroFormulaire: string) : boolean {
    return (numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_374 ||
      numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_374A);
  }

  reloadPage(){
    setTimeout(() => {
      window.location.reload();
      this.hasReloaded = true;
    }, 6000);
  }

}

Here is my test Spec.ts file :

import { DatePipe } from '@angular/common';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule, FormControl, FormGroup, FormsModule } from '@angular/forms';
import { of, Subscription, throwError } from 'rxjs';
import { CUSTOM_ELEMENTS_SCHEMA, EventEmitter } from '@angular/core';
import { ModelesDocumentsComponent } from './modeles-documents.component';
import { ModeleDocumentService } from 'src/app/core/services/modele-document.service';
import { OffreService } from 'src/app/core/services/offre.service';
import { getTranslocoModule } from 'src/app/shared/transloco/transloco-testing.module';
import { DocumentSommaire } from 'src/app/core/models/offre/offre-detail/document/document-sommaire';
import { ModelTableau } from 'src/app/core/models/offre/offre-detail/document/model-tableau';
import { DocumentsSharedService } from '../../../common/documents-shared.service';
import { OffreDetailsSharedService } from '../../../common/offre-details-shared.service';
import { NumeroModeleGabaritEnum } from 'src/app/core/models/offre/offre-detail/document/numero-modele-gabarit-enum';
import { subscribeOn } from 'rxjs/operators';
declare const require: any;

describe('ModelesDocumentsComponent', () => {
  let component: ModelesDocumentsComponent;
  let fixture: ComponentFixture<ModelesDocumentsComponent>;
  let mockModeleDocumentService: ModeleDocumentService;
  let mockOffreService: OffreService;
  let mockDocumentsSharedService: DocumentsSharedService;
  let mockOffreDetailSharedService: OffreDetailsSharedService;
  let mockDatePipe: DatePipe;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ModelesDocumentsComponent],
      imports: [
        getTranslocoModule(),
        HttpClientTestingModule,
        FormsModule,
        ReactiveFormsModule
      ],
      providers: [DatePipe, FormBuilder, ModeleDocumentService, OffreService],
      schemas: [
        CUSTOM_ELEMENTS_SCHEMA
      ]
    })
      .compileComponents();
      mockModeleDocumentService = TestBed.inject(ModeleDocumentService);
      mockOffreService = TestBed.inject(OffreService);
      mockDocumentsSharedService = TestBed.inject(DocumentsSharedService);
      mockOffreDetailSharedService = TestBed.inject(OffreDetailsSharedService);
      mockDatePipe = TestBed.inject(DatePipe);

  });

  beforeEach(() => {
    fixture = TestBed.createComponent(ModelesDocumentsComponent);
    component = fixture.componentInstance;
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.modelesDocument = require('../../../../../../../assets/mock/convention-modeles.json');
    fixture.detectChanges();
  });

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

  it('Injection service ModeleDocumentService', () => {
    expect(mockModeleDocumentService).toBeTruthy();
  });

  it('it should ngOnInit with convention différent de 372', () => {
    component.formModel = new FormGroup({
      modelRadio: new FormControl([]),
      dateEntenteCalendrier: new FormControl([])
    });
    const offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    const convention = offreDetail.documents["CONVENTION"][2];

    mockDocumentsSharedService.conventionDetailBS.next(convention);
    mockDocumentsSharedService.documentSelectedBS.next(convention);
    mockOffreDetailSharedService.offreDetailBS.next(offreDetail);

    const chargerModelsDocumentSpy = spyOn(component, "chargerModelsDocument");
    const updateModelDocumentSpy = spyOn(component, "updateModelDocument");


    component.ngOnInit();

    expect(component.documentDetail).toEqual(convention);
    expect(component.documentSelected).toEqual(convention);
    expect(component.offreDetail).toEqual(offreDetail);

    expect(component.afficherCrayonDateEntente).toBeFalse;
    expect(component.offreDetail).toBeTrue;
    expect(component.dateEntenteAAfficher).toBeTruthy;

    const date = new Date(mockDatePipe.transform(component.offreDetail.dateEntente, 'yyyy-MM-dd'));
    date.setHours(date.getUTCHours());
    expect(component.dateEntenteAAfficher).toEqual(date);

    const maxDate = new Date(component.offreDetail.dateEntente);
    maxDate.setFullYear(maxDate.getFullYear() + 1);
    expect(component.maxDate).toEqual(maxDate);

    expect(component.formModel.controls.dateEntenteCalendrier.value).toEqual(component.dateEntenteAAfficher);
    expect(component.dateEntenteStr).toEqual(mockDatePipe.transform(component.dateEntenteAAfficher, "dd MMM. y"));

    expect(chargerModelsDocumentSpy).toHaveBeenCalled();

    component.formModel.controls.modelRadio.valueChanges.subscribe(value => {
      expect(component.updateModelDocument(value)).toBeTruthy();
      expect(updateModelDocumentSpy).toHaveBeenCalledWith(value);
    });

  });

  it('it should ngOnInit with convention = 372 ; Doit tester afficherCrayonDateEntente TRUE', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_372;

    mockDocumentsSharedService.conventionDetailBS.next(component.documentDetail);
    mockDocumentsSharedService.documentSelectedBS.next(component.documentSelected);

    component.ngOnInit();


    expect(mockDocumentsSharedService.documentSelectedBS.next(component.documentSelected));
    expect(component.estConvention372(component.documentSelected.model.numeroFormulaire)).toBeTrue;
    expect(component.afficherCrayonDateEntente).toBeTrue;

  });

  it('it should chargerModelsDocument; doit reset la valeur de modelRadio', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    const modelesDocument = require('../../../../../../../assets/mock/convention-modeles.json');

    component.formModel = new FormGroup({
      modelRadio: new FormControl([]),
      dateEntenteCalendrier: new FormControl([])
    });

    const getModeleSpy = spyOn(mockModeleDocumentService, "getModelesDocuments").and.returnValue(of(modelesDocument));

    component.chargerModelsDocument();

    expect(getModeleSpy).toHaveBeenCalled();
    expect(component.modelesDocument).toEqual(modelesDocument);
    expect(component.documentSelected.model.numeroFormulaire).not.toEqual(null);
    expect(component.formModel.controls.modelRadio.value).toEqual(component.documentSelected.model.numeroFormulaire);
  });

  it('it should chargerModelsDocument; doit reset la valeur de modelRadio to NULL', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    component.documentSelected.model.numeroFormulaire = null;
    const modelesDocument = require('../../../../../../../assets/mock/convention-modeles.json');

    component.formModel = new FormGroup({
      modelRadio: new FormControl([]),
      dateEntenteCalendrier: new FormControl([])
    });

    const getModeleSpy = spyOn(mockModeleDocumentService, "getModelesDocuments").and.returnValue(of(modelesDocument));

    component.chargerModelsDocument();

    expect(getModeleSpy).toHaveBeenCalled();
    expect(component.modelesDocument).toEqual(modelesDocument);
    expect(component.formModel.controls.modelRadio.value).toEqual(null);
  });

  it('it should updateModelDocument for Convention NumeroModeleGabaritEnum.CF_01255_372', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_373;
    const convention = require('../../../../../../../assets/mock/convention.json');
    component.reloadPage = function() { };


    expect(NumeroModeleGabaritEnum.CF_01255_372).not.toEqual(component.documentSelected.model.numeroFormulaire);

    const updateModelConventionSpy = spyOn(mockModeleDocumentService, "updateModelConvention").and.returnValue(of(convention));

    component.updateModelDocument(NumeroModeleGabaritEnum.CF_01255_372);

    expect(NumeroModeleGabaritEnum.CF_01255_372).toEqual(component.documentSelected.model.numeroFormulaire);
    expect(updateModelConventionSpy).toHaveBeenCalled();
    expect(component.afficherCrayonDateEntente).toBeTrue;
    expect(component.estConvention372(component.documentSelected.model.numeroFormulaire)).toBeTrue;
    mockDocumentsSharedService.conventionDetailBS.next(convention);
    expect(component.documentSelected.model).toEqual(component.modelesDocument.find(m => m.numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_372));
    mockDocumentsSharedService.documentSelectedBS.next(component.documentSelected);

  });

  it('it should updateModelDocument for Convention with NumeroModeleGabaritEnum.CF_01255_373', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_372;
    const convention = require('../../../../../../../assets/mock/convention.json');
    component.reloadPage = function() { };



    const updateModelConventionSpy = spyOn(mockModeleDocumentService, "updateModelConvention").and.returnValue(of(convention));
    component.updateModelDocument(NumeroModeleGabaritEnum.CF_01255_373);

    expect(updateModelConventionSpy).toHaveBeenCalled();
    expect(component.afficherCrayonDateEntente).toBeFalse;
  });

  it('it should updateModelDocument for Convention with Error', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["CONVENTION"][2];
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_372;

    component.formModel = new FormGroup({
      modelRadio: new FormControl([]),
      dateEntenteCalendrier: new FormControl([])
    });

    const err = new Object();
    err['error'] = new Error();

    const updateModelConventionSpy = spyOn(mockModeleDocumentService, "updateModelConvention").and.returnValue(throwError(err));

    component.updateModelDocument(NumeroModeleGabaritEnum.CF_01255_373);

    expect(component.formModel.controls.modelRadio.value).toEqual(component.documentSelected.model.numeroFormulaire);
    expect(updateModelConventionSpy).toHaveBeenCalled();
  });

  it('it should updateModelDocument for Lettre with 473', () => {
    component.offreDetail = require('../../../../../../../assets/mock/offre-detail.json');
    component.documentSelected = component.offreDetail.documents["LETTRE"][0];
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_472;
    const lettre = require('../../../../../../../assets/mock/lettre.json');
    component.reloadPage = function() { };


    const updateModelLettreSpy = spyOn(mockModeleDocumentService, "updateModelLettre").and.returnValue(of(lettre));
    component.updateModelDocument(NumeroModeleGabaritEnum.CF_01255_473);

    expect(updateModelLettreSpy).toHaveBeenCalled();
    mockDocumentsSharedService.lettreDetailBS.next(lettre);
    expect(component.documentSelected.model).toEqual(component.modelesDocument.find(m => m.numeroFormulaire === NumeroModeleGabaritEnum.CF_01255_473));
    mockDocumentsSharedService.documentSelectedBS.next(component.documentSelected);
  });

  it('it should updateModelDocument for Lettre with Error', () => {
    component.documentSelected =  require('../../../../../../../assets/mock/lettre.json');
    component.documentSelected.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_472;

    const err = new Object();
    err['error'] = new Error();

    const updateModelLettreSpy = spyOn(mockModeleDocumentService, "updateModelLettre").and.returnValue(throwError(err));
    component.updateModelDocument(NumeroModeleGabaritEnum.CF_01255_473);

    expect(updateModelLettreSpy).toHaveBeenCalled();
  });

  it('should test if isDisabled is false', () => {
    const convention = require('../../../../../../../assets/mock/convention.json');
    component.documentSelected = convention;
    component.documentDetail = convention;

    expect(component.isDisabled(convention.model)).toBeFalse();
  });

  it('should test if isDisabled is true', () => {
    const convention = require('../../../../../../../assets/mock/convention.json');
    const paiement = new ModelTableau();
    paiement.montant = '100000.00';
    paiement.date = "2020-09-18";
    paiement.frequence = "SEMESTRIELLE";

    component.documentSelected = convention;
    component.documentDetail.paiementIrreguliers = [paiement];

    convention.model.numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_374;

    const resultat = component.isDisabled(convention.model);

    expect(component.documentDetail.paiementIrreguliers).not.toEqual(null);
    expect(component.documentDetail.paiementIrreguliers).not.toEqual(undefined);
    expect(component.documentDetail.paiementIrreguliers.length).toBeGreaterThan(0);
    expect(resultat).toBeTrue();
  });

  it('should test if estConvention374 is true', () => {
    const numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_374;
    expect(component.estConvention374(numeroFormulaire)).toBeTrue();
  });

  it('should test if estConvention374 is false', () => {
    const numeroFormulaire = NumeroModeleGabaritEnum.CF_01255_372;
    expect(component.estConvention374(numeroFormulaire)).toBeFalse();
  });

  it("should updateDateEntente()", () => {

    const dateEntenteTemps = new Date("2022-11-25T01:01:36");
    const event = new EventEmitter<Date>();
    event.emit(dateEntenteTemps);

    fixture.detectChanges();

    const subSpy = spyOn(mockOffreService, 'updateDateEntente').and.returnValue(of(true));

    component.dateEntenteChange(event);

    expect(subSpy).toHaveBeenCalled();

  });


});

As of now when I run my jasmine test it keeps reloading the page and the following test- :

it("reloadPage: should be validated", () => {spyOn(window.location, 'reload').and.callFake(() => {`
//test
});
component.reloadPage();
});

keeps giving me the error that Error: <spyOn> : reload is not declared writable or has no setter

If anyone can help because I am missing the coverage of this test

I tried using InjectionToken and

windowMock = { location: { reload: jasmine.createSpy('reload') } } with my test but it still does not pass

Futiliter
  • 3
  • 2
  • Could you post the all the component code and test code? It may be related to how you are injecting the window object in your component or in the test.. or maybe both! – g0rb Sep 09 '22 at 16:29
  • I just deleted the code but I followed this https://stackoverflow.com/questions/68607971/how-to-unit-test-window-location-reload-in-angular-12-unit-testing – Futiliter Sep 09 '22 at 16:39
  • Okay.. hard to tell whats going on without seeing all the code. It could be related to your `setTimeout` function in the component. The test should be using `tick()` to flush the timeout. – g0rb Sep 09 '22 at 16:44
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Sep 10 '22 at 10:47
  • Sorry guys I just updated my post if any of you can take a look – Futiliter Sep 12 '22 at 15:00

0 Answers0