Skip to content

Commit

Permalink
feat: Dismiss Dialog for duplicate expenses (#3175)
Browse files Browse the repository at this point in the history
* feat: Dismiss dialog for potential duplicate expenses

* minor fixes

* minor comment fixes

* removed not required model

* removed not used model file

* test: Added unit test cases for dismiss dialog (#3176)

* test: Added unit test cases for dismiss dialog

* added more test cases and fixed minor comments

---------

Co-authored-by: Devendra Singh Rana <[email protected]>

* improve unit test coverage

---------

Co-authored-by: Devendra Singh Rana <[email protected]>
  • Loading branch information
devendrafyle and Devendra Singh Rana authored Aug 27, 2024
1 parent e0be093 commit 8200b6c
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="dismiss-dialog">
<ion-content>
<ion-grid class="dismiss-dialog--grid">
<ion-row>
<ion-col>
<div class="dismiss-dialog--header">Dismiss duplicate expenses</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<div class="dismiss-dialog--body">Are you sure you want to take this action?</div>
</ion-col>
</ion-row>
<ion-row class="dismiss-dialog--cta-container">
<ion-col size="6">
<div
[ngClass]="{ 'dismiss-dialog--cancel__disabled': dismissCallInProgress }"
class="dismiss-dialog--cancel"
(click)="cancel()"
>
No, go back
</div>
</ion-col>
<ion-col size="6">
<div class="dismiss-dialog--dismiss" (click)="dismiss()" appFormButtonValidation>Yes, Dismiss</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@import '../../../../../theme/colors.scss';

.dismiss-dialog {
&--header {
font-size: 16px;
line-height: 20px;
color: $black;
font-weight: 500;
}

&--body {
font-size: 14px;
line-height: 18px;
color: $blue-black;
font-weight: 400;
margin-top: 16px;
}

&--cta-container {
margin-top: 16px;
}

&--dismiss {
display: flex;
padding: 12px 16px;
justify-content: center;
color: $pure-white;
align-items: center;
border-radius: 4px;
background: $pink-gradient;
}

&--cancel {
display: flex;
padding: 12px 16px;
justify-content: center;
align-items: center;
color: $blue-black;
&__disabled {
opacity: 0.2;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule, PopoverController } from '@ionic/angular';

import { DismissDialogComponent } from './dismiss-dialog.component';
import { FormButtonValidationDirective } from 'src/app/shared/directive/form-button-validation.directive';
import { MatIconModule } from '@angular/material/icon';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { FormsModule } from '@angular/forms';
import { of, throwError } from 'rxjs';
import { click, getElementBySelector, getTextContent } from 'src/app/core/dom-helpers';

describe('DismissDialogComponent', () => {
let component: DismissDialogComponent;
let fixture: ComponentFixture<DismissDialogComponent>;
let popoverController: jasmine.SpyObj<PopoverController>;

const dismissMethod = () => of(true);
const errMethod = () => throwError(() => new Error('error'));

beforeEach(waitForAsync(() => {
const popoverControllerSpy = jasmine.createSpyObj('PopoverController', ['dismiss']);
TestBed.configureTestingModule({
declarations: [DismissDialogComponent, FormButtonValidationDirective],
imports: [IonicModule.forRoot(), FormsModule, MatIconTestingModule, MatIconModule],
providers: [
{
provide: PopoverController,
useValue: popoverControllerSpy,
},
],
}).compileComponents();

fixture = TestBed.createComponent(DismissDialogComponent);
component = fixture.componentInstance;
popoverController = TestBed.inject(PopoverController) as jasmine.SpyObj<PopoverController>;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});

it('should display header and CTA text correctly', () => {
fixture.detectChanges();

expect(getTextContent(getElementBySelector(fixture, '.dismiss-dialog--header'))).toEqual(
'Dismiss duplicate expenses'
);
expect(getTextContent(getElementBySelector(fixture, '.dismiss-dialog--dismiss'))).toEqual('Yes, Dismiss');
});

it('cancel(): should cancel the CTA', () => {
popoverController.dismiss.and.callThrough();
component.dismissCallInProgress = false;
fixture.detectChanges();

component.cancel();
expect(popoverController.dismiss).toHaveBeenCalledTimes(1);
});

describe('dismiss():', () => {
it('should dismiss expense', (done) => {
popoverController.dismiss.and.callThrough();
component.dismissCallInProgress = false;
component.dismissMethod = dismissMethod;
fixture.detectChanges();

component.dismiss();
expect(popoverController.dismiss).toHaveBeenCalledWith({ status: 'success' });
done();
});

it('should not dismiss expenses if dismiss method throws error', (done) => {
popoverController.dismiss.and.callThrough();
component.dismissCallInProgress = false;
component.dismissMethod = errMethod;
fixture.detectChanges();

component.dismiss();
expect(popoverController.dismiss).toHaveBeenCalledWith({ status: 'error' });
done();
});
});

it('should call cancel() if button is clicked', () => {
const cancelFn = spyOn(component, 'cancel');

const cancelButton = getElementBySelector(fixture, '.dismiss-dialog--cancel') as HTMLElement;
click(cancelButton);
expect(cancelFn).toHaveBeenCalledTimes(1);
});

it('should call dismiss() if card is clicked', () => {
const dismissFn = spyOn(component, 'dismiss');

const dismissCard = getElementBySelector(fixture, '.dismiss-dialog--dismiss') as HTMLElement;
click(dismissCard);
expect(dismissFn).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Component, Input, OnInit } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { PopoverController } from '@ionic/angular';
import { catchError, finalize, map } from 'rxjs/operators';
import { of } from 'rxjs';

@Component({
selector: 'app-dismiss-dialog',
templateUrl: './dismiss-dialog.component.html',
styleUrls: ['./dismiss-dialog.component.scss'],
})
export class DismissDialogComponent implements OnInit {
@Input() dismissMethod: () => Observable<{}>;

dismissCallInProgress: boolean;

constructor(private popoverController: PopoverController) {}

ngOnInit(): void {
this.dismissCallInProgress = false;
}

cancel(): void {
if (!this.dismissCallInProgress) {
this.popoverController.dismiss();
}
}

dismiss(): void {
this.dismissCallInProgress = true;
this.dismissMethod()
.pipe(
map(() => ({ status: 'success' })),
catchError(() =>
of({
status: 'error',
})
),
finalize(() => (this.dismissCallInProgress = false))
)
.subscribe((res) => {
this.popoverController.dismiss(res);
});
}
}
3 changes: 2 additions & 1 deletion src/app/fyle/my-expenses/my-expenses.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { AddTxnToReportDialogComponent } from './add-txn-to-report-dialog/add-tx
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { DismissDialogComponent } from '../dashboard/tasks/dismiss-dialog/dismiss-dialog.component';

@NgModule({
imports: [
Expand All @@ -40,6 +41,6 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
SharedModule,
MatCheckboxModule,
],
declarations: [MyExpensesPage, AddTxnToReportDialogComponent],
declarations: [MyExpensesPage, AddTxnToReportDialogComponent, DismissDialogComponent],
})
export class MyExpensesPageModule {}
Loading

0 comments on commit 8200b6c

Please sign in to comment.