Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: unit test the intacct export log pages #989

Merged
merged 12 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/core/services/common/export-log.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ExportLogService {
private workspaceService: WorkspaceService
) { }

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

}

getExpenseGroups(state: TaskLogState, limit: number, offset: number, selectedDateFilter: SelectedDateFilter | null, exportedAt?: string | null, query?: string | null, appName?: string): Observable<ExpenseGroupResponse> {
getExpenseGroups(state: TaskLogState, limit: number, offset: number, selectedDateFilter?: SelectedDateFilter | null, exportedAt?: string | null, query?: string | null, appName?: string): Observable<ExpenseGroupResponse> {
const params: ExpenseGroupParam = {
limit,
offset
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,143 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { of } from 'rxjs';
import { IntacctCompletedExportLogComponent } from './intacct-completed-export-log.component';
import { TrackingService } from 'src/app/core/services/integration/tracking.service';
import { ExportLogService } from 'src/app/core/services/common/export-log.service';
import { PaginatorService } from 'src/app/core/services/common/paginator.service';
import { UserService } from 'src/app/core/services/misc/user.service';
import { mockExpenseGroupResponse, mockPaginator } from '../../../intacct.fixture';
import { PaginatorPage, TaskLogState } from 'src/app/core/models/enum/enum.model';
import { MinimalUser } from 'src/app/core/models/db/user.model';
import { SharedModule } from 'src/app/shared/shared.module';

xdescribe('IntacctCompletedExportLogComponent', () => {
describe('IntacctCompletedExportLogComponent', () => {
let component: IntacctCompletedExportLogComponent;
let fixture: ComponentFixture<IntacctCompletedExportLogComponent>;
let exportLogService: jasmine.SpyObj<ExportLogService>;
let trackingService: jasmine.SpyObj<TrackingService>;
let paginatorService: jasmine.SpyObj<PaginatorService>;
let userService: jasmine.SpyObj<UserService>;

beforeEach(async () => {
const exportLogServiceSpy = jasmine.createSpyObj('ExportLogService', ['getExpenseGroups']);
const trackingServiceSpy = jasmine.createSpyObj('TrackingService', ['onDateFilter']);
const paginatorServiceSpy = jasmine.createSpyObj('PaginatorService', ['getPageSize', 'storePageSize']);
const userServiceSpy = jasmine.createSpyObj('UserService', ['getUserProfile']);

await TestBed.configureTestingModule({
declarations: [ IntacctCompletedExportLogComponent ]
})
.compileComponents();
declarations: [ IntacctCompletedExportLogComponent ],
imports: [ ReactiveFormsModule, SharedModule ],
providers: [
FormBuilder,
{ provide: ExportLogService, useValue: exportLogServiceSpy },
{ provide: TrackingService, useValue: trackingServiceSpy },
{ provide: PaginatorService, useValue: paginatorServiceSpy },
{ provide: UserService, useValue: userServiceSpy }
]
}).compileComponents();

exportLogService = TestBed.inject(ExportLogService) as jasmine.SpyObj<ExportLogService>;
trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>;
paginatorService = TestBed.inject(PaginatorService) as jasmine.SpyObj<PaginatorService>;
userService = TestBed.inject(UserService) as jasmine.SpyObj<UserService>;

userService.getUserProfile.and.returnValue({ org_id: 'ORG123' } as MinimalUser);
paginatorService.getPageSize.and.returnValue(mockPaginator);
exportLogService.getExpenseGroups.and.returnValue(of(mockExpenseGroupResponse));

fixture = TestBed.createComponent(IntacctCompletedExportLogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this line removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just because all tests dont require a full re-render, for example should handle page size changes. The tests that require a component render calls fixture.detectChanges() within the test case. For example: should handle page changes



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

it('should initialize component and load data', () => {
component.ngOnInit();
expect(component.limit).toBe(mockPaginator.limit);
expect(component.offset).toBe(mockPaginator.offset);
expect(component.isLoading).toBeFalse();
expect(component.totalCount).toBe(mockExpenseGroupResponse.count);
expect(component.filteredAccountingExports.length).toBe(mockExpenseGroupResponse.results.length);
expect(component.filteredAccountingExports).toEqual(component.accountingExports);
});

it('should handle page size changes', () => {
const newLimit = 20;
component.pageSizeChanges(newLimit);
expect(component.limit).toBe(newLimit);
expect(component.currentPage).toBe(1);
expect(paginatorService.storePageSize).toHaveBeenCalledWith(PaginatorPage.EXPORT_LOG, newLimit);
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
});

it('should handle page changes', () => {
fixture.detectChanges();
component.pageChanges(10);
expect(component.offset).toBe(10);
expect(component.currentPage).toBe(2);
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
});

it('should handle simple search', fakeAsync(() => {
const searchQuery = 'test query';
fixture.detectChanges();
component.handleSimpleSearch(searchQuery);
tick(1000);
expect(component.searchQuery).toBe(searchQuery);
expect(component.offset).toBe(0);
expect(component.currentPage).toBe(1);
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
}));

it('should open expense in Fyle', () => {
const expenseId = 'exp123';
spyOn(window, 'open');
component.openExpenseinFyle(expenseId);
expect(window.open).toHaveBeenCalledWith(jasmine.stringContaining(expenseId), '_blank');
});

it('should handle date filter changes', fakeAsync(() => {
component.ngOnInit();
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
component.exportLogForm.controls.start.setValue(dateRange);
tick(10);
expect(component.selectedDateFilter).toEqual({
startDate: dateRange[0],
endDate: dateRange[1]
});
expect(component.isDateSelected).toBeTrue();
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
expect(component.hideCalendar).toBeFalse();
}));

it('should clear date filter when null is set', fakeAsync(() => {
fixture.detectChanges();
component.exportLogForm.controls.start.setValue(null);
tick(10);
expect(component.selectedDateFilter).toBeNull();
expect(component.isDateSelected).toBeFalse();
expect(exportLogService.getExpenseGroups).toHaveBeenCalled();
}));

it('should call getExpenseGroups with correct parameters', () => {
component.ngOnInit();
expect(exportLogService.getExpenseGroups).toHaveBeenCalledWith(
TaskLogState.COMPLETE,
mockPaginator.limit,
mockPaginator.offset,
undefined,
null,
undefined
);
});

it('should track date filter', () => {
const dateFilter = { startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') };
(component as any).trackDateFilter('custom', dateFilter);
expect(trackingService.onDateFilter).toHaveBeenCalledWith(jasmine.any(String), jasmine.objectContaining(dateFilter));
});
JustARatherRidiculouslyLongUsername marked this conversation as resolved.
Show resolved Hide resolved
});
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class IntacctCompletedExportLogComponent implements OnInit {

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

selectedDateFilter: SelectedDateFilter | null;
selectedDateFilter?: SelectedDateFilter | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we add '?' here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the default value saved of selectedDate is undefined, this test case was not passing the ts type check. In it, we are testing the case where we call the exportLogService.getExpenseGroups with this.selectedDateFilter set to undefined (this line):

this.exportLogService.getExpenseGroups(TaskLogState.COMPLETE, limit, offset, this.selectedDateFilter, null, this.searchQuery)


exportLogForm: FormGroup;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { IntacctExportLogComponent } from './intacct-export-log.component';
import { FormBuilder } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { provideRouter, Router } from '@angular/router';

xdescribe('IntacctExportLogComponent', () => {
describe('IntacctExportLogComponent', () => {
let component: IntacctExportLogComponent;
let fixture: ComponentFixture<IntacctExportLogComponent>;
let router: Router;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [ IntacctExportLogComponent ],
providers: [ FormBuilder ]
providers: [ FormBuilder, provideRouter([]) ]
})
.compileComponents();

router = TestBed.inject(Router);
spyOn(router, 'navigateByUrl');

fixture = TestBed.createComponent(IntacctExportLogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
Expand All @@ -24,4 +29,9 @@ xdescribe('IntacctExportLogComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

it('should navigate to completed export log', () => {
expect(component.activeModule).toEqual(component.modules[0]);
expect(router.navigateByUrl).toHaveBeenCalledOnceWith('/integrations/intacct/main/export_log/complete');
});
});
Original file line number Diff line number Diff line change
@@ -1,23 +1,143 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { of } from 'rxjs';
import { IntacctSkipExportLogComponent } from './intacct-skip-export-log.component';
import { TrackingService } from 'src/app/core/services/integration/tracking.service';
import { ExportLogService } from 'src/app/core/services/common/export-log.service';
import { PaginatorService } from 'src/app/core/services/si/si-core/paginator.service';
import { UserService } from 'src/app/core/services/misc/user.service';
import { mockSkipExportLogResponse, mockPaginator } from '../../../intacct.fixture';
import { PaginatorPage } from 'src/app/core/models/enum/enum.model';
import { MinimalUser } from 'src/app/core/models/db/user.model';
import { SharedModule } from 'src/app/shared/shared.module';

xdescribe('SkipExportLogComponent', () => {
describe('IntacctSkipExportLogComponent', () => {
let component: IntacctSkipExportLogComponent;
let fixture: ComponentFixture<IntacctSkipExportLogComponent>;
let exportLogService: jasmine.SpyObj<ExportLogService>;
let trackingService: jasmine.SpyObj<TrackingService>;
let paginatorService: jasmine.SpyObj<PaginatorService>;
let userService: jasmine.SpyObj<UserService>;

beforeEach(async () => {
const exportLogServiceSpy = jasmine.createSpyObj('ExportLogService', ['getSkippedExpenses']);
const trackingServiceSpy = jasmine.createSpyObj('TrackingService', ['onDateFilter']);
const paginatorServiceSpy = jasmine.createSpyObj('PaginatorService', ['getPageSize', 'storePageSize']);
const userServiceSpy = jasmine.createSpyObj('UserService', ['getUserProfile']);

await TestBed.configureTestingModule({
declarations: [ IntacctSkipExportLogComponent ]
})
.compileComponents();
imports: [ ReactiveFormsModule, SharedModule ],
declarations: [ IntacctSkipExportLogComponent ],
providers: [
FormBuilder,
{ provide: ExportLogService, useValue: exportLogServiceSpy },
{ provide: TrackingService, useValue: trackingServiceSpy },
{ provide: PaginatorService, useValue: paginatorServiceSpy },
{ provide: UserService, useValue: userServiceSpy }
]
}).compileComponents();

exportLogService = TestBed.inject(ExportLogService) as jasmine.SpyObj<ExportLogService>;
trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>;
paginatorService = TestBed.inject(PaginatorService) as jasmine.SpyObj<PaginatorService>;
userService = TestBed.inject(UserService) as jasmine.SpyObj<UserService>;
});

beforeEach(() => {
fixture = TestBed.createComponent(IntacctSkipExportLogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
userService.getUserProfile.and.returnValue({ org_id: 'ORG123' } as MinimalUser);
paginatorService.getPageSize.and.returnValue(mockPaginator);
exportLogService.getSkippedExpenses.and.returnValue(of(mockSkipExportLogResponse));
});

JustARatherRidiculouslyLongUsername marked this conversation as resolved.
Show resolved Hide resolved
it('should create', () => {
expect(component).toBeTruthy();
});
});

it('should initialize component and load data', () => {
component.ngOnInit();
expect(component.limit).toBe(mockPaginator.limit);
expect(component.offset).toBe(mockPaginator.offset);
expect(component.isLoading).toBeFalse();
expect(component.totalCount).toBe(mockSkipExportLogResponse.count);
expect(component.filteredExpenses.length).toBe(mockSkipExportLogResponse.results.length);
expect(component.filteredExpenses).toEqual(component.expenses);
});

it('should handle page size changes', () => {
const newLimit = 20;
component.pageSizeChanges(newLimit);
expect(component.limit).toBe(newLimit);
expect(component.currentPage).toBe(1);
expect(paginatorService.storePageSize).toHaveBeenCalledWith(PaginatorPage.EXPORT_LOG, newLimit);
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
});

it('should handle page changes', () => {
fixture.detectChanges();
const newOffset = 10;
component.pageChanges(newOffset);
expect(component.offset).toBe(newOffset);
expect(component.currentPage).toBe(2);
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
});

it('should handle simple search', fakeAsync(() => {
fixture.detectChanges();
const searchQuery = 'test query';
component.handleSimpleSearch(searchQuery);
tick(1000);
expect(component.searchQuery).toBe(searchQuery);
expect(component.offset).toBe(0);
expect(component.currentPage).toBe(1);
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
}));

it('should handle date filter changes', fakeAsync(() => {
component.ngOnInit();
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
component.skipExportLogForm.controls.start.setValue(dateRange);
tick(10);
expect(component.selectedDateFilter).toEqual({
startDate: dateRange[0],
endDate: dateRange[1]
});
expect(component.isDateSelected).toBeTrue();
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
}));

it('should clear date filter when null is set', fakeAsync(() => {
component.ngOnInit();
component.skipExportLogForm.controls.start.setValue(null);
tick(10);
expect(component.selectedDateFilter).toBeNull();
expect(component.isDateSelected).toBeFalse();
expect(exportLogService.getSkippedExpenses).toHaveBeenCalled();
}));

it('should call getSkippedExpenses with correct parameters', () => {
fixture.detectChanges();
expect(exportLogService.getSkippedExpenses).toHaveBeenCalledWith(
mockPaginator.limit,
mockPaginator.offset,
undefined,
undefined
);
});

it('should track date filter', () => {
const dateFilter = { startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') };
(component as any).trackDateFilter('custom', dateFilter);
expect(trackingService.onDateFilter).toHaveBeenCalledWith(jasmine.any(String), jasmine.objectContaining(dateFilter));
});

it('should set hideCalendar to false after timeout', fakeAsync(() => {
component.ngOnInit();
const dateRange = [new Date('2023-01-01'), new Date('2023-01-31')];
component.skipExportLogForm.controls.start.setValue(dateRange);
expect(component.hideCalendar).toBeTrue();
tick(10);
expect(component.hideCalendar).toBeFalse();
}));
});
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class IntacctSkipExportLogComponent implements OnInit {

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

selectedDateFilter: SelectedDateFilter | null;
selectedDateFilter?: SelectedDateFilter | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason


presentDate = new Date().toLocaleDateString();

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

readonly brandingConfig = brandingConfig;

searchQuery: string | null;
searchQuery?: string | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same reason


private searchQuerySubject = new Subject<string>();

Expand Down
Loading
Loading