import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { CreditApplicationDaoService } from '../shared/credit-application-dao.service'; import { ApplicationWizardService } from './application-wizard.service'; import { MaskingService } from '../shared/masking/masking.service'; import { MemberInfoFormComponent } from './field-groups/member/member-info-form.component'; import { TextMaskModule } from 'angular2-text-mask'; import { MemberInfoPageService } from './wizards/common/member/member-info-page.service'; import { CommonGroups } from './field-groups/common-groups'; import { LoanTypeSet } from '../shared/loan-type'; import { of } from 'rxjs'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { CreditApplicationValues } from '../shared/credit-application-values'; import { TranslateModule } from '@ngx-translate/core'; import { BorrowerType } from '../shared/borrower-type'; import { apiTranslatorPreTranslate } from '../testing/shared-mocks/api-translator-pre-post'; import { EquityMemberInfoPageService } from './wizards/equity/equity-member-info-page.service'; import { configureTestSuite } from 'ng-bullet'; import { CreditApplicationService } from '../shared/credit-application.service'; const createTestFormGroup = (formBuilder: FormBuilder): FormGroup => { const group = formBuilder.group({}); CommonGroups.MEMBER_INFO.fields.forEach((eachField) => { group.addControl(eachField.field, formBuilder.control('', eachField.validation.slice())); }, this); return group; }; describe('ApplicationWizardService', () => { let applicationWizardService: ApplicationWizardService; let creditApplicationDaoService: CreditApplicationDaoService; let creditApplicationService: CreditApplicationService; let component: MemberInfoFormComponent; let fixture: ComponentFixture; let memberInfoPageService: MemberInfoPageService; let equityMemberInfoPageService: EquityMemberInfoPageService; let formBuilder: FormBuilder; configureTestSuite(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule, NgbModule.forRoot(), ReactiveFormsModule, TextMaskModule, HttpClientTestingModule, TranslateModule.forRoot() ], declarations: [ MemberInfoFormComponent ], schemas: [NO_ERRORS_SCHEMA], providers: [] }); }); beforeEach(() => { formBuilder = TestBed.get(FormBuilder); applicationWizardService = TestBed.get(ApplicationWizardService); applicationWizardService.setLoanType(LoanTypeSet[0].id); creditApplicationDaoService = TestBed.get(CreditApplicationDaoService); creditApplicationService = TestBed.get(CreditApplicationService); memberInfoPageService = TestBed.get(MemberInfoPageService); equityMemberInfoPageService = TestBed.get(EquityMemberInfoPageService); fixture = TestBed.createComponent(MemberInfoFormComponent); component = fixture.componentInstance; component.group = createTestFormGroup(formBuilder); }); it('should create', () => { expect(applicationWizardService).toBeTruthy(); }); it('should determine whether or not a page can be visited', () => { const canVisitStep1: boolean = applicationWizardService.canVisitPage('step-1'); const canVisitStep2: boolean = applicationWizardService.canVisitPage('step-2'); expect(canVisitStep1).toBe(true); expect(canVisitStep2).toBe(false); }); it('should determine a page can be visited because there were no errors', () => { spyOn(applicationWizardService, 'getFieldErrors').and.callThrough().and.returnValue([]); const noErrors: boolean = applicationWizardService.canVisitPage('step-2'); expect(noErrors).toBe(true); }); it('should determine if there is a co-applicant', () => { spyOn(MaskingService, 'unMaskNumber').and.callThrough().and.returnValue(1000); spyOn(applicationWizardService, 'getFieldValue').and.callThrough(); spyOn(memberInfoPageService, 'createMemberInformationGroup').and.callThrough(); spyOn(creditApplicationService, 'saveCreditApplication').and.returnValue(of(true)); component.group.patchValue({ 'applicantType': CreditApplicationValues.CHOICE_YES, 'limitRequested': '1000', 'maritalStatus': CreditApplicationValues.CHOICE_NO }); creditApplicationService.saveMemberInformation(component.group.value); const isCoApplicant: boolean = applicationWizardService.isCoApplicant(); expect(isCoApplicant).toBe(true); component.group.patchValue({ 'applicantType': CreditApplicationValues.CHOICE_NO, 'limitRequested': '1000', 'maritalStatus': CreditApplicationValues.CHOICE_NO }); creditApplicationService.saveMemberInformation(component.group.value); const changedCoApplicant: boolean = applicationWizardService.isCoApplicant(); expect(changedCoApplicant).toBe(false); }); it('should submit an application ', () => { const application = applicationWizardService.getFullCreditApplication(); spyOn(creditApplicationDaoService, 'submitApplication').and.returnValue(of(true)); applicationWizardService.submitCreditApplication(application); expect(creditApplicationDaoService.submitApplication).toHaveBeenCalled(); }); it('should submit an application for decision', () => { const application = applicationWizardService.getFullCreditApplication(); spyOn(creditApplicationDaoService, 'decideApplication').and.returnValue(of(true)); applicationWizardService.submitApplicationForDecision(application); expect(creditApplicationDaoService.decideApplication).toHaveBeenCalled(); }); it('should update an applications decision status', () => { spyOn(creditApplicationDaoService, 'getApplicationDecision').and.returnValue(of(true)); applicationWizardService.updateApplicationDecisionStatus(); expect(creditApplicationDaoService.getApplicationDecision).toHaveBeenCalled(); }); it('should return data for primary applicant', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); const primaryData1 = applicationWizardService.getIndividualGroupValues('employmentInformation', BorrowerType.PRIMARY_BORROWER); expect(primaryData1).toEqual(apiTranslatorPreTranslate.fullInfoBorrowers[0].employmentInformation); expect(Array.isArray(primaryData1)).toBeTruthy(); }); it('should return data for secondary applicant', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); const primaryData1 = applicationWizardService.getIndividualGroupValues('otherIncomeInformation', BorrowerType.CO_BORROWER); expect(primaryData1).toEqual(apiTranslatorPreTranslate.fullInfoBorrowers[1].otherIncomeInformation); }); it('should return the applicant\'s first name', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); expect(applicationWizardService.getApplicantName(BorrowerType.PRIMARY_BORROWER)) .toEqual(apiTranslatorPreTranslate.fullInfoBorrowers[0].personalInformation.firstName); expect(applicationWizardService.getApplicantName(BorrowerType.CO_BORROWER)) .toEqual(apiTranslatorPreTranslate.fullInfoBorrowers[1].personalInformation.firstName); }); it('should return a field value w/ or w/o a group', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); expect(applicationWizardService.getFieldValue('loanType')).toEqual(apiTranslatorPreTranslate.loanType); expect(applicationWizardService.getFieldValue('estimatedValue', 'collateralInformation')) .toBe(apiTranslatorPreTranslate.collateralInformation.estimatedValue); }); it('should determine that a loan needs collateral information', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); // apiTranslatorPreTranslate is using Loan type 8, which does not require collateral. // 8 used to be MANUFACTURED_HOME_LOAN which is commented out as of 2023. expect(applicationWizardService.needsCollateral()).toBe(false); }); it('should determine that a loan doesn\'t need collateral information', () => { const creditCardApplication = apiTranslatorPreTranslate; creditCardApplication.loanType = LoanTypeSet[0]; spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(creditCardApplication); expect(applicationWizardService.needsCollateral()).toBe(false); }); it('should return true if the co-borrower is married to the primary borrower', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); expect(applicationWizardService.isCoApplicantSpouse()).toBe(true); }); it('should return false if the co-borrower is not married to the primary borrower', () => { const applicantsAreNotMarriedToEachOther = apiTranslatorPreTranslate; applicantsAreNotMarriedToEachOther.hasCoApplicantSpouse = null; spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(applicantsAreNotMarriedToEachOther); expect(applicationWizardService.isCoApplicantSpouse()).toBe(false); }); // tslint:disable-next-line:max-line-length it('should return false if the applicant/co-applicant does not need to provide spouse information (if primary and co-borrower are not married to each other)', () => { apiTranslatorPreTranslate.hasCoApplicantSpouse = CreditApplicationValues.CHOICE_YES; apiTranslatorPreTranslate.fullInfoBorrowers[0].personalInformation.maritalStatus = CreditApplicationValues.CHOICE_YES; spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); spyOn(applicationWizardService, 'isCoApplicantSpouse').and.callThrough(); expect(applicationWizardService.isApplicantNonSpouse(BorrowerType.CO_BORROWER)).toBe(false); }); it('should return true if the applicant/co-applicant needs to provide spouse information', () => { apiTranslatorPreTranslate.hasCoApplicantSpouse = CreditApplicationValues.CHOICE_NO; spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); spyOn(applicationWizardService, 'isCoApplicantSpouse').and.callThrough(); expect(applicationWizardService.isApplicantNonSpouse(BorrowerType.PRIMARY_BORROWER)).toBe(true); }); it('should return false if this is not a Manufactured Home', () => { const mfgHomeNotOnRentedLotApplication = apiTranslatorPreTranslate; mfgHomeNotOnRentedLotApplication.loanType = LoanTypeSet[4]; spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(mfgHomeNotOnRentedLotApplication); expect(applicationWizardService.isRentedLotInfoRequired()).toBe(false); expect(applicationWizardService.isLienPositionInfoRequired()).toBe(true); }); it('should return group values', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); expect(applicationWizardService.getGroupValues('collateralInformation')).toEqual(apiTranslatorPreTranslate.collateralInformation); expect(applicationWizardService.getGroupValues('someNonExistantGroup')).toEqual({}); }); it('should return an individual from the application', () => { spyOn(applicationWizardService, 'getFullCreditApplication').and.returnValue(apiTranslatorPreTranslate); expect(applicationWizardService.getIndividualByBorrowerType(BorrowerType.CO_BORROWER)) .toEqual(apiTranslatorPreTranslate.fullInfoBorrowers[1]); }); it('should correctly calculate a simple next route name', () => { const service = applicationWizardService; expect(service.getSimpleRouteName('https://applydev.landmarkcu.com/loan-wizard/cc/re/step-2')).toEqual('step-2'); expect(service.getSimpleRouteName('https://a.x.com/lw/cc/re/step-1?fbclid=IwAR226oQp-ISjjS9U1I440bjA')).toEqual('step-1'); }); });