Skip to content

Commit

Permalink
feat: Add tests and component logic
Browse files Browse the repository at this point in the history
  • Loading branch information
bistaastha committed Dec 23, 2024
1 parent e6b4d99 commit 35c37cc
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 60 deletions.
14 changes: 14 additions & 0 deletions src/app/core/mock-data/onboarding-status.data.ts
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,
});
109 changes: 73 additions & 36 deletions src/app/core/services/spender-onboarding.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ 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';

// Add any other imports as necessary from the original TasksService spec
import { onboardingStatusData } from '../mock-data/onboarding-status.data';
import { OnboardingWelcomeStepStatus } from '../models/onboarding-welcome-step-status.model';

describe('SpenderOnboardingService', () => {
let spenderOnboardingService: SpenderOnboardingService;
Expand All @@ -29,21 +29,18 @@ describe('SpenderOnboardingService', () => {
) as jasmine.SpyObj<SpenderPlatformV1ApiService>;
});

fit('getOnboardingStatus(): should get onboarding status', (done) => {
const onboardingResponse: OnboardingStepStatus = {
is_configured: true,
is_skipped: false,
};
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('/spender/onboarding');
expect(spenderPlatformV1ApiService.get).toHaveBeenCalledOnceWith('/onboarding');
done();
});
});

fit('processConnnectCardsStep(): should process connect card step', (done) => {
it('processConnnectCardsStep(): should process connect card step', (done) => {
const onboardingRequestResponse: OnboardingStepStatus = {
is_configured: true,
is_skipped: false,
Expand All @@ -52,55 +49,95 @@ describe('SpenderOnboardingService', () => {

spenderOnboardingService.processConnectCardsStep(onboardingRequestResponse).subscribe((res) => {
expect(res).toEqual(onboardingRequestResponse);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith(
'/spender/onboarding/process_step_connect_cards',
onboardingRequestResponse
);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_connect_cards', {
data: onboardingRequestResponse,
});
done();
});
});

fit('processWelcomeModalStep(): should get category count', (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.processConnectCardsStep(onboardingRequestResponse).subscribe((res) => {
spenderOnboardingService.processSmsOptInStep(onboardingRequestResponse).subscribe((res) => {
expect(res).toEqual(onboardingRequestResponse);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith(
'/spender/onboarding/process_step_connect_cards',
onboardingRequestResponse
);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_sms_opt_in', {
data: onboardingRequestResponse,
});
done();
});
});

fit('getActiveCategoriesCount(): should get category count', (done) => {
const onboardingResponse: OnboardingStepStatus = {
is_configured: true,
is_skipped: false,
it('processWelcomeModalStep(): should get category count', (done) => {
const onboardingRequestResponse: OnboardingWelcomeStepStatus = {
is_complete: true,
};
spenderPlatformV1ApiService.get.and.returnValue(of({ data: onboardingResponse }));
spenderPlatformV1ApiService.post.and.returnValue(of({ data: onboardingRequestResponse }));

spenderOnboardingService.getOnboardingStatus().subscribe((res) => {
expect(res).toEqual(onboardingResponse);
expect(spenderPlatformV1ApiService.get).toHaveBeenCalledOnceWith('/spender/onboarding');
spenderOnboardingService.processWelcomeModalStep(onboardingRequestResponse).subscribe((res) => {
expect(res).toEqual(onboardingRequestResponse);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/onboarding/process_step_show_welcome_modal', {
data: onboardingRequestResponse,
});
done();
});
});

fit('getActiveCategoriesCount(): should get category count', (done) => {
const onboardingResponse: OnboardingStepStatus = {
is_configured: true,
is_skipped: false,
};
spenderPlatformV1ApiService.get.and.returnValue(of({ data: onboardingResponse }));
it('markWelcomeModalStepAsComplete(): should call processWelcomeModalStep with the correct data', (done) => {
const mockData: OnboardingWelcomeStepStatus = { is_complete: true };
spyOn(spenderOnboardingService, 'processWelcomeModalStep').and.returnValue(of(mockData));

spenderOnboardingService.getOnboardingStatus().subscribe((res) => {
expect(res).toEqual(onboardingResponse);
expect(spenderPlatformV1ApiService.get).toHaveBeenCalledOnceWith('/spender/onboarding');
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();
});
});
Expand Down
11 changes: 6 additions & 5 deletions src/app/core/services/spender-onboarding.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,37 @@ import { SpenderPlatformV1ApiService } from './spender-platform-v1-api.service';
import { PlatformApiResponse } from '../models/platform/platform-api-response.model';
import { OnboardingWelcomeStepStatus } from '../models/onboarding-welcome-step-status.model';
import { OnboardingStepStatus } from '../models/onboarding-step-status.model';
import { OnboardingStatus } from '../models/onboarding-status.model';

@Injectable({
providedIn: 'root',
})
export class SpenderOnboardingService {
constructor(private spenderPlatformV1ApiService: SpenderPlatformV1ApiService) {}

getOnboardingStatus(): Observable<OnboardingStepStatus> {
getOnboardingStatus(): Observable<OnboardingStatus> {
return this.spenderPlatformV1ApiService
.get<PlatformApiResponse<OnboardingStepStatus>>('/spender/onboarding')
.get<PlatformApiResponse<OnboardingStatus>>('/onboarding')
.pipe(map((res) => res.data));
}

processConnectCardsStep(data: OnboardingStepStatus): Observable<OnboardingStepStatus> {
return this.spenderPlatformV1ApiService
.post<PlatformApiResponse<OnboardingStepStatus>>('/spender/onboarding/process_step_connect_cards', {
.post<PlatformApiResponse<OnboardingStepStatus>>('/onboarding/process_step_connect_cards', {
data,
})
.pipe(map((res) => res.data));
}

processSmsOptInStep(data: OnboardingStepStatus): Observable<OnboardingStepStatus> {
return this.spenderPlatformV1ApiService
.post<PlatformApiResponse<OnboardingStepStatus>>('/spender/onboarding/process_step_sms_opt_in', { data })
.post<PlatformApiResponse<OnboardingStepStatus>>('/onboarding/process_step_sms_opt_in', { data })
.pipe(map((res) => res.data));
}

processWelcomeModalStep(data: OnboardingWelcomeStepStatus): Observable<OnboardingWelcomeStepStatus> {
return this.spenderPlatformV1ApiService
.post<PlatformApiResponse<OnboardingWelcomeStepStatus>>('/spender/onboarding/process_step_show_welcome_modal', {
.post<PlatformApiResponse<OnboardingWelcomeStepStatus>>('/onboarding/process_step_show_welcome_modal', {
data,
})
.pipe(map((res) => res.data));
Expand Down
16 changes: 13 additions & 3 deletions src/app/fyle/spender-onboarding/spender-onboarding.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ import { NgModule } from '@angular/core';
import { SharedModule } from 'src/app/shared/shared.module';
import { SpenderOnboardingPage } from './spender-onboarding.page';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { SpenderOnboardingRoutingModule } from './spender-onboarding-routing.module';
import { MatButtonModule } from '@angular/material/button';
import { SpenderOnboardingConnectCardStepComponent } from './spender-onboarding-connect-card-step/spender-onboarding-connect-card-step.component';

@NgModule({
imports: [SharedModule, CommonModule, FormsModule, IonicModule, MatButtonModule, SpenderOnboardingRoutingModule],
declarations: [SpenderOnboardingPage],
imports: [
SharedModule,
CommonModule,
FormsModule,
IonicModule,
MatButtonModule,
SpenderOnboardingRoutingModule,
FormsModule,
ReactiveFormsModule,
],
declarations: [SpenderOnboardingPage, SpenderOnboardingConnectCardStepComponent],
})
export class SpenderOnboardingPageModule {}
6 changes: 6 additions & 0 deletions src/app/fyle/spender-onboarding/spender-onboarding.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@
</div>
<div class="spender-onboarding__skip-cta" (click)="skipConnectCardOnboardingStep()">Skip</div>
</div>
<div class="spender-onboarding__component-container">
<app-spender-onboarding-connect-card-step
[orgSettings]="orgSettings"
(isStepCompleted)="skipOnboardingStep()"
></app-spender-onboarding-connect-card-step>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ $toolbar-border: #ababab6b;
border: 1px solid $border-info-lighter;
background: $pure-white;
box-shadow: -14px -6px 24px 0px #00000008;
height: 100%;
}

&__stepper-container {
Expand Down
106 changes: 106 additions & 0 deletions src/app/fyle/spender-onboarding/spender-onboarding.page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { of } from 'rxjs';
import { SpenderOnboardingPage } from './spender-onboarding.page';
import { LoaderService } from 'src/app/core/services/loader.service';
import { OrgUserService } from 'src/app/core/services/org-user.service';
import { SpenderOnboardingService } from 'src/app/core/services/spender-onboarding.service';
import { OrgSettingsService } from 'src/app/core/services/org-settings.service';
import { CorporateCreditCardExpenseService } from 'src/app/core/services/corporate-credit-card-expense.service';
import { OnboardingStep } from './models/onboarding-step.enum';
import { orgSettingsData } from 'src/app/core/test-data/accounts.service.spec.data';
import { onboardingStatusData } from 'src/app/core/mock-data/onboarding-status.data';
import { extendedOrgUserResponse } from 'src/app/core/test-data/tasks.service.spec.data';

describe('SpenderOnboardingPage', () => {
let component: SpenderOnboardingPage;
let fixture: ComponentFixture<SpenderOnboardingPage>;
let loaderService: jasmine.SpyObj<LoaderService>;
let orgUserService: jasmine.SpyObj<OrgUserService>;
let spenderOnboardingService: jasmine.SpyObj<SpenderOnboardingService>;
let orgSettingsService: jasmine.SpyObj<OrgSettingsService>;
let corporateCreditCardExpenseService: jasmine.SpyObj<CorporateCreditCardExpenseService>;
let router: jasmine.SpyObj<Router>;

beforeEach(async () => {
const loaderServiceSpy = jasmine.createSpyObj('LoaderService', ['showLoader', 'hideLoader']);
const orgUserServiceSpy = jasmine.createSpyObj('OrgUserService', ['getCurrent']);
const spenderOnboardingServiceSpy = jasmine.createSpyObj('SpenderOnboardingService', [
'getOnboardingStatus',
'skipConnectCardsStep',
'markConnectCardsStepAsComplete',
'skipSmsOptInStep',
'markSmsOptInStepAsComplete',
]);
const orgSettingsServiceSpy = jasmine.createSpyObj('OrgSettingsService', ['get']);
const corporateCreditCardExpenseServiceSpy = jasmine.createSpyObj('CorporateCreditCardExpenseService', [
'getCorporateCards',
]);
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);

await TestBed.configureTestingModule({
declarations: [SpenderOnboardingPage],
providers: [
{ provide: LoaderService, useValue: loaderServiceSpy },
{ provide: OrgUserService, useValue: orgUserServiceSpy },
{ provide: SpenderOnboardingService, useValue: spenderOnboardingServiceSpy },
{ provide: OrgSettingsService, useValue: orgSettingsServiceSpy },
{ provide: CorporateCreditCardExpenseService, useValue: corporateCreditCardExpenseServiceSpy },
{ provide: Router, useValue: routerSpy },
],
}).compileComponents();

fixture = TestBed.createComponent(SpenderOnboardingPage);
component = fixture.componentInstance;

loaderService = TestBed.inject(LoaderService) as jasmine.SpyObj<LoaderService>;
orgUserService = TestBed.inject(OrgUserService) as jasmine.SpyObj<OrgUserService>;
spenderOnboardingService = TestBed.inject(SpenderOnboardingService) as jasmine.SpyObj<SpenderOnboardingService>;
orgSettingsService = TestBed.inject(OrgSettingsService) as jasmine.SpyObj<OrgSettingsService>;
corporateCreditCardExpenseService = TestBed.inject(
CorporateCreditCardExpenseService
) as jasmine.SpyObj<CorporateCreditCardExpenseService>;
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
});

it('ionViewWillEnter(): should show loader and fetch onboarding data on ionViewWillEnter', (done) => {
loaderService.showLoader.and.resolveTo();
orgUserService.getCurrent.and.returnValue(of(extendedOrgUserResponse));
orgSettingsService.get.and.returnValue(of(orgSettingsData));
spenderOnboardingService.getOnboardingStatus.and.returnValue(of(onboardingStatusData));
corporateCreditCardExpenseService.getCorporateCards.and.returnValue(of([]));

component.ionViewWillEnter();

fixture.whenStable().then(() => {
fixture.detectChanges();

expect(loaderService.showLoader).toHaveBeenCalledTimes(1);
expect(component.userFullName).toBe('Aiyush');
expect(component.currentStep).toBe(OnboardingStep.CONNECT_CARD);
expect(component.isLoading).toBeFalse();
expect(loaderService.hideLoader).toHaveBeenCalled();
done();
});
});

it('skipOnboardingStep(): should skip the current onboarding step', () => {
component.currentStep = OnboardingStep.CONNECT_CARD;
component.skipOnboardingStep();
expect(spenderOnboardingService.skipConnectCardsStep).toHaveBeenCalled();

component.currentStep = OnboardingStep.OPT_IN;
component.skipOnboardingStep();
expect(spenderOnboardingService.skipSmsOptInStep).toHaveBeenCalled();
});

it('markStepAsComplete(): should mark the current step as complete', () => {
component.currentStep = OnboardingStep.CONNECT_CARD;
component.markStepAsComplete();
expect(spenderOnboardingService.markConnectCardsStepAsComplete).toHaveBeenCalled();

component.currentStep = OnboardingStep.OPT_IN;
component.markStepAsComplete();
expect(spenderOnboardingService.markSmsOptInStepAsComplete).toHaveBeenCalled();
});
});
Loading

0 comments on commit 35c37cc

Please sign in to comment.