Skip to content

Commit

Permalink
Merge branch 'master' into FYLE-86cvrjd0e-submit
Browse files Browse the repository at this point in the history
  • Loading branch information
bistaastha authored Jun 28, 2024
2 parents b730b6d + 3fdcbb9 commit a372543
Show file tree
Hide file tree
Showing 101 changed files with 4,364 additions and 526 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@
"@typescript-eslint/no-empty-function": ["error"],
"@typescript-eslint/no-empty-interface": ["error"],
"@typescript-eslint/no-inferrable-types": ["error"],
"no-unused-expressions": ["error"]
"no-unused-expressions": ["error"],
"no-console": ["error", { "allow": [""] }]
}
},
{
Expand Down
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"jetifier": "^2.0.0",
"launchdarkly-js-client-sdk": "^2.22.1",
"lodash": "^4.17.21",
"ng-otp-input": "^1.9.3",
"ng2-pdf-viewer": "^9.0.0",
"ngx-image-cropper": "^6.1.0",
"ngx-mask": "^13.1.15",
Expand Down
6 changes: 4 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { HAMMER_GESTURE_CONFIG, HammerGestureConfig } from '@angular/platform-br
import { PAGINATION_SIZE, DEVICE_PLATFORM } from './constants';
import { Smartlook } from '@awesome-cordova-plugins/smartlook/ngx';
import { Capacitor } from '@capacitor/core';
import { NgOtpInputModule } from 'ng-otp-input';

export class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{
overrides = {
pinch: { enable: false },
rotate: { enable: false },
};
Expand All @@ -46,6 +47,7 @@ export const MIN_SCREEN_WIDTH = new InjectionToken<number>(
HttpClientJsonpModule,
SharedModule,
HammerModule,
NgOtpInputModule,
],
providers: [
GooglePlus,
Expand Down Expand Up @@ -74,7 +76,7 @@ export const MIN_SCREEN_WIDTH = new InjectionToken<number>(
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) => () => configService.loadConfigurationData(),
useFactory: (configService: ConfigService) => (): Promise<void> => configService.loadConfigurationData(),
deps: [ConfigService, RouterAuthService, TokenService, SecureStorageService, StorageService, Sentry.TraceService],
multi: true,
},
Expand Down
6 changes: 6 additions & 0 deletions src/app/core/enums/opt-in-flow-state.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum OptInFlowState {
MOBILE_INPUT = 'MOBILE_INPUT',
OTP_VERIFICATION = 'OTP_VERIFICATION',
SUCCESS = 'SUCCESS',
ERROR = 'ERROR',
}
172 changes: 172 additions & 0 deletions src/app/core/guards/opt-in.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { TestBed } from '@angular/core/testing';

import { OptInGuard } from './opt-in.guard';
import { UtilityService } from '../services/utility.service';
import { ActivatedRoute, Router, RouterStateSnapshot } from '@angular/router';
import { Observable, of } from 'rxjs';

describe('OptInGuard', () => {
let guard: OptInGuard;
let utilityService: jasmine.SpyObj<UtilityService>;
let router: jasmine.SpyObj<Router>;

beforeEach(() => {
const utilityServiceSpy = jasmine.createSpyObj('UtilityService', [
'canShowOptInAfterExpenseCreation',
'canShowOptInModal',
'canShowOptInAfterAddingCard',
]);
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);

TestBed.configureTestingModule({
providers: [
{
provide: UtilityService,
useValue: utilityServiceSpy,
},
{
provide: Router,
useValue: routerSpy,
},
],
});
guard = TestBed.inject(OptInGuard);
utilityService = TestBed.inject(UtilityService) as jasmine.SpyObj<UtilityService>;
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
});

it('should be created', () => {
expect(guard).toBeTruthy();
});

describe('canActivate():', () => {
it('should return true if the current route includes "my_expenses" and the next route does not include "add_edit" and canShowOptIn is false', (done) => {
const currentRoute = 'my_expenses';
const nextRoute = 'my_dashboard';
const canShowOptIn = false;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterExpenseCreation.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterExpenseCreation).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).not.toHaveBeenCalled();
expect(res).toBeTrue();
done();
});
});

it('should return true if the current route includes "my_expenses" and the next route does not include "add_edit" and canShowOptIn is true', (done) => {
const currentRoute = 'my_expenses';
const nextRoute = 'my_dashboard';
const canShowOptIn = true;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterExpenseCreation.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterExpenseCreation).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).toHaveBeenCalledOnceWith({
feature: 'OPT_IN_POPUP_POST_EXPENSE_CREATION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
});
expect(res).toBeFalse();
done();
});
});

it('should return true if the current route includes "my_dashboard" and canShowOptIn is false', (done) => {
const currentRoute = 'my_dashboard';
const nextRoute = 'my_dashboard';
const canShowOptIn = false;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterAddingCard.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterAddingCard).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).not.toHaveBeenCalled();
expect(res).toBeTrue();
done();
});
});

it('should return true if the current route includes "my_dashboard" and canShowOptIn is true', (done) => {
const currentRoute = 'my_dashboard';
const nextRoute = 'my_dashboard';
const canShowOptIn = true;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterAddingCard.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterAddingCard).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).toHaveBeenCalledOnceWith({
feature: 'OPT_IN_POPUP_POST_CARD_ADDITION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
});
expect(res).toBeFalse();
done();
});
});

it('should return true if the current route includes "manage_corporate_cards" and canShowOptIn is false', (done) => {
const currentRoute = 'manage_corporate_cards';
const nextRoute = 'manage_corporate_cards';
const canShowOptIn = false;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterAddingCard.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterAddingCard).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).not.toHaveBeenCalled();
expect(res).toBeTrue();
done();
});
});

it('should return true if the current route includes "manage_corporate_cards" and canShowOptIn is true', (done) => {
const currentRoute = 'manage_corporate_cards';
const nextRoute = 'manage_corporate_cards';
const canShowOptIn = true;
const canShowOptInModal = true;
Object.defineProperty(router, 'routerState', { writable: true, value: { snapshot: { url: currentRoute } } });
utilityService.canShowOptInAfterAddingCard.and.returnValue(canShowOptIn);
utilityService.canShowOptInModal.and.returnValue(of(canShowOptInModal));

const canActivate = guard.canActivate(new ActivatedRoute().snapshot, {
url: nextRoute,
} as RouterStateSnapshot) as Observable<boolean>;
canActivate.subscribe((res) => {
expect(utilityService.canShowOptInAfterAddingCard).toHaveBeenCalledTimes(1);
expect(utilityService.canShowOptInModal).toHaveBeenCalledOnceWith({
feature: 'OPT_IN_POPUP_POST_CARD_ADDITION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
});
expect(res).toBeFalse();
done();
});
});
});
});
69 changes: 69 additions & 0 deletions src/app/core/guards/opt-in.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable, map, of } from 'rxjs';
import { UtilityService } from '../services/utility.service';

@Injectable({
providedIn: 'root',
})
export class OptInGuard implements CanActivate {
constructor(private utilityService: UtilityService, private router: Router) {}

canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const currentRoute = this.router.routerState.snapshot.url;
const nextRoute = state.url;

if (currentRoute.includes('my_expenses') && !nextRoute.includes('add_edit')) {
const canShowOptInPostExpenseCreation = this.utilityService.canShowOptInAfterExpenseCreation();

if (!canShowOptInPostExpenseCreation) {
return of(true);
} else {
const optInModalPostExpenseCreationFeatureConfig = {
feature: 'OPT_IN_POPUP_POST_EXPENSE_CREATION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
};
return this.utilityService
.canShowOptInModal(optInModalPostExpenseCreationFeatureConfig)
.pipe(map((canShowOptInModal) => !canShowOptInModal));
}
}

if (currentRoute.includes('my_dashboard')) {
const canShowOptInPostCardAddition = this.utilityService.canShowOptInAfterAddingCard();

if (!canShowOptInPostCardAddition) {
return of(true);
} else {
const optInModalPostCardAdditionFeatureConfig = {
feature: 'OPT_IN_POPUP_POST_CARD_ADDITION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
};
return this.utilityService
.canShowOptInModal(optInModalPostCardAdditionFeatureConfig)
.pipe(map((canShowOptInModal) => !canShowOptInModal));
}
}

if (currentRoute.includes('manage_corporate_cards')) {
const canShowOptInPostCardAddition = this.utilityService.canShowOptInAfterAddingCard();

if (!canShowOptInPostCardAddition) {
return of(true);
} else {
const optInModalPostCardAdditionFeatureConfig = {
feature: 'OPT_IN_POPUP_POST_CARD_ADDITION',
key: 'OPT_IN_POPUP_SHOWN_COUNT',
};
return this.utilityService
.canShowOptInModal(optInModalPostCardAdditionFeatureConfig)
.pipe(map((canShowOptInModal) => !canShowOptInModal));
}
}

return true;
}
}
1 change: 0 additions & 1 deletion src/app/core/mock-data/advance-platform.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const advancePlatform: PlatformApiResponse<AdvancesPlatform[]> = deepFree
project_id: '317383',
purpose: 'testing',
seq_num: 'A/2024/03/T/1',
settlement_id: null,
source: 'WEBAPP',
updated_at: new Date('2024-03-11T08:32:40.861889+00:00'),
user: {
Expand Down
4 changes: 0 additions & 4 deletions src/app/core/mock-data/api-reports.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export const apiReportRes: ApiV2Response<ExtendedReport> = deepFreeze({
rp_reimbursed_at: null,
rp_risk_state: null,
rp_risk_state_expense_count: null,
rp_settlement_id: null,
rp_source: 'MOBILE',
rp_state: 'DRAFT',
rp_submitted_at: null,
Expand Down Expand Up @@ -100,7 +99,6 @@ export const apiReportRes: ApiV2Response<ExtendedReport> = deepFreeze({
rp_reimbursed_at: null,
rp_risk_state: null,
rp_risk_state_expense_count: null,
rp_settlement_id: null,
rp_source: 'WEBAPP',
rp_state: 'APPROVER_INQUIRY',
rp_submitted_at: new Date('2023-01-17T06:34:59.523'),
Expand Down Expand Up @@ -157,7 +155,6 @@ export const apiReportRes: ApiV2Response<ExtendedReport> = deepFreeze({
rp_reimbursed_at: null,
rp_risk_state: null,
rp_risk_state_expense_count: null,
rp_settlement_id: null,
rp_source: 'WORKFLOWS',
rp_state: 'APPROVED',
rp_submitted_at: new Date('2023-01-13T07:29:01.135'),
Expand Down Expand Up @@ -214,7 +211,6 @@ export const apiReportRes: ApiV2Response<ExtendedReport> = deepFreeze({
rp_reimbursed_at: null,
rp_risk_state: null,
rp_risk_state_expense_count: null,
rp_settlement_id: null,
rp_source: 'WORKFLOWS',
rp_state: 'APPROVER_PENDING',
rp_submitted_at: new Date('2022-12-26T07:29:01.743'),
Expand Down
2 changes: 0 additions & 2 deletions src/app/core/mock-data/cc-transaction.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export const ccTransactionData: corporateCardTransaction = deepFreeze({
},
org_id: 'oroLKHBYQVvj',
post_date: null,
settlement_id: null,
spent_at: '2018-07-04T00:00:00+00:00',
statement_id: 'stmt2K9aLunGU4',
transaction_status: TransactionStatus.PENDING,
Expand Down Expand Up @@ -185,7 +184,6 @@ export const ccTransactionData1: corporateCardTransaction = deepFreeze({
},
org_id: 'oroLKHBYQVvj',
post_date: null,
settlement_id: null,
spent_at: '2018-06-06T00:00:00+00:00',
statement_id: 'stmt2K9aLunGU4',
updated_at: '2024-02-12T12:36:16.437742+00:00',
Expand Down
Loading

0 comments on commit a372543

Please sign in to comment.