diff --git a/src/app/client/src/app/modules/public/module/sign-in/sso/components/update-contact/update-contact.component.spec.ts b/src/app/client/src/app/modules/public/module/sign-in/sso/components/update-contact/update-contact.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c5237a7a8516f43e032667cf05eded9c6a36f69 --- /dev/null +++ b/src/app/client/src/app/modules/public/module/sign-in/sso/components/update-contact/update-contact.component.spec.ts @@ -0,0 +1,399 @@ +import { FormControl, FormGroup } from '@angular/forms'; +import { UpdateContactComponent } from './update-contact.component'; +import { ActivatedRoute } from '@angular/router'; +import { ToasterService } from '@sunbird/shared'; +import { TncService } from '@sunbird/core'; +import { TelemetryService } from '@sunbird/telemetry'; +import { ResourceService } from '@sunbird/shared'; +import { of as observableOf, Observable, throwError as observableThrowError } from 'rxjs'; +import { TenantService, UserService, OtpService, OrgDetailsService } from '@sunbird/core'; +import { mockUpdateContactData } from './update-contact.mock.spec.data' +import { NavigationHelperService, UtilService } from '../../../../../../shared/services'; +import { SignupService } from '../../../../signup'; + +describe('UpdateContactComponent', () => { + let component: UpdateContactComponent; + + const activatedRoute: Partial<ActivatedRoute> = { + snapshot: mockUpdateContactData.snapshotData as any, + queryParams: observableOf({ userId: 'mockUserId' }) + }; + const tenantService: Partial<TenantService> = { + tenantData$: observableOf({ favicon: 'sample-favicon', tenantData: { logo: 'test' } }) as any + }; + const resourceService: Partial<ResourceService> = { + frmelmnts: mockUpdateContactData.resourceBundle.frmelmnts, + messages: mockUpdateContactData.resourceBundle.messages + }; + const userService: Partial<UserService> = { + getUserByKey: jest.fn().mockReturnValue(observableOf(mockUpdateContactData.userData)) + }; + const otpService: Partial<OtpService> = { + generateOTP: jest.fn().mockReturnValue(observableOf()) + }; + const toasterService: Partial<ToasterService> = { + error: jest.fn() + }; + const navigationHelperService: Partial<NavigationHelperService> = { + getPageLoadTime: jest.fn() + }; + const orgDetailsService: Partial<OrgDetailsService> = { + getCustodianOrgDetails: jest.fn() + }; + const utilService: Partial<UtilService> = { + parseJson: jest.fn() + }; + const signupService: Partial<SignupService> = {}; + const telemetryService: Partial<TelemetryService> = { + interact: jest.fn(), + log: jest.fn() + }; + const tncService: Partial<TncService> = { + getTncConfig: jest.fn().mockReturnValue(observableOf({ + 'id': 'api', + 'params': { + 'status': 'success', + }, + 'responseCode': 'OK', + 'result': { + 'response': { + 'id': 'tncConfig', + 'field': 'tncConfig', + 'value': '{"latestVersion":"v4","v4":{"url":}}' + } + } + })) + }; + + beforeEach(() => { + component = new UpdateContactComponent( + + activatedRoute as ActivatedRoute, + tenantService as TenantService, + resourceService as ResourceService, + userService as UserService, + otpService as OtpService, + toasterService as ToasterService, + navigationHelperService as NavigationHelperService, + orgDetailsService as OrgDetailsService, + utilService as UtilService, + signupService as SignupService, + telemetryService as TelemetryService, + tncService as TncService, + ) + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should show Merge confirmation after success otp verification', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + component.userDetails = { + id: 'mockId' + }; + component.handleOtpValidationSuccess(); + expect(component.showOtpComp).toEqual(false); + expect(component.showMergeConfirmation).toEqual(true); + }); + + it('should redirect verified user', () => { + jest.spyOn(component, 'getQueryParams'); + Object.defineProperty(window, 'location', { + writable: true, + value: { assign: jest.fn() } + }); + component.userDetails = {}; + component.handleOtpValidationSuccess(); + expect(component.getQueryParams).toHaveBeenCalled(); + }); + + it('should reset form as otp validation failed', () => { + component.handleOtpValidationFailed(); + expect(component).toBeTruthy(); + expect(component.showOtpComp).toEqual(false); + expect(component.disableSubmitBtn).toEqual(true); + expect(component.contactForm).toEqual({ + value: '', + type: 'phone', + tncAccepted: false + }); + expect(component.userExist).toEqual(false); + expect(component.userBlocked).toEqual(false); + }); + + it('should reset form as otp validation failed', (done) => { + jest.spyOn(component, 'handleFormChangeEvent').mockImplementation(); + component.handleOtpValidationFailed(); + setTimeout(() => { + expect(component.handleFormChangeEvent).toHaveBeenCalled(); + done() + }, 100); + }); + + it('should return query params for given query object', () => { + const test = component.getQueryParams({ queryParam1: 'mockValue' }); + expect(test).toEqual('?queryParam1=mockValue'); + }); + + it('should not fail if query parmas are not send', () => { + const test = component.getQueryParams({}); + expect(test).toEqual('?'); + }); + + it('should reset form', () => { + component.resetForm(); + expect(component.disableSubmitBtn).toEqual(true); + expect(component.contactForm).toEqual({ + value: '', + type: 'phone', + tncAccepted: false + }); + expect(component.userExist).toEqual(false); + expect(component.userDetails).toEqual({}); + expect(component.userBlocked).toEqual(false); + }); + + it('should not throw error and not generate otp as root org id is different', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableOf(mockUpdateContactData.userData) as any); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => observableOf(mockUpdateContactData.nonCustOrgDetails) as any); + component.onFormUpdate(); + expect(component.userExist).toEqual(true); + expect(component.userBlocked).toEqual(false); + expect(component.disableSubmitBtn).toEqual(true); + }); + + it('should not generate otp as user account blocked', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.blockedUserError)); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => observableOf(mockUpdateContactData.nonCustOrgDetails)); + component.onFormUpdate(); + expect(component.userExist).toEqual(false); + expect(component.userBlocked).toEqual(true); + expect(component.disableSubmitBtn).toEqual(true); + }); + + it('should not generate otp as an eror occured', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError({ + error: { + params: { + status: 'I\'m a teapot' + } + } + })); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => observableOf(mockUpdateContactData.nonCustOrgDetails)); + component.onFormUpdate(); + expect(component.disableSubmitBtn).toEqual(true); + expect(component.captchaValidationFailed).toEqual(true); + }); + + it('should generate otp as user not found', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError) as any); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.nonCustOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableOf(mockUpdateContactData.successResponse) as any); + component.onFormUpdate(); + }); + + it('should not generate otp and throw error as phone is in use', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError)); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.nonCustOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableThrowError(mockUpdateContactData.phoneAlreadyUsedError)); + jest.spyOn(toasterService, 'error').mockImplementation((value) => { + return value; + }); + component.onFormUpdate(); + expect(toasterService.error).toHaveBeenCalledWith('PHONE_ALREADY_IN_USE'); + }); + + it('should not generate otp and throw error as email is in use', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError)); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.nonCustOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableThrowError(mockUpdateContactData.emailAlreadyUsedError)); + jest.spyOn(toasterService, 'error').mockImplementation((value) => { + return value; + }); + component.onFormUpdate(); + expect(toasterService.error).toHaveBeenCalledWith('EMAIL_IN_USE'); + }); + + it('should not generate otp and throw error as rate limit has exceed', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError)); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.nonCustOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableThrowError(mockUpdateContactData.rateLimitExceed)); + jest.spyOn(toasterService, 'error').mockImplementation((value) => { + return value; + }); + component.onFormUpdate(); + expect(toasterService.error).toHaveBeenCalledWith('ERROR_RATE_LIMIT_EXCEEDED'); + }); + + it('should not generate otp and throw error as server error', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError)); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.nonCustOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableThrowError(mockUpdateContactData.serverError)); + jest.spyOn(toasterService, 'error').mockImplementation((value) => { + return value; + }); + component.onFormUpdate(); + expect(toasterService.error).toHaveBeenCalledWith(mockUpdateContactData.resourceBundle.messages.fmsg.m0085); + }); + + it('should generate otp as user org id is same for email id', () => { + component.contactForm.type = 'email'; + component.contactForm.value = 'test@gmail.com'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => observableOf(mockUpdateContactData.userData) as Observable<any>); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.custOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => observableOf(mockUpdateContactData.successResponse) as Observable<any>); + component.onFormUpdate(); + expect(component.userDetails).toEqual(mockUpdateContactData.userData.result.response); + expect(component.userExist).toEqual(false); + expect(component.userBlocked).toEqual(false); + expect(component.disableSubmitBtn).toEqual(false); + }); + + it('should generate otp as user org id is same for phone number', () => { + component.contactForm.type = 'phone'; + component.contactForm.value = '7896541257'; + jest.spyOn(userService, 'getUserByKey').mockImplementation(() => + observableOf(mockUpdateContactData.userData) as Observable<any>); + jest.spyOn(orgDetailsService, 'getCustodianOrgDetails').mockImplementation(() => + observableOf(mockUpdateContactData.custOrgDetails)); + jest.spyOn(otpService, 'generateOTP').mockImplementation(() => + observableOf(mockUpdateContactData.successResponse) as Observable<any>); + component.onFormUpdate(); + expect(component.userDetails).toEqual(mockUpdateContactData.userData.result.response); + expect(component.userExist).toEqual(false); + expect(component.userBlocked).toEqual(false); + expect(component.disableSubmitBtn).toEqual(false); + }); + + it('initiate instance with SUNBIRD', () => { + jest.spyOn(component, 'fetchTncConfiguration'); + component.ngOnInit(); + expect(component.instance).toEqual('SUNBIRD'); + expect(component.fetchTncConfiguration).toHaveBeenCalled(); + }); + + it('initiate instance with SUNBIRD without captcha', () => { + jest.spyOn(component, 'fetchTncConfiguration'); + let mockElement = (<HTMLInputElement>document.createElement('p1reCaptchaEnabled')); + mockElement.value = "false"; + jest.spyOn(document, 'getElementById').mockReturnValue(mockElement); + component.ngOnInit(); + expect(component.instance).toEqual('SUNBIRD'); + expect(component.fetchTncConfiguration).toHaveBeenCalled(); + }); + + it('should toggle tnc checkboc if already false', () => { + jest.spyOn(telemetryService, 'interact'); + component.toggleTncCheckBox({ target: { checked: true } }); + expect(component.contactForm.tncAccepted).toEqual(true); + expect(telemetryService.interact).toHaveBeenCalledWith(mockUpdateContactData.interactEDataSelected); + }); + + it('should toggle tnc checkboc', () => { + jest.spyOn(telemetryService, 'interact'); + component.toggleTncCheckBox({ target: { checked: false } }); + expect(component.contactForm.tncAccepted).toEqual(false); + expect(telemetryService.interact).toHaveBeenCalledWith(mockUpdateContactData.interactEDataUnSelected); + }); + + it('should fetch tnc configuration', () => { + jest.spyOn(tncService, 'getTncConfig').mockReturnValue(observableOf(mockUpdateContactData.tncConfig) as any) + jest.spyOn(telemetryService, 'log'); + component.fetchTncConfiguration(); + expect(telemetryService.log).toHaveBeenCalledWith(mockUpdateContactData.telemetryLogSuccess); + }); + + it('should fetch tnc configuration and throw error as cannot parse data', () => { + jest.spyOn(tncService, 'getTncConfig').mockReturnValue(observableOf(mockUpdateContactData.tncConfigIncorrectData) as any); + jest.spyOn(toasterService, 'error'); + component.fetchTncConfiguration(); + expect(toasterService.error).toHaveBeenCalledWith(mockUpdateContactData.resourceBundle.messages.fmsg.m0004); + }); + + it('should fetch tnc configuration and throw error', () => { + jest.spyOn(tncService, 'getTncConfig').mockReturnValue(observableThrowError(mockUpdateContactData.tncConfigIncorrectData) as any); + jest.spyOn(toasterService, 'error'); + component.fetchTncConfiguration(); + expect(toasterService.error).toHaveBeenCalledWith(mockUpdateContactData.resourceBundle.messages.fmsg.m0004); + }); + + it('should show tnc popup if given mode is true', () => { + component.showAndHidePopup(true); + expect(component.showTncPopup).toBe(true); + }); + + it('should not show tnc popup if given mode is false', () => { + component.showAndHidePopup(false); + expect(component.showTncPopup).toBe(false); + }); + + it('should submit form when captcha enabled', () => { + component.isP1CaptchaEnabled = 'true'; + jest.spyOn(component, 'resetGoogleCaptcha'); + jest.spyOn(component, 'resolved').mockImplementation(() => true); + component.submitForm(); + expect(component.resetGoogleCaptcha).toHaveBeenCalled(); + }); + + it('should submit form when captcha is not enabled', () => { + component.isP1CaptchaEnabled = 'false'; + jest.spyOn(component, 'onFormUpdate'); + component.submitForm(); + expect(component.onFormUpdate).toHaveBeenCalled(); + }); + + it('should receive response from captcha', () => { + component.isP1CaptchaEnabled = 'true'; + jest.spyOn(component, 'onFormUpdate').mockImplementation(() => true); + component.resolved(mockUpdateContactData.captchaToken); + expect(component.onFormUpdate).toHaveBeenCalledWith(mockUpdateContactData.captchaToken); + }); + + it("should call ngAfterViewInit", (done) => { + jest.spyOn(component, 'handleFormChangeEvent').mockImplementation(); + component.ngAfterViewInit(); + setTimeout(() => { + expect(component.handleFormChangeEvent).toHaveBeenCalled(); + done() + }); + }); + + it("should call handleFormChangeEvent", () => { + // @ts-ignore + component.contactDetailsForm = new FormGroup({ + value: new FormControl('12345'), + type: new FormControl('phone'), + tncAccepted: new FormControl(true), + status: new FormControl('VALID'), + }) + component.handleFormChangeEvent(); + // @ts-ignore + component.contactDetailsForm.valueChanges.subscribe((data, data2) => { + expect(component.disableSubmitBtn).toBeFalsy(); + }) + }) +}); \ No newline at end of file diff --git a/src/app/client/src/app/modules/shared/services/activity-dashboard/activity-dashboard.service.spec.ts b/src/app/client/src/app/modules/shared/services/activity-dashboard/activity-dashboard.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8f72b151a746968d6341018c546cb3862a8c16c7 --- /dev/null +++ b/src/app/client/src/app/modules/shared/services/activity-dashboard/activity-dashboard.service.spec.ts @@ -0,0 +1,26 @@ +import { TestBed } from '@angular/core/testing'; +import { truncate } from 'fs'; + +import { ActivityDashboardService } from './activity-dashboard.service'; + +describe('ActivityDashboardService', () => { + let service: ActivityDashboardService; + + beforeEach(() => { + service = new ActivityDashboardService(); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('should set isActivityAdded', () => { + service.isActivityAdded = true; + expect(service['_isActivityAdded']).toEqual(true); + }); + + it('should get isActivityAdded', () => { + service._isActivityAdded = true; + expect(service['isActivityAdded']).toEqual(true); + }); +}); \ No newline at end of file diff --git a/src/app/client/src/app/plugins/profile/components/account-recovery-info/account-recovery-info.component.spec.ts b/src/app/client/src/app/plugins/profile/components/account-recovery-info/account-recovery-info.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e9ac2d061ac10ce68a097b792d1a35f58f9429cf --- /dev/null +++ b/src/app/client/src/app/plugins/profile/components/account-recovery-info/account-recovery-info.component.spec.ts @@ -0,0 +1,217 @@ +import { AccountRecoveryInfoComponent } from './account-recovery-info.component'; +import { ResourceService } from '@sunbird/shared'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { ProfileService } from './../../services'; +import { of as observableOf, of, throwError } from 'rxjs'; +import { OtpService, UserService } from '../../../../modules/core'; +import { ConfigService, ToasterService } from '../../../../modules/shared'; +import { MatDialog } from '@angular/material/dialog'; + +describe('AccountRecoveryInfoComponent', () => { + let component: AccountRecoveryInfoComponent; + + const resourceService: Partial<ResourceService> = { + 'messages': { + 'smsg': { + 'm0047': 'Your Mobile Number has been updated', + 'm0048': 'Your email address has been updated' + }, + 'emsg': { + 'm0014': 'Could not update mobile number', + 'm0015': 'Could not update email address' + } + }, + 'frmelmnts': { + 'lbl': { + unableToUpdateMobile: 'unableToUpdateMobile', + unableToUpdateEmail: 'unableToUpdateEmail', + wrongPhoneOTP: 'wrongPhoneOTP', + wrongEmailOTP: 'wrongEmailOTP' + + }, + instn: { + 't0083': 'Could not update email address', + 't0084': 'Could not update email address', + } + } + }; + const profileService: Partial<ProfileService> = { + updateProfile: jest.fn() + }; + const userService: Partial<UserService> = {}; + const matDialog: Partial<MatDialog> = { + getDialogById: jest.fn() + }; + const toasterService: Partial<ToasterService> = { + success: jest.fn(), + error: jest.fn() + }; + const otpService: Partial<OtpService> = { + generateOTP: jest.fn().mockImplementation(() => of(true)) + }; + const configService: Partial<ConfigService> = { + appConfig: { + OTPTemplate: { + updateContactTemplate: 'updateContactTemplate' + } + }, + }; + + beforeEach(() => { + component = new AccountRecoveryInfoComponent( + resourceService as ResourceService, + profileService as ProfileService, + userService as UserService, + matDialog as MatDialog, + toasterService as ToasterService, + otpService as OtpService, + configService as ConfigService, + ) + component.userProfile = { + email: 'emailid', + phone: '5253252321' + }; + component.otpData = {}; + component.showOTPForm = true; + }); + + it('should select email id radio button by default and call initialize initializeFormFields() ', () => { + jest.spyOn(component, 'validateAndEditContact'); + component.showOTPForm = false; + component.ngOnInit(); + expect(component.contactType).toBe('emailId'); + expect(component.validateAndEditContact).toHaveBeenCalled(); + }); + + it('should select recovery email id radio button and call initialize initializeFormFields() ', () => { + jest.spyOn(component, 'validateAndEditContact'); + component.userProfile = { + recoveryEmail: 'emailid', + }; + component.showOTPForm = false; + component.ngOnInit(); + expect(component.contactType).toBe('emailId'); + expect(component.validateAndEditContact).toHaveBeenCalled(); + }); + + it('should select recovery phone radio button and call initialize initializeFormFields() ', () => { + jest.spyOn(component, 'validateAndEditContact'); + component.userProfile = { + recoveryPhone: 567127788, + }; + component.showOTPForm = false; + component.ngOnInit(); + expect(component.contactType).toBe('emailId'); + expect(component.validateAndEditContact).toHaveBeenCalled(); + }); + + it('should select email id radio button by default and call initialize initializeFormFields() ', () => { + component.accountRecoveryForm = new FormGroup({ + email: new FormControl('test@demo.com', [Validators.required, Validators.pattern(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-z]{2,4}$/)]), + }); + component.userVerificationSuccess(); + expect(component.showOTPForm).toEqual(false); + }); + + it('initializeFormFields if emailId radio is selected', () => { + component.contactType = 'emailId'; + jest.spyOn(component, 'handleSubmitButton'); + jest.spyOn(component, 'setTelemetryData'); + component.initializeFormFields(); + expect(component.handleSubmitButton).toHaveBeenCalled(); + expect(component.setTelemetryData).toHaveBeenCalled(); + }); + + it('initializeFormFields if phone no. radio is selected', () => { + component.contactType = 'phoneNo'; + jest.spyOn(component, 'handleSubmitButton'); + jest.spyOn(component, 'setTelemetryData'); + component.initializeFormFields(); + expect(component.handleSubmitButton).toHaveBeenCalled(); + expect(component.setTelemetryData).toHaveBeenCalled(); + }); + + it('should shoudl call initializeFormFields() whenever different radio button is selected', () => { + component.accountRecoveryForm = new FormGroup({ + email: new FormControl('test@demo.com', [Validators.required, Validators.pattern(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-z]{2,4}$/)]), + }); + jest.spyOn(component, 'initializeFormFields'); + component.onItemChange(); + expect(component.initializeFormFields).toHaveBeenCalled(); + }); + + it('should add/update phone no. for account recovery identifier', () => { + component.enableSubmitButton = false; + component.contactType = 'phoneNo'; + jest.spyOn(component, 'closeModal'); + jest.spyOn(profileService, 'updateProfile').mockReturnValue(observableOf({}) as any); + component.onItemChange(); + component.updateRecoveryId(); + expect(component.closeModal).toHaveBeenCalled(); + }); + + it('should throw error while adding/updating phone no for recovery identifier', () => { + component.enableSubmitButton = false; + component.contactType = 'phoneNo'; + jest.spyOn(component, 'closeModal'); + jest.spyOn(profileService, 'updateProfile').mockReturnValue(throwError({ error: { params: { err: 'RECOVERY_PARAM_MATCH_EXCEPTION' } } }) as any); + component.onItemChange(); + component.updateRecoveryId(); + expect(component.closeModal).not.toHaveBeenCalled(); + }); + + it('should throw error while adding/updating phone no for recovery identifier error', () => { + component.enableSubmitButton = false; + component.contactType = 'phoneNo'; + jest.spyOn(component, 'closeModal'); + jest.spyOn(profileService, 'updateProfile').mockReturnValue(throwError({ error: {} }) as any); + component.onItemChange(); + component.updateRecoveryId(); + }); + + it('should add/update email id for account recovery identifier', () => { + component.enableSubmitButton = false; + component.contactType = 'emailId'; + jest.spyOn(component, 'closeModal'); + jest.spyOn(profileService, 'updateProfile').mockReturnValue(observableOf({}) as any); + component.onItemChange(); + component.updateRecoveryId(); + expect(component.closeModal).toHaveBeenCalled(); + }); + it('should show appropriate message when fails to generate OTP', () => { + component.accountRecoveryForm = new FormGroup({ + email: new FormControl('test@demo.com', [Validators.required, Validators.pattern(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-z]{2,4}$/)]), + uniqueContact: new FormControl(true, [Validators.required]) + }); + component.contactType = 'email'; + jest.spyOn(otpService, 'generateOTP').mockReturnValue(throwError({ error: { params: { status: 'EMAIL_IN_USE', errmsg: 'error' } } })); + component.validateAndEditContact(); + expect(otpService.generateOTP).toHaveBeenCalled(); + expect(toasterService.error).toHaveBeenCalledWith('error'); + }); + + it('should show appropriate error message when fails to generate OTP', () => { + component.accountRecoveryForm = new FormGroup({ + email: new FormControl('test@demo.com', [Validators.required, Validators.pattern(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-z]{2,4}$/)]), + uniqueContact: new FormControl(true, [Validators.required]) + }); + component.contactType = 'email'; + jest.spyOn(otpService, 'generateOTP').mockReturnValue(throwError({ error: { params: { status: 'error', errmsg: 'error' } } })); + component.validateAndEditContact(); + expect(otpService.generateOTP).toHaveBeenCalled(); + expect(toasterService.error).toHaveBeenCalledWith('error'); + }); + + + it('should unsubscribe from all observable subscriptions', () => { + component.contactType = 'phone'; + component.accountRecoveryForm = new FormGroup({ + email: new FormControl('test@demo.com', [Validators.required, Validators.pattern(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-z]{2,4}$/)]), + }); + component.dialogProps = { id: "asd" }; + jest.spyOn(component, 'closeMatDialog'); + component.initializeFormFields(); + component.ngOnDestroy(); + expect(component.closeMatDialog).toHaveBeenCalled(); + }); +}); \ No newline at end of file