Skip to content

Commit 659aca8

Browse files
test: intacct import settings utility functions (#1013)
* test: unit test intacct import settings * refactor: move to fixtures * refactor: comments * test: intacct import settings save functionality * test: intacct import settings watchers * test: intacct import settings utility functions
1 parent e25571b commit 659aca8

File tree

2 files changed

+224
-3
lines changed

2 files changed

+224
-3
lines changed

src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts

Lines changed: 209 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable dot-notation */
22
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3-
import { AbstractControl, FormArray, FormBuilder, ReactiveFormsModule } from '@angular/forms';
3+
import { AbstractControl, FormArray, FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
44
import { provideRouter, Router, RouterModule } from '@angular/router';
55
import { of, throwError } from 'rxjs';
66

@@ -13,8 +13,8 @@ import { TrackingService } from 'src/app/core/services/integration/tracking.serv
1313
import { IntegrationsToastService } from 'src/app/core/services/common/integrations-toast.service';
1414
import { StorageService } from 'src/app/core/services/common/storage.service';
1515
import { SiWorkspaceService } from 'src/app/core/services/si/si-core/si-workspace.service';
16-
import { configuration, costCodeFieldValue, costTypeFieldValue, fyleFields, groupedDestinationAttributes, importSettings, importSettingsWithProject, intacctImportCodeConfig, locationEntityMapping, sageIntacctFields, sageIntacctFieldsSortedByPriority, settingsWithDependentFields } from '../../intacct.fixture';
17-
import { IntacctCategoryDestination, IntacctOnboardingState, IntacctUpdateEvent, Page, ProgressPhase, ToastSeverity, TrackingApp } from 'src/app/core/models/enum/enum.model';
16+
import { configuration, costCodeFieldValue, costTypeFieldValue, customField, customFieldValue, fyleFields, groupedDestinationAttributes, importSettings, importSettingsWithProject, intacctImportCodeConfig, locationEntityMapping, sageIntacctFields, sageIntacctFieldsSortedByPriority, settingsWithDependentFields } from '../../intacct.fixture';
17+
import { IntacctCategoryDestination, IntacctOnboardingState, IntacctUpdateEvent, MappingSourceField, Page, ProgressPhase, SageIntacctField, ToastSeverity, TrackingApp } from 'src/app/core/models/enum/enum.model';
1818
import { SharedModule } from 'src/app/shared/shared.module';
1919
import { Org } from 'src/app/core/models/org/org.model';
2020
import { HttpClientTestingModule } from '@angular/common/http/testing';
@@ -82,6 +82,8 @@ describe('IntacctImportSettingsComponent', () => {
8282
siMappingsService.getFyleFields.and.returnValue(of(fyleFields));
8383
siMappingsService.getGroupedDestinationAttributes.and.returnValue(of(groupedDestinationAttributes));
8484
siMappingsService.getConfiguration.and.returnValue(of(configuration));
85+
siMappingsService.refreshSageIntacctDimensions.and.returnValue(of(''));
86+
siMappingsService.refreshFyleDimensions.and.returnValue(of(''));
8587
intacctConnectorService.getLocationEntityMapping.and.returnValue(of(locationEntityMapping));
8688
orgService.getCachedOrg.and.returnValue({ created_at: new Date() } as Org);
8789
siWorkspaceService.getIntacctOnboardingState.and.returnValue(IntacctOnboardingState.IMPORT_SETTINGS);
@@ -388,4 +390,208 @@ describe('IntacctImportSettingsComponent', () => {
388390
});
389391
});
390392
});
393+
394+
describe('Utility Functions', () => {
395+
beforeEach(() => {
396+
fixture.detectChanges();
397+
});
398+
399+
it('importCodeFieldGetter should return a valid FormArray', () => {
400+
expect(component.importCodeFieldGetter instanceof FormArray).toBeTrue();
401+
});
402+
403+
it('addImportCodeField should add and remove fields correctly', () => {
404+
const sourceField = IntacctCategoryDestination.ACCOUNT;
405+
406+
component.addImportCodeField({ checked: true }, sourceField);
407+
expect(component.importCodeFieldGetter.length).toBe(1);
408+
409+
component.addImportCodeField({ checked: false }, sourceField);
410+
expect(component.importCodeFieldGetter.length).toBe(0);
411+
});
412+
413+
it('getFormGroup should return FormGroup', () => {
414+
const formGroup = component['formBuilder'].group({
415+
test: ['value']
416+
});
417+
expect(component.getFormGroup(formGroup) instanceof FormGroup).toBeTrue();
418+
});
419+
420+
it('getDestinationField should correctly transform field names', () => {
421+
expect(component.getDestinationField('category')).toBe('categories');
422+
expect(component.getDestinationField('tax')).toBe('taxes');
423+
expect(component.getDestinationField('match')).toBe('matches');
424+
expect(component.getDestinationField('import')).toBe('imports');
425+
});
426+
427+
it('refreshDimensions should call refresh services and show toast', fakeAsync(() => {
428+
tick();
429+
430+
component.refreshDimensions(true);
431+
expect(siMappingsService.refreshSageIntacctDimensions).toHaveBeenCalled();
432+
expect(siMappingsService.refreshFyleDimensions).toHaveBeenCalled();
433+
expect(toastService.displayToastMessage).toHaveBeenCalledWith(
434+
ToastSeverity.SUCCESS,
435+
'Syncing data dimensions from Sage Intacct'
436+
);
437+
}));
438+
439+
it('removeFilter should reset form controls', () => {
440+
const formGroup = component['formBuilder'].group({
441+
source_field: ['test'],
442+
import_to_fyle: [true],
443+
destination_field: ['ACCOUNT']
444+
});
445+
spyOn(component, 'addImportCodeField');
446+
447+
component.removeFilter(formGroup);
448+
449+
expect(formGroup.get('source_field')?.value).toBe('');
450+
expect(formGroup.get('import_to_fyle')?.value).toBeFalse();
451+
expect(component.addImportCodeField).toHaveBeenCalledWith(
452+
{ checked: false },
453+
'ACCOUNT'
454+
);
455+
});
456+
457+
it('hasDuplicateOption should check control validity', () => {
458+
const formGroup = component['formBuilder'].group({
459+
testControl: ['value']
460+
});
461+
expect(component.hasDuplicateOption(formGroup, 0, 'testControl')).toBeTrue();
462+
});
463+
464+
it('showOrHideAddButton should return correct visibility', () => {
465+
component.sageIntacctFields = [];
466+
expect(component.showOrHideAddButton()).toBeTrue();
467+
468+
for (let i = 0; i < component.importSettingsForm.controls.expenseFields.value.length; i++) {
469+
component.sageIntacctFields.push({} as ExpenseField);
470+
}
471+
expect(component.showOrHideAddButton()).toBeFalse();
472+
});
473+
474+
it('showPreviewDialog should set dialog visibility', () => {
475+
component.showPreviewDialog(true);
476+
expect(component.isDialogVisible).toBeTrue();
477+
478+
component.showPreviewDialog(false);
479+
expect(component.isDialogVisible).toBeFalse();
480+
});
481+
482+
it('addExpenseField should add new expense field', () => {
483+
const initialLength = component.expenseFieldsGetter.length;
484+
component.addExpenseField();
485+
expect(component.expenseFieldsGetter.length).toBe(initialLength + 1);
486+
});
487+
488+
it('closeModel should reset form and close dialog', () => {
489+
component.customFieldForm = component['formBuilder'].group({
490+
testField: ['value']
491+
});
492+
component.showDialog = true;
493+
494+
component.closeModel();
495+
496+
expect(component.customFieldForm.get('testField')?.value).toBeNull();
497+
expect(component.showDialog).toBeFalse();
498+
});
499+
500+
describe('saveCustomField', () => {
501+
502+
it('should handle dependent field creation', () => {
503+
component.customFieldForDependentField = true;
504+
component.customFieldForm = component['formBuilder'].group({
505+
attribute_type: ['Test Field'],
506+
source_placeholder: ['Test Placeholder']
507+
});
508+
component['isCostCodeFieldSelected'] = true;
509+
component.customFieldControl = component.importSettingsForm.get('costCodes') as AbstractControl;
510+
511+
component.saveCustomField();
512+
513+
expect(component.costCodeFieldOption.length).toBeGreaterThan(1);
514+
expect(component.showDialog).toBeFalse();
515+
});
516+
517+
it('should handle non-dependent field creation', () => {
518+
component.customFieldForDependentField = false;
519+
component.customFieldForm = component['formBuilder'].group({
520+
attribute_type: ['Test Field'],
521+
source_placeholder: ['Test Placeholder']
522+
});
523+
spyOn(component.customFieldForm, 'reset').and.callThrough();
524+
component.customFieldControl = component['createFormGroup'](customFieldValue);
525+
526+
component.saveCustomField();
527+
528+
expect(component.customField).toEqual(customField);
529+
expect(component.fyleFields[component.fyleFields.length - 2]).toEqual(customField);
530+
expect(component.fyleFields[component.fyleFields.length - 1]).toEqual(component.customFieldOption[0]);
531+
expect(component.customFieldForm.reset).toHaveBeenCalled();
532+
});
533+
});
534+
535+
it('updateDependentField should handle dependent field updates', () => {
536+
component.importSettingsForm.patchValue({
537+
isDependentImportEnabled: true
538+
});
539+
540+
component.updateDependentField('DEPARTMENT', true);
541+
expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeFalse();
542+
543+
component.updateDependentField('PROJECT', true);
544+
expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeFalse();
545+
});
546+
547+
it('onDropdownChange should handle dependent fields', () => {
548+
const expenseFieldsArray = component.importSettingsForm.get('expenseFields') as FormArray;
549+
expenseFieldsArray.push(component['formBuilder'].group({
550+
import_to_fyle: [true],
551+
destination_field: ['TEST_FIELD']
552+
}));
553+
554+
component.fyleFields = [{
555+
attribute_type: 'DEPENDENT_FIELD',
556+
is_dependent: true
557+
} as ExpenseField];
558+
559+
component.onDropdownChange({ value: 'DEPENDENT_FIELD' }, 0);
560+
561+
expect(expenseFieldsArray.at(0).get('import_to_fyle')?.value).toBeFalse();
562+
expect(expenseFieldsArray.at(0).get('import_to_fyle')?.disabled).toBeTrue();
563+
});
564+
565+
it('acceptDependentFieldWarning should handle warning being rejected', () => {
566+
const expenseFieldsArray = component.importSettingsForm.get('expenseFields') as FormArray;
567+
const newExpenseField = component['formBuilder'].group({
568+
source_field: [MappingSourceField.PROJECT],
569+
destination_field: ['TEST_FIELD'],
570+
import_to_fyle: [false],
571+
is_custom: [false]
572+
});
573+
expenseFieldsArray.push(newExpenseField);
574+
575+
component.acceptDependentFieldWarning(false);
576+
577+
expect(newExpenseField.get('import_to_fyle')?.value).toBeTrue();
578+
expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeTrue();
579+
expect(component.importSettingsForm.get('costCodes')?.disabled).toBeTrue();
580+
expect(component.importSettingsForm.get('costTypes')?.disabled).toBeTrue();
581+
});
582+
583+
it('showWarningForDependentFields should show warning dialog', () => {
584+
const formGroup = component['formBuilder'].group({
585+
source_field: [MappingSourceField.PROJECT],
586+
destination_field: ['TEST_FIELD']
587+
});
588+
589+
component.costCodeFieldOption = [{ attribute_type: 'existing_field' } as ExpenseField];
590+
component.costTypeFieldOption = [{ attribute_type: 'existing_field' } as ExpenseField];
591+
592+
component.showWarningForDependentFields({ checked: false }, formGroup);
593+
594+
expect(component.showDependentFieldWarning).toBeTrue();
595+
});
596+
});
391597
});

src/app/integrations/intacct/intacct.fixture.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,4 +862,19 @@ export const costTypeFieldValue = {
862862
display_name: 'COST_TYPE',
863863
source_placeholder: 'Enter Cost Type',
864864
is_dependent: true
865+
};
866+
867+
export const customFieldValue = {
868+
source_field: '',
869+
destination_field: 'PROJECT',
870+
import_to_fyle: false,
871+
is_custom: false,
872+
source_placeholder: null
873+
};
874+
875+
export const customField = {
876+
attribute_type: 'TEST_FIELD',
877+
source_placeholder: 'Test Placeholder',
878+
display_name: 'Test Field',
879+
is_dependent: false
865880
};

0 commit comments

Comments
 (0)