Skip to content

Commit

Permalink
fix: add ldFlag for manual flag feature (#3013)
Browse files Browse the repository at this point in the history
* add ldFlag for manual flag feature

* add test cases for isManualFlagFeatureEnabled

* increased tests code coverage

* change deprecate_manual_flagging default ldFlag val to true

* fix: Fyle 86cv9y0a4 lint errors resolved (#3022)

* minor change

* add more tests

* add more tests to launchDarklyService
  • Loading branch information
sumrender authored May 29, 2024
1 parent ee7831c commit 28abe7f
Show file tree
Hide file tree
Showing 23 changed files with 349 additions and 59 deletions.
49 changes: 49 additions & 0 deletions src/app/core/services/launch-darkly.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ describe('LaunchDarklyService', () => {
expect(launchDarklyService).toBeTruthy();
});

it('should call shutDownClient on userEventService logout', () => {
spyOn(launchDarklyService, 'shutDownClient');

userEventService.onLogout.calls.mostRecent().args[0]();
expect(launchDarklyService.shutDownClient).toHaveBeenCalledTimes(1);
});

it('isTheSameUser(): should check if the user is same', () => {
//@ts-ignore
expect(launchDarklyService.isTheSameUser(lDUser)).toBeFalse();
Expand Down Expand Up @@ -86,4 +93,46 @@ describe('LaunchDarklyService', () => {
done();
});
});

it('checkIfAndroidNegativeExpensePluginIsEnabled(): should check if android negative expense plugin is enabled', (done) => {
spyOn(launchDarklyService, 'getVariation').and.returnValue(of(true));
const key = 'android-numeric-keypad';

launchDarklyService.checkIfAndroidNegativeExpensePluginIsEnabled().subscribe((res) => {
expect(res).toBeTrue();
expect(launchDarklyService.getVariation).toHaveBeenCalledOnceWith(key, false);
done();
});
});

it('checkIfManualFlaggingFeatureIsEnabled(): should check if manual flagging feature is enabled', (done) => {
spyOn(launchDarklyService, 'getVariation').and.returnValue(of(true));
const key = 'deprecate_manual_flagging';

launchDarklyService.checkIfManualFlaggingFeatureIsEnabled().subscribe((res) => {
expect(res.value).toBeTrue();
expect(launchDarklyService.getVariation).toHaveBeenCalledOnceWith(key, true);
done();
});
});

describe('shutDownClient():', () => {
beforeEach(() => {
ldClient = jasmine.createSpyObj('LDClient', ['off', 'close']);
(launchDarklyService as any).ldClient = ldClient;
});

it('should shut down LD client if it exists', () => {
launchDarklyService.shutDownClient();
expect(ldClient.off).toHaveBeenCalledWith('initialized', jasmine.any(Function), launchDarklyService);
expect(ldClient.off).toHaveBeenCalledWith('change', jasmine.any(Function), launchDarklyService);
expect(ldClient.close).toHaveBeenCalled();
expect((launchDarklyService as any).ldClient).toBeNull();
});

it('should not throw error if LD client does not exist', () => {
(launchDarklyService as any).ldClient = null;
expect(() => launchDarklyService.shutDownClient()).not.toThrow();
});
});
});
4 changes: 4 additions & 0 deletions src/app/core/services/launch-darkly.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export class LaunchDarklyService {
return this.getVariation('android-numeric-keypad', false);
}

checkIfManualFlaggingFeatureIsEnabled(): Observable<{ value: boolean }> {
return this.getVariation('deprecate_manual_flagging', true).pipe(map((value) => ({ value })));
}

// Checks if the passed in user is the same as the user which is initialized to LaunchDarkly (if any)
private isTheSameUser(newUser: LDClient.LDUser): boolean {
const previousUser = this.ldClient?.getUser();
Expand Down
23 changes: 13 additions & 10 deletions src/app/fyle/my-reports/my-reports.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,19 @@

<ng-container *ngIf="!isLoading; else loading">
<ng-container *ngIf="(simplifyReportsSettings$ | async) as simplifyReportsSettings; else loading">
<div *ngFor="let report of myReports$ | async as list; let i = index">
<app-reports-card
[report]="report"
[prevDate]="list[i-1]?.created_at"
[simplifyReportsEnabled]="simplifyReportsSettings.enabled"
(gotoReport)="onReportClick($event)"
(deleteReport)="onDeleteReportClick($event)"
(viewComments)="onViewCommentsClick()"
></app-reports-card>
</div>
<ng-container *ngIf="(isManualFlagFeatureEnabled$ | async) as isManualFlagFeatureEnabled; else loading">
<div *ngFor="let report of myReports$ | async as list; let i = index">
<app-reports-card
[report]="report"
[prevDate]="list[i-1]?.created_at"
[simplifyReportsEnabled]="simplifyReportsSettings.enabled"
[isManualFlagFeatureEnabled]="isManualFlagFeatureEnabled.value"
(gotoReport)="onReportClick($event)"
(deleteReport)="onDeleteReportClick($event)"
(viewComments)="onViewCommentsClick()"
></app-reports-card>
</div>
</ng-container>
</ng-container>
</ng-container>
<ng-container *ngIf="isConnected$|async">
Expand Down
15 changes: 15 additions & 0 deletions src/app/fyle/my-reports/my-reports.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import { expectedReportsSinglePage } from 'src/app/core/mock-data/platform-repor
import { SpenderReportsService } from 'src/app/core/services/platform/v1/spender/reports.service';
import { ReportState as PlatformReportState } from 'src/app/core/models/platform/v1/report.model';
import { ReportState } from 'src/app/shared/pipes/report-state.pipe';
import { LaunchDarklyService } from 'src/app/core/services/launch-darkly.service';

describe('MyReportsPage', () => {
let component: MyReportsPage;
Expand All @@ -106,6 +107,7 @@ describe('MyReportsPage', () => {
let modalController: jasmine.SpyObj<ModalController>;
let inputElement: HTMLInputElement;
let spenderReportsService: jasmine.SpyObj<SpenderReportsService>;
let launchDarklyService: jasmine.SpyObj<LaunchDarklyService>;

beforeEach(waitForAsync(() => {
const tasksServiceSpy = jasmine.createSpyObj('TasksService', ['getReportsTaskCount']);
Expand Down Expand Up @@ -146,6 +148,9 @@ describe('MyReportsPage', () => {
'getReportsCount',
'getReportsByParams',
]);
const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', [
'checkIfManualFlaggingFeatureIsEnabled',
]);

TestBed.configureTestingModule({
declarations: [MyReportsPage, ReportState],
Expand Down Expand Up @@ -195,6 +200,10 @@ describe('MyReportsPage', () => {
provide: SpenderReportsService,
useValue: spenderReportsServiceSpy,
},
{
provide: LaunchDarklyService,
useValue: launchDarklyServiceSpy,
},
ReportState,
],
schemas: [NO_ERRORS_SCHEMA],
Expand Down Expand Up @@ -222,6 +231,7 @@ describe('MyReportsPage', () => {
trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>;
modalController = TestBed.inject(ModalController) as jasmine.SpyObj<ModalController>;
spenderReportsService = TestBed.inject(SpenderReportsService) as jasmine.SpyObj<SpenderReportsService>;
launchDarklyService = TestBed.inject(LaunchDarklyService) as jasmine.SpyObj<LaunchDarklyService>;
}));

it('should create', () => {
Expand All @@ -245,6 +255,7 @@ describe('MyReportsPage', () => {
spenderReportsService.getReportsByParams.and.returnValue(of(paginatedPipeValue));
orgSettingsService.get.and.returnValue(of(orgSettingsRes));
expensesService.getExpenseStats.and.returnValue(of(completeStats1));
launchDarklyService.checkIfManualFlaggingFeatureIsEnabled.and.returnValue(of({ value: true }));

component.simpleSearchInput = fixture.debugElement.query(By.css('.my-reports--simple-search-input'));

Expand All @@ -270,6 +281,10 @@ describe('MyReportsPage', () => {
expect(currency).toEqual('USD');
});

component.isManualFlagFeatureEnabled$.subscribe((res) => {
expect(res.value).toBeTrue();
});

expect(component.simpleSearchInput.nativeElement.value).toBe('');

inputElement.value = 'example';
Expand Down
8 changes: 7 additions & 1 deletion src/app/fyle/my-reports/my-reports.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { SpenderReportsService } from 'src/app/core/services/platform/v1/spender
import { ReportsQueryParams } from 'src/app/core/models/platform/v1/reports-query-params.model';
import { Report } from 'src/app/core/models/platform/v1/report.model';
import { PlatformApiResponse } from 'src/app/core/models/platform/platform-api-response.model';
import { LaunchDarklyService } from 'src/app/core/services/launch-darkly.service';

type Filters = Partial<{
state: string | string[];
Expand Down Expand Up @@ -112,6 +113,8 @@ export class MyReportsPage {

nonReimbursableOrg$: Observable<boolean>;

isManualFlagFeatureEnabled$: Observable<{ value: boolean }>;

constructor(
private networkService: NetworkService,
private loaderService: LoaderService,
Expand All @@ -128,7 +131,8 @@ export class MyReportsPage {
private orgSettingsService: OrgSettingsService,
private reportStatePipe: ReportState,
private expensesService: ExpensesService,
private spenderReportsService: SpenderReportsService
private spenderReportsService: SpenderReportsService,
private launchDarklyService: LaunchDarklyService
) {}

get HeaderState(): typeof HeaderState {
Expand All @@ -147,6 +151,8 @@ export class MyReportsPage {
this.isLoading = true;
this.setupNetworkWatcher();

this.isManualFlagFeatureEnabled$ = this.launchDarklyService.checkIfManualFlaggingFeatureIsEnabled();

this.searchText = '';
this.navigateBack = !!this.activatedRoute.snapshot.params.navigateBack;
this.acc = [];
Expand Down
29 changes: 17 additions & 12 deletions src/app/fyle/my-view-report/my-view-report.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,23 @@
<div *ngIf="!isExpensesLoading && report.num_expenses > 0">
<div class="view-reports--divider"></div>
<div class="view-reports--expenses-card-block">
<div *ngFor="let expense of expenses$|async as list; let i = index;">
<app-expense-card-v2
[expense]="expense"
[expenseIndex]="i"
[previousExpenseTxnDate]="list[i-1]?.spent_at"
[previousExpenseCreatedAt]="list[i-1]?.created_at"
(goToTransaction)="goToTransaction($event)"
[isFromReports]="true"
[isFromViewReports]="true"
>
</app-expense-card-v2>
</div>
<ng-container
*ngIf="(isManualFlagFeatureEnabled$ | async) as isManualFlagFeatureEnabled; else ExpensesLoader"
>
<div *ngFor="let expense of expenses$|async as list; let i = index;">
<app-expense-card-v2
[expense]="expense"
[expenseIndex]="i"
[previousExpenseTxnDate]="list[i-1]?.spent_at"
[previousExpenseCreatedAt]="list[i-1]?.created_at"
(goToTransaction)="goToTransaction($event)"
[isFromReports]="true"
[isFromViewReports]="true"
[isManualFlagFeatureEnabled]="isManualFlagFeatureEnabled.value"
>
</app-expense-card-v2>
</div>
</ng-container>
</div>
<ng-template #ExpensesLoader>
<ion-spinner name="crescent"></ion-spinner>
Expand Down
11 changes: 11 additions & 0 deletions src/app/fyle/my-view-report/my-view-report.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import { ShareReportComponent } from './share-report/share-report.component';
import { EditReportNamePopoverComponent } from './edit-report-name-popover/edit-report-name-popover.component';
import { SpenderReportsService } from 'src/app/core/services/platform/v1/spender/reports.service';
import { expectedSentBackResponseSingularReport } from 'src/app/core/mock-data/report-stats.data';
import { LaunchDarklyService } from 'src/app/core/services/launch-darkly.service';

describe('MyViewReportPage', () => {
let component: MyViewReportPage;
Expand All @@ -86,6 +87,7 @@ describe('MyViewReportPage', () => {
let refinerService: jasmine.SpyObj<RefinerService>;
let orgSettingsService: jasmine.SpyObj<OrgSettingsService>;
let spenderReportsService: jasmine.SpyObj<SpenderReportsService>;
let launchDarklyService: jasmine.SpyObj<LaunchDarklyService>;

beforeEach(waitForAsync(() => {
const reportServiceSpy = jasmine.createSpyObj('ReportService', [
Expand Down Expand Up @@ -133,6 +135,9 @@ describe('MyViewReportPage', () => {
'permissions',
'postComment',
]);
const launchDarklyServiceSpy = jasmine.createSpyObj('LaunchDarklyService', [
'checkIfManualFlaggingFeatureIsEnabled',
]);

TestBed.configureTestingModule({
declarations: [
Expand Down Expand Up @@ -224,6 +229,7 @@ describe('MyViewReportPage', () => {
useValue: spenderReportsServiceSpy,
},
{ provide: NavController, useValue: { push: NavController.prototype.back } },
{ provide: LaunchDarklyService, useValue: launchDarklyServiceSpy },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
}).compileComponents();
Expand All @@ -246,6 +252,7 @@ describe('MyViewReportPage', () => {
refinerService = TestBed.inject(RefinerService) as jasmine.SpyObj<RefinerService>;
orgSettingsService = TestBed.inject(OrgSettingsService) as jasmine.SpyObj<OrgSettingsService>;
spenderReportsService = TestBed.inject(SpenderReportsService) as jasmine.SpyObj<SpenderReportsService>;
launchDarklyService = TestBed.inject(LaunchDarklyService) as jasmine.SpyObj<LaunchDarklyService>;

component.report$ = of(platformReportData);
component.canEdit$ = of(true);
Expand Down Expand Up @@ -328,6 +335,7 @@ describe('MyViewReportPage', () => {
spenderReportsService.permissions.and.returnValue(of(apiReportPermissions));
expensesService.getAllExpenses.and.returnValue(of([expenseData, expenseData]));
orgSettingsService.get.and.returnValue(of(orgSettingsData));
launchDarklyService.checkIfManualFlaggingFeatureIsEnabled.and.returnValue(of({ value: true }));
spyOn(component, 'getSimplifyReportSettings').and.returnValue(true);

component.ionViewWillEnter();
Expand All @@ -342,6 +350,9 @@ describe('MyViewReportPage', () => {
component.report$.subscribe((res) => {
expect(res).toEqual(report);
});
component.isManualFlagFeatureEnabled$.subscribe((res) => {
expect(res.value).toBeTrue();
});
expect(component.systemComments).toEqual(systemExtendedComments);
expect(component.type).toEqual(component.objectType.substring(0, component.objectType.length - 1));

Expand Down
8 changes: 7 additions & 1 deletion src/app/fyle/my-view-report/my-view-report.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { ReportPermissions } from 'src/app/core/models/report-permissions.model'
import { ExtendedComment } from 'src/app/core/models/platform/v1/extended-comment.model';
import { Comment } from 'src/app/core/models/platform/v1/comment.model';

import { LaunchDarklyService } from 'src/app/core/services/launch-darkly.service';
@Component({
selector: 'app-my-view-report',
templateUrl: './my-view-report.page.html',
Expand Down Expand Up @@ -112,6 +113,8 @@ export class MyViewReportPage {

hardwareBackButtonAction: Subscription;

isManualFlagFeatureEnabled$: Observable<{ value: boolean }>;

constructor(
private activatedRoute: ActivatedRoute,
private reportService: ReportService,
Expand All @@ -130,7 +133,8 @@ export class MyViewReportPage {
private refinerService: RefinerService,
private orgSettingsService: OrgSettingsService,
private platformHandlerService: PlatformHandlerService,
private spenderReportsService: SpenderReportsService
private spenderReportsService: SpenderReportsService,
private launchDarklyService: LaunchDarklyService
) {}

get Segment(): typeof ReportPageSegment {
Expand Down Expand Up @@ -224,6 +228,8 @@ export class MyViewReportPage {
this.reportId = this.activatedRoute.snapshot.params.id as string;
this.navigateBack = !!this.activatedRoute.snapshot.params.navigateBack;

this.isManualFlagFeatureEnabled$ = this.launchDarklyService.checkIfManualFlaggingFeatureIsEnabled();

this.segmentValue = ReportPageSegment.EXPENSES;

this.report$ = this.loadReportDetails$.pipe(
Expand Down
11 changes: 11 additions & 0 deletions src/app/fyle/team-reports/team-reports-1.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
import { tasksQueryParamsParams } from 'src/app/core/mock-data/get-tasks-query-params.data';
import { getTeamReportsParams1, getTeamReportsParams2 } from 'src/app/core/mock-data/api-params.data';
import { GetTasksQueryParamsWithFilters } from 'src/app/core/models/get-tasks-query-params-with-filters.model';
import { LaunchDarklyService } from 'src/app/core/services/launch-darkly.service';
import { expectedReportsSinglePage } from 'src/app/core/mock-data/platform-report.data';
import { SpenderReportsService } from 'src/app/core/services/platform/v1/spender/reports.service';
import { ApproverReportsService } from 'src/app/core/services/platform/v1/approver/reports.service';
Expand All @@ -53,6 +54,7 @@ export function TestCases1(getTestBed) {
let approverReportsService: jasmine.SpyObj<ApproverReportsService>;
let authService: jasmine.SpyObj<AuthService>;
let inputElement: HTMLInputElement;
let launchDarklyService: jasmine.SpyObj<LaunchDarklyService>;

beforeEach(waitForAsync(() => {
const TestBed = getTestBed();
Expand All @@ -71,6 +73,7 @@ export function TestCases1(getTestBed) {
apiV2Service = TestBed.inject(ApiV2Service) as jasmine.SpyObj<ApiV2Service>;
tasksService = TestBed.inject(TasksService) as jasmine.SpyObj<TasksService>;
orgSettingsService = TestBed.inject(OrgSettingsService) as jasmine.SpyObj<OrgSettingsService>;
launchDarklyService = TestBed.inject(LaunchDarklyService) as jasmine.SpyObj<LaunchDarklyService>;
approverReportsService = TestBed.inject(ApproverReportsService) as jasmine.SpyObj<ApproverReportsService>;
authService = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
component.eou$ = of(apiEouRes);
Expand Down Expand Up @@ -113,6 +116,7 @@ export function TestCases1(getTestBed) {
mockAddNewFiltersToParams.and.returnValue(mockTasksQuery);
spyOn(component, 'generateFilterPills').and.returnValue(creditTxnFilterPill);
spyOn(component, 'clearFilters');
launchDarklyService.checkIfManualFlaggingFeatureIsEnabled.and.returnValue(of({ value: true }));
});

it('should set navigateBack to true if navigate_back is defined in activatedRoute.snapshot.params', () => {
Expand All @@ -121,6 +125,13 @@ export function TestCases1(getTestBed) {
expect(component.navigateBack).toBeTrue();
});

it('should set isManualFlagFeatureEnabled$ from launchDarklyService ', () => {
component.ionViewWillEnter();
component.isManualFlagFeatureEnabled$.subscribe((res) => {
expect(res.value).toBeTrue();
});
});

it('should set navigateBack to false if navigate_back is undefined in activatedRoute.snapshot.params', () => {
component.navigateBack = true;
activatedRoute.snapshot.params.navigate_back = undefined;
Expand Down
Loading

0 comments on commit 28abe7f

Please sign in to comment.