Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
10 kB
0
Indexable
Never
import {
  FloaterNotificationModule,
  IconContainerModule,
  CheckboxModule,
  ModalModule} from '@btgclient-web/orquestra';
import { ModalHelperService, MultiFactorAuthenticationModalComponent } from '@btgclient-web/core';
import { Component, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, ViewRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { HubService } from '@btgclient-web/shared';
import { Observable, of, throwError } from 'rxjs';
import { By } from '@angular/platform-browser';
import { FormBuilder } from '@angular/forms';
import { Location } from '@angular/common';

import { RemuneratedBalanceData, RemuneratedBalanceFilesInterface } from '../../shared/interfaces/remunerated-balance.interface';
import { RemuneratedBalanceService } from '../../shared/services/remunerated-balance.service';
import { remuneratedBalanceMock } from '../../shared/mocks/remunerated-balance.mock';
import { AutomaticIncomeComponent } from './automatic-income.component';

const AutomaticIcomeDataMock: Partial<RemuneratedBalanceData | undefined> = {
  remuneratedBalance: remuneratedBalanceMock,
  selectedAccount: {
    investmentAccount: {
      accountNumber: '123456'
    }
  }
} as RemuneratedBalanceData;

class LocationStub {
  public back(): void {}
}

class HubServiceStub {
  public dispatchEvent(eventName: string): any {
    if(eventName === 'middlaware.getSoftTokenData'){
      return 'secret';
    }

    return {};
  }
}

class ChangeDetectorRefStub implements ViewRef {
  destroy(): void { }
  get destroyed(): boolean { return false; }
  onDestroy(): void { }
  markForCheck(): void { }
  detach(): void { }
  detectChanges(): void { }
  checkNoChanges(): void { }
  reattach(): void { }
}

@Component({ selector: 'core-multi-factor-authentication-modal' })
class MultiFactorAuthModalStubComponent extends MultiFactorAuthenticationModalComponent {
  constructor() {
    super(new FormBuilder(), new ChangeDetectorRefStub());
  }
  public override open(callback: (token: string)=> Observable<any>): void {
    setTimeout(() => {
      const token = '123456';
      callback(token).subscribe();
    }, 0);
  }
}

describe('AutomaticIncomeComponent', () => {
  let component: AutomaticIncomeComponent;
  let fixture: ComponentFixture<AutomaticIncomeComponent>;
  let location: Location;
  let remuneratedBalanceService: RemuneratedBalanceService;
  let modal: ModalHelperService;

  const deepCopyData = (data: any): any => JSON.parse(JSON.stringify(data));
  const setup = async (dataMock: RemuneratedBalanceData | null): Promise<void> => {
    await TestBed.configureTestingModule({
      declarations: [
        AutomaticIncomeComponent,
        MultiFactorAuthModalStubComponent
      ],
      imports: [
        CheckboxModule,
        IconContainerModule,
        FloaterNotificationModule,
        ModalModule
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
      providers: [
        provideMockStore({}),
        {
          provide: Location,
          useClass: LocationStub,
        },
        {
          provide: HubService,
          useClass: HubServiceStub,
        }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(AutomaticIncomeComponent);
    location = TestBed.inject(Location);
    TestBed.inject(MockStore);
    modal = TestBed.inject(ModalHelperService);
    remuneratedBalanceService = TestBed.inject(RemuneratedBalanceService);
    component = fixture.componentInstance;
    component.loading = false;
    component.loadFailed = false;
    component.automaticIncomeData = dataMock;
    component.ngOnChanges({
      loading: {
        currentValue: false,
        previousValue: false,
        isFirstChange: () => false,
        firstChange: false
      }
    });
  };

  it('should create', async () => {
    await setup(AutomaticIcomeDataMock as RemuneratedBalanceData);
    fixture.detectChanges();
    expect(component).toBeTruthy();
  });

  it('should prevent error when create without data', async () => {
    await setup(null);
    fixture.detectChanges();
    expect(component).toBeTruthy();
  });

  it('should show error modal when not ready to load terms', async () => {
    await setup(null);
    const spyModalOpen = spyOn(modal, 'showModal');

    //@ts-expect-error
    component.onPrimaryButtonClick();
    fixture.detectChanges();
    expect(spyModalOpen).not.toHaveBeenCalled();

    component.termsLoadFn = (): Observable<never> => throwError(() => '');

    //@ts-expect-error
    component.onPrimaryButtonClick();
    fixture.detectChanges();
    expect(spyModalOpen).toHaveBeenCalled();
  });

  it('should prevent twice download terms', async () => {
    await setup(AutomaticIcomeDataMock as RemuneratedBalanceData);
    component.termsLoadFn = (): Observable<RemuneratedBalanceFilesInterface[]> => of([
      {
        name: 'mock-file.pdf',
        id: 123456
      } as RemuneratedBalanceFilesInterface
    ]);
    spyOn(remuneratedBalanceService, 'downloadFile').and.returnValue(throwError(() => ''));
    const spyModalOpen = spyOn(modal, 'showModal');
    const mockFile = { id: 123456, name: 'mock-filename.pdf' };
    //@ts-expect-error
    component.filesDownloading[mockFile.id] = true;
    //@ts-expect-error
    component.downloadFile('123456', mockFile);

    //@ts-expect-error
    component.filesDownloading[mockFile.id] = false;
    //@ts-expect-error
    component.downloadFile('123456', mockFile);

    fixture.detectChanges();
    expect(spyModalOpen).toHaveBeenCalled();
  });

  it('should be able to come back navigation', async () => {
    await setup(AutomaticIcomeDataMock as RemuneratedBalanceData);
    fixture.detectChanges();
    const spy = spyOn(location, 'back');
    const primaryButtonRef = fixture.debugElement.query(By.css('[data-testid="back-button"]'));
    primaryButtonRef.triggerEventHandler('click');
    expect(spy).toHaveBeenCalled();
  });

  it('should be able to enable automatic income', (done: DoneFn) => {
    const deepCopyMock = deepCopyData(remuneratedBalanceMock) ;
    deepCopyMock.remuneratedBalanceEnabled = false;
    setup(deepCopyMock).then(() => {
      component.termsLoadFn = (): Observable<RemuneratedBalanceFilesInterface[]> => of([
        {
          name: 'mock-file.pdf',
          id: 123456
        } as RemuneratedBalanceFilesInterface
      ]);
      spyOn(remuneratedBalanceService, 'downloadFile').and.returnValue(of(new ArrayBuffer(1)));
      fixture.detectChanges();

      spyOn(component.multiFactorAuthModal, 'open').and.callThrough();
      spyOn(remuneratedBalanceService, 'enable').and.returnValue(of({ success: true }));

      const spyOpenModal = spyOn<any>(component, 'showModal').and.callThrough();
      const spyCloseModal = spyOn<any>(component, 'closeModal').and.callThrough();

      // primary button
      const primaryButtonRef = fixture.debugElement.query(By.css('[data-testid="primary-button"]'));
      expect(primaryButtonRef.nativeElement.innerText).toContain('Ativar');
      primaryButtonRef.triggerEventHandler('click');
      fixture.detectChanges();
      expect(spyOpenModal).toHaveBeenCalled();

      //@ts-expect-error
      component.termsModalConfig.modalActions.primary!.callback();
      fixture.detectChanges();

      // modal not close because need to accept terms
      const modalRef = fixture.debugElement.query(By.css('[data-testid="modal-terms"]'));
      expect(modalRef.componentInstance.visible).toBeTrue();

      // download terms document
      const createElement = document.createElement;
      spyOn(document, 'createElement').and.callFake((tag: string) => {
        const mockLink = createElement.call(document, tag);
        spyOn(mockLink, 'click');
        return mockLink;
      });
      const downloadButtonRef = modalRef.query(By.css('[data-testid="terms-download-button"]'));
      downloadButtonRef.triggerEventHandler('$click');
      fixture.detectChanges();

      //@ts-expect-error
      component.termsForm.get('acceptTerms')?.setValue(true);
      //@ts-expect-error
      component.onAcceptTermsChange();
      //@ts-expect-error
      component.termsModalConfig.modalActions.primary!.callback();
      fixture.detectChanges();
      expect(modalRef.componentInstance.visible).toBeFalse(); // modal close after accept terms
      expect(spyCloseModal).toHaveBeenCalled();

      setTimeout(()=> {
        done();
      }, 0);
    });
  });

  it('should be able to disable automatic income', (done) => {
    const deepCopyMock = deepCopyData(remuneratedBalanceMock) ;
    deepCopyMock.remuneratedBalanceEnabled = true;
    // deepCopyMock.accountDetails.hasServiceEnabled = 'ENABLED';
    setup(deepCopyMock).then(() => {
      fixture.detectChanges();

      spyOn(component.multiFactorAuthModal, 'open').and.callThrough();
      spyOn(remuneratedBalanceService, 'disable').and.returnValue(of({ success: true }));

      const spyOpenModal = spyOn<any>(component, 'showModal').and.callThrough();
      const spyCloseModal = spyOn<any>(component, 'closeModal').and.callThrough();

      // primary button
      const primaryButtonRef = fixture.debugElement.query(By.css('[data-testid="primary-button"]'));
      expect(primaryButtonRef.nativeElement.innerText).toContain('Cancelar');
      primaryButtonRef.triggerEventHandler('click');
      fixture.detectChanges();
      expect(spyOpenModal).toHaveBeenCalled();

      const modalRef = fixture.debugElement.query(
        By.css('[data-testid="modal-confirm-automatic-icome"]')
      );
      expect(modalRef.componentInstance.visible).toBeTrue();

      //@ts-expect-error
      component.confimAutomaticIcomeModalConfig.modalActions.primary!.callback();
      fixture.detectChanges();
      expect(modalRef.componentInstance.visible).toBeFalse();
      expect(spyCloseModal).toHaveBeenCalled();

      setTimeout(()=> {
        done();
      }, 0);
    });
  });
});