-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: controller logic and tests for onboarding home page (#3387)
- Loading branch information
1 parent
b003ae1
commit 0c53949
Showing
12 changed files
with
700 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import deepFreeze from 'deep-freeze-strict'; | ||
import { OnboardingStatus } from '../models/onboarding-status.model'; | ||
import { OnboardingState } from '../models/onboarding-state.enum'; | ||
|
||
export const onboardingStatusData: OnboardingStatus = deepFreeze({ | ||
user_id: 'us1ymEVgUKqb', | ||
org_id: 'orOTDe765hQp', | ||
step_connect_cards_is_configured: false, | ||
step_connect_cards_is_skipped: false, | ||
step_sms_opt_in_is_configured: false, | ||
step_sms_opt_in_is_skipped: false, | ||
step_show_welcome_modal_is_complete: false, | ||
state: OnboardingState.YET_TO_START, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { TestBed } from '@angular/core/testing'; | ||
import { SpenderOnboardingService } from './spender-onboarding.service'; | ||
import { SpenderPlatformV1ApiService } from './spender-platform-v1-api.service'; | ||
import { OnboardingStepStatus } from '../models/onboarding-step-status.model'; | ||
import { of } from 'rxjs'; | ||
import { onboardingStatusData } from '../mock-data/onboarding-status.data'; | ||
import { OnboardingWelcomeStepStatus } from '../models/onboarding-welcome-step-status.model'; | ||
|
||
describe('SpenderOnboardingService', () => { | ||
let spenderOnboardingService: SpenderOnboardingService; | ||
let spenderPlatformV1ApiService: jasmine.SpyObj<SpenderPlatformV1ApiService>; | ||
|
||
beforeEach(() => { | ||
const spenderPlatformV1ApiServiceSpy = jasmine.createSpyObj('SpenderPlatformV1ApiService', ['get', 'post']); | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
SpenderOnboardingService, | ||
[ | ||
{ | ||
provide: SpenderPlatformV1ApiService, | ||
useValue: spenderPlatformV1ApiServiceSpy, | ||
}, | ||
], | ||
], | ||
}); | ||
spenderOnboardingService = TestBed.inject(SpenderOnboardingService); | ||
spenderPlatformV1ApiService = TestBed.inject( | ||
SpenderPlatformV1ApiService | ||
) as jasmine.SpyObj<SpenderPlatformV1ApiService>; | ||
}); | ||
|
||
it('getOnboardingStatus(): should get onboarding status', (done) => { | ||
const onboardingResponse = onboardingStatusData; | ||
spenderPlatformV1ApiService.get.and.returnValue(of({ data: onboardingResponse })); | ||
|
||
spenderOnboardingService.getOnboardingStatus().subscribe((res) => { | ||
expect(res).toEqual(onboardingResponse); | ||
expect(spenderPlatformV1ApiService.get).toHaveBeenCalledOnceWith('/onboarding'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('processConnnectCardsStep(): should process connect card step', (done) => { | ||
const onboardingRequestResponse: OnboardingStepStatus = { | ||
is_configured: true, | ||
is_skipped: false, | ||
}; | ||
spenderPlatformV1ApiService.post.and.returnValue(of({ data: onboardingRequestResponse })); | ||
|
||
spenderOnboardingService.processConnectCardsStep(onboardingRequestResponse).subscribe((res) => { | ||
expect(res).toEqual(onboardingRequestResponse); | ||
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_connect_cards', { | ||
data: onboardingRequestResponse, | ||
}); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('processSmsOptInStep(): should process opt in step', (done) => { | ||
const onboardingRequestResponse: OnboardingStepStatus = { | ||
is_configured: true, | ||
is_skipped: false, | ||
}; | ||
spenderPlatformV1ApiService.post.and.returnValue(of({ data: onboardingRequestResponse })); | ||
|
||
spenderOnboardingService.processSmsOptInStep(onboardingRequestResponse).subscribe((res) => { | ||
expect(res).toEqual(onboardingRequestResponse); | ||
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_sms_opt_in', { | ||
data: onboardingRequestResponse, | ||
}); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('processWelcomeModalStep(): should get category count', (done) => { | ||
const onboardingRequestResponse: OnboardingWelcomeStepStatus = { | ||
is_complete: true, | ||
}; | ||
spenderPlatformV1ApiService.post.and.returnValue(of({ data: onboardingRequestResponse })); | ||
|
||
spenderOnboardingService.processWelcomeModalStep(onboardingRequestResponse).subscribe((res) => { | ||
expect(res).toEqual(onboardingRequestResponse); | ||
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_show_welcome_modal', { | ||
data: onboardingRequestResponse, | ||
}); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('markWelcomeModalStepAsComplete(): should call processWelcomeModalStep with the correct data', (done) => { | ||
const mockData: OnboardingWelcomeStepStatus = { is_complete: true }; | ||
spyOn(spenderOnboardingService, 'processWelcomeModalStep').and.returnValue(of(mockData)); | ||
|
||
spenderOnboardingService.markWelcomeModalStepAsComplete().subscribe((result) => { | ||
expect(spenderOnboardingService.processWelcomeModalStep).toHaveBeenCalledWith(mockData); | ||
expect(result).toEqual(mockData); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('markConnectCardsStepAsComplete(): should call processConnectCardsStep with the correct data', (done) => { | ||
const mockData: OnboardingStepStatus = { is_configured: true, is_skipped: false }; | ||
spyOn(spenderOnboardingService, 'processConnectCardsStep').and.returnValue(of(mockData)); | ||
|
||
spenderOnboardingService.markConnectCardsStepAsComplete().subscribe((result) => { | ||
expect(spenderOnboardingService.processConnectCardsStep).toHaveBeenCalledWith(mockData); | ||
expect(result).toEqual(mockData); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('skipConnectCardsStep(): should call processConnectCardsStep with the correct data', (done) => { | ||
const mockData: OnboardingStepStatus = { is_configured: false, is_skipped: true }; | ||
spyOn(spenderOnboardingService, 'processConnectCardsStep').and.returnValue(of(mockData)); | ||
|
||
spenderOnboardingService.skipConnectCardsStep().subscribe((result) => { | ||
expect(spenderOnboardingService.processConnectCardsStep).toHaveBeenCalledWith(mockData); | ||
expect(result).toEqual(mockData); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('markSmsOptInStepAsComplete(): should call processSmsOptInStep with the correct data', (done) => { | ||
const mockData: OnboardingStepStatus = { is_configured: true, is_skipped: false }; | ||
spyOn(spenderOnboardingService, 'processSmsOptInStep').and.returnValue(of(mockData)); | ||
|
||
spenderOnboardingService.markSmsOptInStepAsComplete().subscribe((result) => { | ||
expect(spenderOnboardingService.processSmsOptInStep).toHaveBeenCalledWith(mockData); | ||
expect(result).toEqual(mockData); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('skipSmsOptInStep(): should call processSmsOptInStep with the correct data', (done) => { | ||
const mockData: OnboardingStepStatus = { is_configured: false, is_skipped: true }; | ||
spyOn(spenderOnboardingService, 'processSmsOptInStep').and.returnValue(of(mockData)); | ||
|
||
spenderOnboardingService.skipSmsOptInStep().subscribe((result) => { | ||
expect(spenderOnboardingService.processSmsOptInStep).toHaveBeenCalledWith(mockData); | ||
expect(result).toEqual(mockData); | ||
done(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
src/app/fyle/spender-onboarding/models/onboarding-step.enum.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum OnboardingStep { | ||
CONNECT_CARD, | ||
OPT_IN, | ||
} |
90 changes: 90 additions & 0 deletions
90
.../spender-onboarding-connect-card-step/spender-onboarding-connect-card-step.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<div class="connect-card__body"> | ||
<div> | ||
<div class="connect-card__heading">Connect corporate card</div> | ||
<div class="connect-card__sub-heading"> | ||
This will help you bring your card transactions into Fyle as expenses instantly. | ||
</div> | ||
|
||
<div class="connect-card__input-label"> | ||
<span>Corporate card</span> | ||
</div> | ||
|
||
<div | ||
class="connect-card__input-inner-container" | ||
[ngClass]="{ 'connect-card__input-inner-container--error': cardForm.touched && cardForm.invalid }" | ||
> | ||
<input | ||
class="smartlook-show connect-card__card-number-input pl-0" | ||
inputmode="numeric" | ||
[formControl]="cardForm" | ||
mask="0000 0000 0000 0000" | ||
data-testid="card-number-input" | ||
appAutofocus | ||
[timeout]="500" | ||
required | ||
placeholder="Enter corporate card number" | ||
/> | ||
|
||
<ion-icon | ||
*ngIf="!cardType || cardType === cardNetworkTypes.OTHERS" | ||
src="../../../../assets/svg/card.svg" | ||
class="connect-card__input-default-icon" | ||
data-testid="default-icon" | ||
></ion-icon> | ||
|
||
<img | ||
*ngIf="cardType === cardNetworkTypes.VISA" | ||
src="../../../../assets/images/visa-logo.png" | ||
class="connect-card__input-visa-icon" | ||
data-testid="visa-icon" | ||
/> | ||
|
||
<img | ||
*ngIf="cardType === cardNetworkTypes.MASTERCARD" | ||
src="../../../../assets/images/mastercard-logo.png" | ||
class="connect-card__input-mastercard-icon" | ||
data-testid="mastercard-icon" | ||
/> | ||
</div> | ||
|
||
<div class="connect-card__input-error-space"></div> | ||
|
||
<div *ngIf="cardForm.touched && cardForm.invalid" class="connect-card__input-errors" data-testid="error-message"> | ||
<span *ngIf="cardForm.errors.invalidCardNumber">Please enter a valid card number.</span> | ||
|
||
<ng-container *ngIf="cardForm.errors.invalidCardNetwork"> | ||
<span *ngIf="isVisaRTFEnabled && isMastercardRTFEnabled; else visaOnlyOrg" | ||
>Enter a valid Visa or Mastercard number. If you have other cards, please contact your admin.</span | ||
> | ||
|
||
<ng-template #visaOnlyOrg> | ||
<!-- Check if only visa is enabled --> | ||
<span *ngIf="cardForm.errors.invalidCardNetwork && isVisaRTFEnabled; else mastercardOnlyOrg" | ||
>Enter a valid Visa number. If you have other cards, please contact your admin.</span | ||
> | ||
</ng-template> | ||
|
||
<ng-template #mastercardOnlyOrg> | ||
<!-- Check if only mastercard is enabled --> | ||
<span *ngIf="cardForm.errors.invalidCardNetwork && isMastercardRTFEnabled" | ||
>Enter a valid Mastercard number. If you have other cards, please contact your admin.</span | ||
> | ||
</ng-template> | ||
</ng-container> | ||
|
||
<span *ngIf="cardForm.errors.enrollmentError"> | ||
{{ enrollmentFailureMessage }} | ||
</span> | ||
</div> | ||
</div> | ||
<div class="connect-card__primary-cta-container"> | ||
<ion-button | ||
class="btn-primary connect-card__primary-cta" | ||
fill="clear" | ||
aria-label="Navigate back to sign in page" | ||
role="button" | ||
> | ||
Continue | ||
</ion-button> | ||
</div> | ||
</div> |
Oops, something went wrong.