Skip to content

Commit 79bede5

Browse files
test: unit test the intacct export log pages (#989)
* test: unit test intacct export log root component * fix: page size change not updating localstorage Currently the page size saved in localstorage does not update at all in intacct export logs. After this change, we store the new page size to localstorage on page size being updated * fix: `selectedDateFilter` default type * test: intacct completed export log component * test: intacct skip export log component * fix: page size change not updating localstorage Currently the page size saved in localstorage does not update at all in intacct skipped export logs. After this change, we store the new page size to localstorage on page size being updated * fix: default types of `searchQuery` and `selectedDateFilter`
1 parent b2c0674 commit 79bede5

File tree

7 files changed

+393
-24
lines changed

7 files changed

+393
-24
lines changed

src/app/core/services/common/export-log.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class ExportLogService {
2323
private workspaceService: WorkspaceService
2424
) { }
2525

26-
getSkippedExpenses(limit: number, offset: number, selectedDateFilter: SelectedDateFilter | null, query: string | null, appName?:string): Observable<SkipExportLogResponse> {
26+
getSkippedExpenses(limit: number, offset: number, selectedDateFilter?: SelectedDateFilter | null, query?: string | null, appName?:string): Observable<SkipExportLogResponse> {
2727
const workspaceId = this.workspaceService.getWorkspaceId();
2828
const params: SkipExportParam = {
2929
limit,
@@ -54,7 +54,7 @@ export class ExportLogService {
5454

5555
}
5656

57-
getExpenseGroups(state: TaskLogState, limit: number, offset: number, selectedDateFilter: SelectedDateFilter | null, exportedAt?: string | null, query?: string | null, appName?: string): Observable<ExpenseGroupResponse> {
57+
getExpenseGroups(state: TaskLogState, limit: number, offset: number, selectedDateFilter?: SelectedDateFilter | null, exportedAt?: string | null, query?: string | null, appName?: string): Observable<ExpenseGroupResponse> {
5858
const params: ExpenseGroupParam = {
5959
limit,
6060
offset
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,143 @@
1-
import { ComponentFixture, TestBed } from '@angular/core/testing';
2-
1+
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
2+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
3+
import { of } from 'rxjs';
34
import { IntacctCompletedExportLogComponent } from './intacct-completed-export-log.component';
5+
import { TrackingService } from 'src/app/core/services/integration/tracking.service';
6+
import { ExportLogService } from 'src/app/core/services/common/export-log.service';
7+
import { PaginatorService } from 'src/app/core/services/common/paginator.service';
8+
import { UserService } from 'src/app/core/services/misc/user.service';
9+
import { mockExpenseGroupResponse, mockPaginator } from '../../../intacct.fixture';
10+
import { PaginatorPage, TaskLogState } from 'src/app/core/models/enum/enum.model';
11+
import { MinimalUser } from 'src/app/core/models/db/user.model';
12+
import { SharedModule } from 'src/app/shared/shared.module';
413

5-
xdescribe('IntacctCompletedExportLogComponent', () => {
14+
describe('IntacctCompletedExportLogComponent', () => {
615
let component: IntacctCompletedExportLogComponent;
716
let fixture: ComponentFixture<IntacctCompletedExportLogComponent>;
17+
let exportLogService: jasmine.SpyObj<ExportLogService>;
18+
let trackingService: jasmine.SpyObj<TrackingService>;
19+
let paginatorService: jasmine.SpyObj<PaginatorService>;
20+
let userService: jasmine.SpyObj<UserService>;
821

922
beforeEach(async () => {
23+
const exportLogServiceSpy = jasmine.createSpyObj('ExportLogService', ['getExpenseGroups']);
24+
const trackingServiceSpy = jasmine.createSpyObj('TrackingService', ['onDateFilter']);
25+
const paginatorServiceSpy = jasmine.createSpyObj('PaginatorService', ['getPageSize', 'storePageSize']);
26+
const userServiceSpy = jasmine.createSpyObj('UserService', ['getUserProfile']);
27+
1028
await TestBed.configureTestingModule({
11-
declarations: [ IntacctCompletedExportLogComponent ]
12-
})
13-
.compileComponents();
29+
declarations: [ IntacctCompletedExportLogComponent ],
30+
imports: [ ReactiveFormsModule, SharedModule ],
31+
providers: [
32+
FormBuilder,
33+
{ provide: ExportLogService, useValue: exportLogServiceSpy },
34+
{ provide: TrackingService, useValue: trackingServiceSpy },
35+
{ provide: PaginatorService, useValue: paginatorServiceSpy },
36+
{ provide: UserService, useValue: userServiceSpy }
37+
]
38+
}).compileComponents();
39+
40+
exportLogService = TestBed.inject(ExportLogService) as jasmine.SpyObj<ExportLogService>;
41+
trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>;
42+
paginatorService = TestBed.inject(PaginatorService) as jasmine.SpyObj<PaginatorService>;
43+
userService = TestBed.inject(UserService) as jasmine.SpyObj<UserService>;
44+
45+
userService.getUserProfile.and.returnValue({ org_id: 'ORG123' } as MinimalUser);
46+
paginatorService.getPageSize.and.returnValue(mockPaginator);
47+
exportLogService.getExpenseGroups.and.returnValue(of(mockExpenseGroupResponse));
1448

1549
fixture = TestBed.createComponent(IntacctCompletedExportLogComponent);
1650
component = fixture.componentInstance;
17-
fixture.detectChanges();
1851
});
1952

53+
2054
it('should create', () => {
2155
expect(component).toBeTruthy();
2256
});
23-
});
57+
58+
it('should initialize component and load data', () => {
59+
component.ngOnInit();
60+
expect(component.limit).toBe(mockPaginator.limit);
61+
expect(component.offset).toBe(mockPaginator.offset);
62+
expect(component.isLoading).toBeFalse();
63+
expect(component.totalCount).toBe(mockExpenseGroupResponse.count);
64+
expect(component.filteredAccountingExports.length).toBe(mockExpenseGroupResponse.results.length);
65+
expect(component.filteredAccountingExports).toEqual(component.accountingExports);
66+
});
67+
68+
it('should handle page size changes', () => {
69+
const newLimit = 20;
70+
component.pageSizeChanges(newLimit);
71+
expect(component.limit).toBe(newLimit);
72+
expect(component.currentPage).toBe(1);
73+
expect(paginatorService.storePageSize).toHaveBeenCalledWith(PaginatorPage.EXPORT_LOG, newLimit);
74+
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
75+
});
76+
77+
it('should handle page changes', () => {
78+
fixture.detectChanges();
79+
component.pageChanges(10);
80+
expect(component.offset).toBe(10);
81+
expect(component.currentPage).toBe(2);
82+
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
83+
});
84+
85+
it('should handle simple search', fakeAsync(() => {
86+
const searchQuery = 'test query';
87+
fixture.detectChanges();
88+
component.handleSimpleSearch(searchQuery);
89+
tick(1000);
90+
expect(component.searchQuery).toBe(searchQuery);
91+
expect(component.offset).toBe(0);
92+
expect(component.currentPage).toBe(1);
93+
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
94+
}));
95+
96+
it('should open expense in Fyle', () => {
97+
const expenseId = 'exp123';
98+
spyOn(window, 'open');
99+
component.openExpenseinFyle(expenseId);
100+
expect(window.open).toHaveBeenCalledWith(jasmine.stringContaining(expenseId), '_blank');
101+
});
102+
103+
it('should handle date filter changes', fakeAsync(() => {
104+
component.ngOnInit();
105+
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
106+
component.exportLogForm.controls.start.setValue(dateRange);
107+
tick(10);
108+
expect(component.selectedDateFilter).toEqual({
109+
startDate: dateRange[0],
110+
endDate: dateRange[1]
111+
});
112+
expect(component.isDateSelected).toBeTrue();
113+
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
114+
expect(component.hideCalendar).toBeFalse();
115+
}));
116+
117+
it('should clear date filter when null is set', fakeAsync(() => {
118+
fixture.detectChanges();
119+
component.exportLogForm.controls.start.setValue(null);
120+
tick(10);
121+
expect(component.selectedDateFilter).toBeNull();
122+
expect(component.isDateSelected).toBeFalse();
123+
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
124+
}));
125+
126+
it('should call getExpenseGroups with correct parameters', () => {
127+
component.ngOnInit();
128+
expect(exportLogService.getExpenseGroups).toHaveBeenCalledWith(
129+
TaskLogState.COMPLETE,
130+
mockPaginator.limit,
131+
mockPaginator.offset,
132+
undefined,
133+
null,
134+
undefined
135+
);
136+
});
137+
138+
it('should track date filter', () => {
139+
const dateFilter = { startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') };
140+
(component as any).trackDateFilter('custom', dateFilter);
141+
expect(trackingService.onDateFilter).toHaveBeenCalledWith(jasmine.any(String), jasmine.objectContaining(dateFilter));
142+
});
143+
});

src/app/integrations/intacct/intacct-main/intacct-export-log/intacct-completed-export-log/intacct-completed-export-log.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class IntacctCompletedExportLogComponent implements OnInit {
4242

4343
dateOptions: DateFilter[] = AccountingExportModel.getDateOptionsV2();
4444

45-
selectedDateFilter: SelectedDateFilter | null;
45+
selectedDateFilter?: SelectedDateFilter | null;
4646

4747
exportLogForm: FormGroup;
4848

src/app/integrations/intacct/intacct-main/intacct-export-log/intacct-export-log.component.spec.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
33
import { IntacctExportLogComponent } from './intacct-export-log.component';
44
import { FormBuilder } from '@angular/forms';
55
import { HttpClientTestingModule } from '@angular/common/http/testing';
6+
import { provideRouter, Router } from '@angular/router';
67

7-
xdescribe('IntacctExportLogComponent', () => {
8+
describe('IntacctExportLogComponent', () => {
89
let component: IntacctExportLogComponent;
910
let fixture: ComponentFixture<IntacctExportLogComponent>;
11+
let router: Router;
1012

1113
beforeEach(async () => {
1214
await TestBed.configureTestingModule({
1315
imports: [HttpClientTestingModule],
1416
declarations: [ IntacctExportLogComponent ],
15-
providers: [ FormBuilder ]
17+
providers: [ FormBuilder, provideRouter([]) ]
1618
})
1719
.compileComponents();
1820

21+
router = TestBed.inject(Router);
22+
spyOn(router, 'navigateByUrl');
23+
1924
fixture = TestBed.createComponent(IntacctExportLogComponent);
2025
component = fixture.componentInstance;
2126
fixture.detectChanges();
@@ -24,4 +29,9 @@ xdescribe('IntacctExportLogComponent', () => {
2429
it('should create', () => {
2530
expect(component).toBeTruthy();
2631
});
32+
33+
it('should navigate to completed export log', () => {
34+
expect(component.activeModule).toEqual(component.modules[0]);
35+
expect(router.navigateByUrl).toHaveBeenCalledOnceWith('/integrations/intacct/main/export_log/complete');
36+
});
2737
});
Lines changed: 128 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,143 @@
1-
import { ComponentFixture, TestBed } from '@angular/core/testing';
2-
1+
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
2+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
3+
import { of } from 'rxjs';
34
import { IntacctSkipExportLogComponent } from './intacct-skip-export-log.component';
5+
import { TrackingService } from 'src/app/core/services/integration/tracking.service';
6+
import { ExportLogService } from 'src/app/core/services/common/export-log.service';
7+
import { PaginatorService } from 'src/app/core/services/si/si-core/paginator.service';
8+
import { UserService } from 'src/app/core/services/misc/user.service';
9+
import { mockSkipExportLogResponse, mockPaginator } from '../../../intacct.fixture';
10+
import { PaginatorPage } from 'src/app/core/models/enum/enum.model';
11+
import { MinimalUser } from 'src/app/core/models/db/user.model';
12+
import { SharedModule } from 'src/app/shared/shared.module';
413

5-
xdescribe('SkipExportLogComponent', () => {
14+
describe('IntacctSkipExportLogComponent', () => {
615
let component: IntacctSkipExportLogComponent;
716
let fixture: ComponentFixture<IntacctSkipExportLogComponent>;
17+
let exportLogService: jasmine.SpyObj<ExportLogService>;
18+
let trackingService: jasmine.SpyObj<TrackingService>;
19+
let paginatorService: jasmine.SpyObj<PaginatorService>;
20+
let userService: jasmine.SpyObj<UserService>;
821

922
beforeEach(async () => {
23+
const exportLogServiceSpy = jasmine.createSpyObj('ExportLogService', ['getSkippedExpenses']);
24+
const trackingServiceSpy = jasmine.createSpyObj('TrackingService', ['onDateFilter']);
25+
const paginatorServiceSpy = jasmine.createSpyObj('PaginatorService', ['getPageSize', 'storePageSize']);
26+
const userServiceSpy = jasmine.createSpyObj('UserService', ['getUserProfile']);
27+
1028
await TestBed.configureTestingModule({
11-
declarations: [ IntacctSkipExportLogComponent ]
12-
})
13-
.compileComponents();
29+
imports: [ ReactiveFormsModule, SharedModule ],
30+
declarations: [ IntacctSkipExportLogComponent ],
31+
providers: [
32+
FormBuilder,
33+
{ provide: ExportLogService, useValue: exportLogServiceSpy },
34+
{ provide: TrackingService, useValue: trackingServiceSpy },
35+
{ provide: PaginatorService, useValue: paginatorServiceSpy },
36+
{ provide: UserService, useValue: userServiceSpy }
37+
]
38+
}).compileComponents();
39+
40+
exportLogService = TestBed.inject(ExportLogService) as jasmine.SpyObj<ExportLogService>;
41+
trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>;
42+
paginatorService = TestBed.inject(PaginatorService) as jasmine.SpyObj<PaginatorService>;
43+
userService = TestBed.inject(UserService) as jasmine.SpyObj<UserService>;
44+
});
1445

46+
beforeEach(() => {
1547
fixture = TestBed.createComponent(IntacctSkipExportLogComponent);
1648
component = fixture.componentInstance;
17-
fixture.detectChanges();
49+
userService.getUserProfile.and.returnValue({ org_id: 'ORG123' } as MinimalUser);
50+
paginatorService.getPageSize.and.returnValue(mockPaginator);
51+
exportLogService.getSkippedExpenses.and.returnValue(of(mockSkipExportLogResponse));
1852
});
1953

2054
it('should create', () => {
2155
expect(component).toBeTruthy();
2256
});
23-
});
57+
58+
it('should initialize component and load data', () => {
59+
component.ngOnInit();
60+
expect(component.limit).toBe(mockPaginator.limit);
61+
expect(component.offset).toBe(mockPaginator.offset);
62+
expect(component.isLoading).toBeFalse();
63+
expect(component.totalCount).toBe(mockSkipExportLogResponse.count);
64+
expect(component.filteredExpenses.length).toBe(mockSkipExportLogResponse.results.length);
65+
expect(component.filteredExpenses).toEqual(component.expenses);
66+
});
67+
68+
it('should handle page size changes', () => {
69+
const newLimit = 20;
70+
component.pageSizeChanges(newLimit);
71+
expect(component.limit).toBe(newLimit);
72+
expect(component.currentPage).toBe(1);
73+
expect(paginatorService.storePageSize).toHaveBeenCalledWith(PaginatorPage.EXPORT_LOG, newLimit);
74+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
75+
});
76+
77+
it('should handle page changes', () => {
78+
fixture.detectChanges();
79+
const newOffset = 10;
80+
component.pageChanges(newOffset);
81+
expect(component.offset).toBe(newOffset);
82+
expect(component.currentPage).toBe(2);
83+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
84+
});
85+
86+
it('should handle simple search', fakeAsync(() => {
87+
fixture.detectChanges();
88+
const searchQuery = 'test query';
89+
component.handleSimpleSearch(searchQuery);
90+
tick(1000);
91+
expect(component.searchQuery).toBe(searchQuery);
92+
expect(component.offset).toBe(0);
93+
expect(component.currentPage).toBe(1);
94+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
95+
}));
96+
97+
it('should handle date filter changes', fakeAsync(() => {
98+
component.ngOnInit();
99+
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
100+
component.skipExportLogForm.controls.start.setValue(dateRange);
101+
tick(10);
102+
expect(component.selectedDateFilter).toEqual({
103+
startDate: dateRange[0],
104+
endDate: dateRange[1]
105+
});
106+
expect(component.isDateSelected).toBeTrue();
107+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
108+
}));
109+
110+
it('should clear date filter when null is set', fakeAsync(() => {
111+
component.ngOnInit();
112+
component.skipExportLogForm.controls.start.setValue(null);
113+
tick(10);
114+
expect(component.selectedDateFilter).toBeNull();
115+
expect(component.isDateSelected).toBeFalse();
116+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
117+
}));
118+
119+
it('should call getSkippedExpenses with correct parameters', () => {
120+
fixture.detectChanges();
121+
expect(exportLogService.getSkippedExpenses).toHaveBeenCalledWith(
122+
mockPaginator.limit,
123+
mockPaginator.offset,
124+
undefined,
125+
undefined
126+
);
127+
});
128+
129+
it('should track date filter', () => {
130+
const dateFilter = { startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') };
131+
(component as any).trackDateFilter('custom', dateFilter);
132+
expect(trackingService.onDateFilter).toHaveBeenCalledWith(jasmine.any(String), jasmine.objectContaining(dateFilter));
133+
});
134+
135+
it('should set hideCalendar to false after timeout', fakeAsync(() => {
136+
component.ngOnInit();
137+
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
138+
component.skipExportLogForm.controls.start.setValue(dateRange);
139+
expect(component.hideCalendar).toBeTrue();
140+
tick(10);
141+
expect(component.hideCalendar).toBeFalse();
142+
}));
143+
});

src/app/integrations/intacct/intacct-main/intacct-export-log/intacct-skip-export-log/intacct-skip-export-log.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class IntacctSkipExportLogComponent implements OnInit {
4040

4141
dateOptions: DateFilter[] = AccountingExportModel.getDateOptionsV2();
4242

43-
selectedDateFilter: SelectedDateFilter | null;
43+
selectedDateFilter?: SelectedDateFilter | null;
4444

4545
presentDate = new Date().toLocaleDateString();
4646

@@ -60,7 +60,7 @@ export class IntacctSkipExportLogComponent implements OnInit {
6060

6161
readonly brandingConfig = brandingConfig;
6262

63-
searchQuery: string | null;
63+
searchQuery?: string | null;
6464

6565
private searchQuerySubject = new Subject<string>();
6666

0 commit comments

Comments
 (0)