-
Notifications
You must be signed in to change notification settings - Fork 0
test: unit test intacct import settings initialization #1007
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 intacct import settings initialization #1007
Conversation
WalkthroughThe pull request introduces significant modifications to the test suite for the Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (5)
src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (1)
173-174: Simplify redundant null checks in test assertionsIn the test assertions at lines 173-174, the use of
|| nullis redundant. Particularly in line 173,|| null || nullis unnecessary. Since the expected value is either a specific value ornull, you can simplify the expression.Consider updating the assertions:
-expect(component.importSettingsForm.get('importVendorAsMerchant')?.value).toEqual(importSettings.configurations.import_vendors_as_merchants || null || null); +expect(component.importSettingsForm.get('importVendorAsMerchant')?.value).toEqual(importSettings.configurations.import_vendors_as_merchants ?? null);Similarly, update line 174:
-expect(component.importSettingsForm.get('importCategories')?.value).toEqual(importSettings.configurations.import_categories || null); +expect(component.importSettingsForm.get('importCategories')?.value).toEqual(importSettings.configurations.import_categories ?? null);src/app/integrations/intacct/intacct.fixture.ts (4)
766-776: Ensure consistent casing indisplay_namevaluesThe
display_namevalues insageIntacctFieldshave inconsistent casing ('customer' vs. 'Project'). For consistency and readability, consider capitalizing the first letter of each word.Apply this diff to standardize the casing:
export const sageIntacctFields = [ { attribute_type: 'CUSTOMER', - display_name: 'customer', + display_name: 'Customer', is_dependent: false }, { attribute_type: 'ITEM', - display_name: 'item', + display_name: 'Item', is_dependent: false }, { attribute_type: 'PROJECT', display_name: 'Project', is_dependent: false } ] as ExpenseField[];
793-793: Simplify type assertion fordependent_field_settingsThe current type assertion
null as unknown as DependentFieldSettingis unnecessary and can be simplified. Sincenullcan be assigned to variables of typeDependentFieldSetting | null, consider removing the redundant casting to improve readability.Apply this diff:
dependent_field_settings: - null as unknown as DependentFieldSetting, + null,
798-801: Simplify type assertion for theconfigurationobjectUsing
as unknown as IntacctConfigurationis redundant here. You can directly assert the type asIntacctConfigurationor ensure the object conforms to the type without unnecessary casting.Apply this diff:
export const configuration = { reimbursable_expenses_object: null, corporate_credit_card_expenses_object: 'CHARGE_CARD_TRANSACTION', import_code_fields: [] -} as unknown as IntacctConfiguration; +} as IntacctConfiguration;
814-821: Avoid unnecessary type assertion ingroupedDestinationAttributesThe object
groupedDestinationAttributesis cast usingas unknown as GroupedDestinationAttribute. This double casting is unnecessary if the object already conforms to theGroupedDestinationAttributetype. Simplify the assertion to enhance code clarity.Apply this diff:
export const groupedDestinationAttributes = { ACCOUNT: [], EXPENSE_TYPE: [], EXPENSE_PAYMENT_TYPE: [], VENDOR: [], EMPLOYEE: [], CHARGE_CARD_NUMBER: [], TAX_DETAIL: [] -} as unknown as GroupedDestinationAttribute; +} as GroupedDestinationAttribute;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (1 hunks)
- src/app/integrations/intacct/intacct.fixture.ts (2 hunks)
🧰 Additional context used
| siImportSettingService.getImportSettings.and.returnValue(of(importSettings)); | ||
| siImportSettingService.getImportCodeFieldConfig.and.returnValue(of(intacctImportCodeConfig)); | ||
| siMappingsService.getSageIntacctFields.and.returnValue(of(sageIntacctFields)); | ||
| siMappingsService.getFyleFields.and.returnValue(of(fyleFields)); | ||
| siMappingsService.getGroupedDestinationAttributes.and.returnValue(of(groupedDestinationAttributes)); | ||
| siMappingsService.getConfiguration.and.returnValue(of(configuration)); | ||
| intacctConnectorService.getLocationEntityMapping.and.returnValue(of(locationEntityMapping)); | ||
| orgService.getCachedOrg.and.returnValue({ created_at: new Date() } as Org); | ||
| siWorkspaceService.getIntacctOnboardingState.and.returnValue(IntacctOnboardingState.IMPORT_SETTINGS); | ||
| storageService.get.and.returnValue(366); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add tests for error handling scenarios
Currently, the tests mock service methods to always return successful responses. To ensure robust error handling in the component, it's important to test how the component behaves when service calls fail.
Consider adding tests that simulate errors from service methods using throwError, and verify that the component handles these errors appropriately (e.g., sets isLoading correctly, displays error messages).
| ] | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include HelperService in the providers array
The HelperService is imported at line 15 but is not provided in the test module's providers array—it is currently commented out at lines 65-66. If the component depends on HelperService, it should be included in the providers to prevent potential runtime errors during testing.
Consider adding HelperService to the providers array:
provideRouter([]),
+HelperService
]Committable suggestion was skipped due to low confidence.
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
...ons/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (5)
src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (3)
1-27: LGTM! Consider grouping imports for better readability.The additional imports are appropriate for the expanded test suite. The use of fixtures from 'intacct.fixture.ts' is a good practice for organizing test data.
Consider grouping the imports by their source (Angular core, services, models, etc.) for improved readability. For example:
// Angular and testing imports import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { AbstractControl, FormArray, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { provideRouter, Router, RouterModule } from '@angular/router'; import { HttpClientTestingModule } from '@angular/common/http/testing'; // RxJS imports import { of, throwError } from 'rxjs'; // Component imports import { IntacctImportSettingsComponent } from './intacct-import-settings.component'; // Service imports import { SiImportSettingService } from 'src/app/core/services/si/si-configuration/si-import-setting.service'; // ... other service imports ... // Model imports import { IntacctCategoryDestination, IntacctOnboardingState, ToastSeverity } from 'src/app/core/models/enum/enum.model'; // ... other model imports ... // Fixture imports import { configuration, fyleFields, /* ... other fixtures ... */ } from '../../intacct.fixture'; // Module imports import { SharedModule } from 'src/app/shared/shared.module'; import { IntacctSharedModule } from '../intacct-shared.module';
101-140: LGTM! Comprehensive form initialization tests.The new Form Initialization test suite covers crucial aspects such as loading state, data fetching, field transformations, and configuration-dependent settings. This ensures that the component initializes correctly under various scenarios.
Consider adding a test for error handling during initialization. For example, you could test how the component behaves if one of the service calls fails:
it('should handle errors during initialization', fakeAsync(() => { siMappingsService.getSageIntacctFields.and.returnValue(throwError(() => new Error('Test error'))); component.ngOnInit(); tick(); expect(component.isLoading).toBeFalse(); expect(toastService.displayToastMessage).toHaveBeenCalledWith(jasmine.any(String), ToastSeverity.ERROR); }));This would ensure that the component gracefully handles initialization errors and provides appropriate user feedback.
183-216: LGTM! Good coverage of dependent fields scenarios.The Dependent Fields Setup tests effectively cover the handling of dependent fields in various scenarios, including when project mapping exists and when specific dependent field settings are present. The use of fakeAsync for handling asynchronous behavior is appropriate.
Consider adding a test for the case when dependent fields are disabled. This would ensure that the component behaves correctly in all possible configurations:
it('should handle disabled dependent fields', () => { const settingsWithoutDependentFields = {...settingsWithDependentFields, configurations: {...settingsWithDependentFields.configurations, is_import_enabled: false}}; siImportSettingService.getImportSettings.and.returnValue(of(settingsWithoutDependentFields)); component.ngOnInit(); fixture.detectChanges(); expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeFalse(); expect(component.importSettingsForm.get('costCodes')?.value).toBeNull(); expect(component.importSettingsForm.get('costTypes')?.value).toBeNull(); });This additional test would enhance the robustness of your test suite by covering all possible configurations of dependent fields.
src/app/integrations/intacct/intacct.fixture.ts (2)
744-749: Consider default values for import configurationThe
intacctImportCodeConfigobject is a good addition for configuring import settings. However, consider if all fields should default totrue. Depending on the use case, some fields might be better off defaulting tofalse.
824-851: LGTM: Additional test constants addedThe new constants
sageIntacctFieldsSortedByPriority,importSettingsWithProject, andsettingsWithDependentFieldsare well-structured and provide useful variations for testing different scenarios. The use of the spread operator for creating variations is appropriate.For improved readability, consider adding a brief comment above each constant explaining its purpose or the scenario it represents.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (1 hunks)
- src/app/integrations/intacct/intacct.fixture.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (7)
src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (2)
28-90: LGTM! Comprehensive test setup with appropriate spy objects.The test setup is well-structured, with spy objects for all necessary services and appropriate initial configurations. This allows for controlled testing of service interactions.
Regarding the past comment about including
HelperServicein the providers array: It appears thatHelperServiceis no longer imported or used in this test file. If the component no longer depends onHelperService, then it's correct to exclude it from the providers array. If the component still usesHelperService, please ensure it's properly mocked and included in the providers.
141-182: LGTM! Thorough testing of form group initialization.The Form Group Initialization tests provide excellent coverage of the form structure and initial values. The separate test for the expenseFields FormArray is particularly good, ensuring that this complex part of the form is correctly set up.
These tests will help maintain the integrity of the form structure as the component evolves. Good job on the detailed assertions!
src/app/integrations/intacct/intacct.fixture.ts (5)
751-762: LGTM: fyleFields constant addedThe
fyleFieldsconstant is well-structured and includes theis_dependentproperty for each field. This is a good addition to the mock data.
797-801: LGTM: configuration constant addedThe
configurationconstant is well-structured and correctly typed asIntacctConfiguration. The use ofnullforreimbursable_expenses_objectis noted and assumed to be intentional.
803-811: LGTM: locationEntityMapping constant addedThe
locationEntityMappingconstant is well-structured and correctly typed. The use ofnew Date()for timestamp fields is appropriate for creating mock data.
813-821: LGTM: groupedDestinationAttributes constant addedThe
groupedDestinationAttributesconstant is well-structured with empty arrays for each attribute type. This provides a good starting point for mock data that can be easily populated in tests as needed.
Line range hint
1-851: Overall assessment: Significant improvements to test fixturesThis update to
intacct.fixture.tsgreatly enhances the mock data and configurations available for testing the Intacct integration. The additions cover a wide range of scenarios and data structures, which should lead to more comprehensive and robust tests.Key points:
- New constants provide mock data for import configurations, field mappings, and various settings.
- The structure and typing of new constants are generally well-done.
- A few minor issues were identified, particularly with the
sageIntacctFieldsandimportSettingsconstants.- Some suggestions for improved consistency and readability were provided.
These changes will likely contribute to better test coverage and more accurate representation of real-world scenarios in your test suite.
|
|
||
| export const sageIntacctFields = [ | ||
| { | ||
| attribute_type: 'CUSTOMER', | ||
| display_name: 'customer' | ||
| }, | ||
| { | ||
| attribute_type: 'ITEM', | ||
| display_name: 'item' | ||
| }, | ||
| { | ||
| attribute_type: 'PROJECT', | ||
| display_name: 'Project' | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing 'is_dependent' property in sageIntacctFields
The sageIntacctFields array is missing the is_dependent property for each field, which is present in the fyleFields array. This inconsistency could lead to type errors or unexpected behavior in tests.
Apply this diff to add the missing property:
export const sageIntacctFields = [
{
attribute_type: 'CUSTOMER',
- display_name: 'customer'
+ display_name: 'customer',
+ is_dependent: false
},
{
attribute_type: 'ITEM',
- display_name: 'item'
+ display_name: 'item',
+ is_dependent: false
},
{
attribute_type: 'PROJECT',
- display_name: 'Project'
+ display_name: 'Project',
+ is_dependent: false
}
] as ExpenseField[];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const sageIntacctFields = [ | |
| { | |
| attribute_type: 'CUSTOMER', | |
| display_name: 'customer' | |
| }, | |
| { | |
| attribute_type: 'ITEM', | |
| display_name: 'item' | |
| }, | |
| { | |
| attribute_type: 'PROJECT', | |
| display_name: 'Project' | |
| } | |
| ] as ExpenseField[]; | |
| export const sageIntacctFields = [ | |
| { | |
| attribute_type: 'CUSTOMER', | |
| display_name: 'customer', | |
| is_dependent: false | |
| }, | |
| { | |
| attribute_type: 'ITEM', | |
| display_name: 'item', | |
| is_dependent: false | |
| }, | |
| { | |
| attribute_type: 'PROJECT', | |
| display_name: 'Project', | |
| is_dependent: false | |
| } | |
| ] as ExpenseField[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (1)
101-205: Test cases are comprehensive and well-structured.The added test cases provide good coverage of the component's functionality, including:
- Form initialization
- Data fetching and transformation
- Handling of dependent fields
- Correct setting of form control values
This comprehensive approach ensures that the component behaves as expected under various scenarios.
Consider adding a test case for error handling scenarios, such as when service calls fail. This would ensure the component handles errors gracefully.
src/app/integrations/intacct/intacct.fixture.ts (1)
744-749: Consider default values for import code configurationThe
intacctImportCodeConfigconstant is well-structured, but all values are set totrue. Consider if this is the intended default behavior, or if some fields should befalseby default.You might want to review the requirements and adjust the default values accordingly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (1 hunks)
- src/app/integrations/intacct/intacct.fixture.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (5)
src/app/integrations/intacct/intacct-shared/intacct-import-settings/intacct-import-settings.component.spec.ts (2)
1-27: Imports and setup look comprehensive and well-structured.The added imports and spy object setup provide a solid foundation for the test suite. They cover all necessary Angular testing utilities, services, and models required for thorough testing of the IntacctImportSettingsComponent.
41-94: beforeEach block is well-structured and comprehensive.The expanded beforeEach block provides a thorough setup for the test suite. It includes:
- Proper initialization of all necessary spy objects
- Mock return values for service methods
- Correct component initialization
This setup ensures that each test starts with a consistent and well-defined state, which is crucial for reliable testing.
src/app/integrations/intacct/intacct.fixture.ts (3)
11-15: LGTM: New imports are appropriateThe newly added imports are relevant to the new constants and types introduced in this file. They provide the necessary types for the mock data structures.
797-864: LGTM: New constants are well-structuredThe newly added constants (
configuration,locationEntityMapping,groupedDestinationAttributes,sageIntacctFieldsSortedByPriority,importSettingsWithProject,settingsWithDependentFields,costCodeFieldValue, andcostTypeFieldValue) are well-structured and provide comprehensive mock data for various testing scenarios.These constants will be useful for thorough testing of the Intacct integration functionality.
764-777:⚠️ Potential issueAdd missing 'is_dependent' property to sageIntacctFields
The
sageIntacctFieldsarray is missing theis_dependentproperty for each field, which is present in thefyleFieldsarray. This inconsistency could lead to type errors or unexpected behavior in tests.Apply this diff to add the missing property:
export const sageIntacctFields = [ { attribute_type: 'CUSTOMER', - display_name: 'customer' + display_name: 'customer', + is_dependent: false }, { attribute_type: 'ITEM', - display_name: 'item' + display_name: 'item', + is_dependent: false }, { attribute_type: 'PROJECT', - display_name: 'Project' + display_name: 'Project', + is_dependent: false } ] as ExpenseField[];Likely invalid or redundant comment.
| import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; | ||
| import { AbstractControl, FormArray, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; | ||
| import { provideRouter, Router, RouterModule } from '@angular/router'; | ||
| import { of, throwError } from 'rxjs'; | ||
|
|
||
| import { IntacctImportSettingsComponent } from './intacct-import-settings.component'; | ||
| import { SiImportSettingService } from 'src/app/core/services/si/si-configuration/si-import-setting.service'; | ||
| import { SiMappingsService } from 'src/app/core/services/si/si-core/si-mappings.service'; | ||
| import { IntacctConnectorService } from 'src/app/core/services/si/si-core/intacct-connector.service'; | ||
| import { OrgService } from 'src/app/core/services/org/org.service'; | ||
| import { TrackingService } from 'src/app/core/services/integration/tracking.service'; | ||
| import { IntegrationsToastService } from 'src/app/core/services/common/integrations-toast.service'; | ||
| import { StorageService } from 'src/app/core/services/common/storage.service'; | ||
| import { SiWorkspaceService } from 'src/app/core/services/si/si-core/si-workspace.service'; | ||
| import { HelperService } from 'src/app/core/services/common/helper.service'; | ||
|
|
||
| xdescribe('IntacctImportSettingsComponent', () => { | ||
| import { configuration, costCodeFieldValue, costTypeFieldValue, fyleFields, groupedDestinationAttributes, importSettings, importSettingsWithProject, intacctImportCodeConfig, locationEntityMapping, sageIntacctFields, sageIntacctFieldsSortedByPriority, settingsWithDependentFields } from '../../intacct.fixture'; | ||
| import { IntacctCategoryDestination, IntacctOnboardingState, ToastSeverity } from 'src/app/core/models/enum/enum.model'; | ||
| import { SharedModule } from 'src/app/shared/shared.module'; | ||
| import { Org } from 'src/app/core/models/org/org.model'; | ||
| import { HttpClientTestingModule } from '@angular/common/http/testing'; | ||
| import { LocationEntityMapping } from 'src/app/core/models/intacct/db/location-entity-mapping.model'; | ||
| import { IntacctSharedModule } from '../intacct-shared.module'; | ||
| import { ExpenseField } from 'src/app/core/models/intacct/db/expense-field.model'; | ||
| import { ImportSettingGet } from 'src/app/core/models/intacct/intacct-configuration/import-settings.model'; | ||
| import { IntacctConfiguration } from 'src/app/core/models/db/configuration.model'; | ||
|
|
||
| describe('IntacctImportSettingsComponent', () => { | ||
| let component: IntacctImportSettingsComponent; | ||
| let fixture: ComponentFixture<IntacctImportSettingsComponent>; | ||
| let siImportSettingService: jasmine.SpyObj<SiImportSettingService>; | ||
| let siMappingsService: jasmine.SpyObj<SiMappingsService>; | ||
| let intacctConnectorService: jasmine.SpyObj<IntacctConnectorService>; | ||
| let orgService: jasmine.SpyObj<OrgService>; | ||
| let trackingService: jasmine.SpyObj<TrackingService>; | ||
| let toastService: jasmine.SpyObj<IntegrationsToastService>; | ||
| let storageService: jasmine.SpyObj<StorageService>; | ||
| let siWorkspaceService: jasmine.SpyObj<SiWorkspaceService>; | ||
| let router: Router; | ||
|
|
||
| beforeEach(async () => { | ||
| const siImportSettingServiceSpy = jasmine.createSpyObj('SiImportSettingService', ['getImportSettings', 'postImportSettings', 'getImportCodeFieldConfig']); | ||
| const siMappingsServiceSpy = jasmine.createSpyObj('SiMappingsService', ['getSageIntacctFields', 'getFyleFields', 'getGroupedDestinationAttributes', 'getConfiguration', 'refreshSageIntacctDimensions', 'refreshFyleDimensions']); | ||
| const intacctConnectorServiceSpy = jasmine.createSpyObj('IntacctConnectorService', ['getLocationEntityMapping']); | ||
| const orgServiceSpy = jasmine.createSpyObj('OrgService', ['getCachedOrg']); | ||
| const trackingServiceSpy = jasmine.createSpyObj('TrackingService', ['integrationsOnboardingCompletion', 'intacctUpdateEvent', 'trackTimeSpent']); | ||
| const toastServiceSpy = jasmine.createSpyObj('IntegrationsToastService', ['displayToastMessage']); | ||
| const storageServiceSpy = jasmine.createSpyObj('StorageService', ['get']); | ||
| const siWorkspaceServiceSpy = jasmine.createSpyObj('SiWorkspaceService', ['getIntacctOnboardingState', 'setIntacctOnboardingState']); | ||
|
|
||
| await TestBed.configureTestingModule({ | ||
| declarations: [ IntacctImportSettingsComponent ] | ||
| declarations: [IntacctImportSettingsComponent], | ||
| imports: [SharedModule, IntacctSharedModule, ReactiveFormsModule, RouterModule.forRoot([]), HttpClientTestingModule], | ||
| providers: [ | ||
| FormBuilder, | ||
| { provide: SiImportSettingService, useValue: siImportSettingServiceSpy }, | ||
| { provide: SiMappingsService, useValue: siMappingsServiceSpy }, | ||
| { provide: IntacctConnectorService, useValue: intacctConnectorServiceSpy }, | ||
| { provide: OrgService, useValue: orgServiceSpy }, | ||
| { provide: TrackingService, useValue: trackingServiceSpy }, | ||
| { provide: IntegrationsToastService, useValue: toastServiceSpy }, | ||
| { provide: StorageService, useValue: storageServiceSpy }, | ||
| { provide: SiWorkspaceService, useValue: siWorkspaceServiceSpy }, | ||
| provideRouter([]) | ||
| ] | ||
| }) | ||
| .compileComponents(); | ||
| .compileComponents(); | ||
|
|
||
| siImportSettingService = TestBed.inject(SiImportSettingService) as jasmine.SpyObj<SiImportSettingService>; | ||
| siMappingsService = TestBed.inject(SiMappingsService) as jasmine.SpyObj<SiMappingsService>; | ||
| intacctConnectorService = TestBed.inject(IntacctConnectorService) as jasmine.SpyObj<IntacctConnectorService>; | ||
| orgService = TestBed.inject(OrgService) as jasmine.SpyObj<OrgService>; | ||
| trackingService = TestBed.inject(TrackingService) as jasmine.SpyObj<TrackingService>; | ||
| toastService = TestBed.inject(IntegrationsToastService) as jasmine.SpyObj<IntegrationsToastService>; | ||
| storageService = TestBed.inject(StorageService) as jasmine.SpyObj<StorageService>; | ||
| siWorkspaceService = TestBed.inject(SiWorkspaceService) as jasmine.SpyObj<SiWorkspaceService>; | ||
| router = TestBed.inject(Router); | ||
|
|
||
| spyOn(router, 'navigate'); | ||
| spyOnProperty(router, 'url').and.returnValue('/onboarding'); | ||
| siImportSettingService.getImportSettings.and.returnValue(of(importSettings)); | ||
| siImportSettingService.getImportCodeFieldConfig.and.returnValue(of(intacctImportCodeConfig)); | ||
| siMappingsService.getSageIntacctFields.and.returnValue(of(sageIntacctFields)); | ||
| siMappingsService.getFyleFields.and.returnValue(of(fyleFields)); | ||
| siMappingsService.getGroupedDestinationAttributes.and.returnValue(of(groupedDestinationAttributes)); | ||
| siMappingsService.getConfiguration.and.returnValue(of(configuration)); | ||
| intacctConnectorService.getLocationEntityMapping.and.returnValue(of(locationEntityMapping)); | ||
| orgService.getCachedOrg.and.returnValue({ created_at: new Date() } as Org); | ||
| siWorkspaceService.getIntacctOnboardingState.and.returnValue(IntacctOnboardingState.IMPORT_SETTINGS); | ||
| storageService.get.and.returnValue(366); | ||
|
|
||
| fixture = TestBed.createComponent(IntacctImportSettingsComponent); | ||
| component = fixture.componentInstance; | ||
| fixture.detectChanges(); | ||
|
|
||
| }); | ||
|
|
||
| it('should create', () => { | ||
| expect(component).toBeTruthy(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('Form Initialization', () => { | ||
| beforeEach(() => { | ||
| component.ngOnInit(); | ||
| fixture.detectChanges(); | ||
| }); | ||
|
|
||
| it('should set initial loading state', () => { | ||
| expect(component.isLoading).toBeFalsy(); | ||
| }); | ||
|
|
||
| it('should fetch and set all required data', () => { | ||
| expect(siMappingsService.getSageIntacctFields).toHaveBeenCalled(); | ||
| expect(siMappingsService.getFyleFields).toHaveBeenCalled(); | ||
| expect(siMappingsService.getGroupedDestinationAttributes).toHaveBeenCalledWith(['TAX_DETAIL']); | ||
| expect(siImportSettingService.getImportSettings).toHaveBeenCalled(); | ||
| expect(siMappingsService.getConfiguration).toHaveBeenCalled(); | ||
| expect(intacctConnectorService.getLocationEntityMapping).toHaveBeenCalled(); | ||
| expect(siImportSettingService.getImportCodeFieldConfig).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('should correctly transform and set sageIntacctFields', () => { | ||
| expect(component.sageIntacctFields).toEqual(sageIntacctFieldsSortedByPriority); | ||
| }); | ||
|
|
||
| it('should set Fyle fields with custom field option', () => { | ||
| expect(component.fyleFields).toEqual(fyleFields as ExpenseField[]); | ||
| }); | ||
|
|
||
| it('should set intacctCategoryDestination based on configuration', () => { | ||
| expect(component.intacctCategoryDestination).toEqual(IntacctCategoryDestination.GL_ACCOUNT); | ||
|
|
||
| const updatedConfig = {...configuration, reimbursable_expenses_object: 'EXPENSE_REPORT'}; | ||
| siMappingsService.getConfiguration.and.returnValue(of(updatedConfig as IntacctConfiguration)); | ||
|
|
||
| component.ngOnInit(); | ||
| fixture.detectChanges(); | ||
|
|
||
| expect(component.intacctCategoryDestination).toEqual(IntacctCategoryDestination.EXPENSE_TYPE); | ||
| }); | ||
|
|
||
| describe('Form Group Initialization', () => { | ||
| it('should initialize the form with correct controls', () => { | ||
| expect(component.importSettingsForm.get('importVendorAsMerchant')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('importCategories')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('importTaxCodes')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('costCodes')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('dependentFieldImportToggle')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('workspaceId')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('costTypes')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('isDependentImportEnabled')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('sageIntacctTaxCodes')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('expenseFields')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('searchOption')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('importCodeField')).toBeTruthy(); | ||
| expect(component.importSettingsForm.get('importCodeFields')).toBeTruthy(); | ||
| }); | ||
|
|
||
| it('should initialize form with correct values', () => { | ||
| expect(component.importSettingsForm.get('importVendorAsMerchant')?.value).toEqual(importSettings.configurations.import_vendors_as_merchants || null || null); | ||
| expect(component.importSettingsForm.get('importCategories')?.value).toEqual(importSettings.configurations.import_categories || null); | ||
| expect(component.importSettingsForm.get('importTaxCodes')?.value).toEqual(importSettings.configurations.import_tax_codes || null); | ||
| expect(component.importSettingsForm.get('workspaceId')?.value).toEqual(366); | ||
| expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeFalsy(); | ||
| expect(component.importSettingsForm.get('searchOption')?.value).toEqual(''); | ||
| expect(component.importSettingsForm.get('importCodeField')?.value).toEqual(importSettings.configurations.import_code_fields); | ||
| }); | ||
|
|
||
| it('should initialize expenseFields FormArray correctly', () => { | ||
| const expenseFieldsArray = component.importSettingsForm.get('expenseFields') as FormArray; | ||
| expect(expenseFieldsArray.length).toBeGreaterThan(0); | ||
|
|
||
| const testForFields = (control: AbstractControl<any, any>) => { | ||
| expect(control.get('source_field')).toBeTruthy(); | ||
| expect(control.get('destination_field')).toBeTruthy(); | ||
| expect(control.get('import_to_fyle')).toBeTruthy(); | ||
| expect(control.get('is_custom')).toBeTruthy(); | ||
| expect(control.get('source_placeholder')).toBeTruthy(); | ||
| }; | ||
| expenseFieldsArray.controls.forEach(testForFields); | ||
| }); | ||
| }); | ||
|
|
||
| describe('Dependent Fields Setup', () => { | ||
| it('should handle dependent fields when project mapping exists', fakeAsync(() => { | ||
| siImportSettingService.getImportSettings.and.returnValue(of(importSettingsWithProject)); | ||
|
|
||
| fixture.detectChanges(); | ||
| tick(); | ||
|
|
||
| expect(component.costCodeFieldOption.length).toBe(1); | ||
| expect(component.costTypeFieldOption.length).toBe(1); | ||
| })); | ||
|
|
||
| it('should handle dependent field settings', () => { | ||
| siImportSettingService.getImportSettings.and.returnValue(of(settingsWithDependentFields)); | ||
|
|
||
| component.ngOnInit(); | ||
| fixture.detectChanges(); | ||
|
|
||
| expect(component.importSettingsForm.get('isDependentImportEnabled')?.value).toBeTrue(); | ||
| expect(component.importSettingsForm.get('costCodes')?.value).toEqual(costCodeFieldValue); | ||
| expect(component.importSettingsForm.get('costTypes')?.value).toEqual(costTypeFieldValue); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider enhancing error handling tests and improving code maintainability.
While the test suite is comprehensive, consider the following improvements:
-
Add tests for error handling scenarios:
- Mock service methods to throw errors and verify that the component handles these gracefully.
- Ensure error states are properly set and error messages are displayed as expected.
-
Improve code maintainability:
- Extract magic numbers (e.g.,
366on line 162) into named constants for better readability and easier updates. - Consider moving mock data setup into separate helper functions to reduce the size of the beforeEach block and improve test readability.
- Extract magic numbers (e.g.,
These enhancements would further improve the robustness and maintainability of the test suite.
| export const importSettings = { | ||
| configurations: { | ||
| import_categories: false, | ||
| import_tax_codes: false, | ||
| import_vendors_as_merchants: false, | ||
| import_code_fields: [] | ||
| }, | ||
| general_mappings: { | ||
| default_tax_code: { | ||
| name: null, | ||
| id: null | ||
| } | ||
| }, | ||
| mapping_settings: [], | ||
| dependent_field_settings: null as unknown as DependentFieldSetting, | ||
| workspace_id: 366 | ||
| } as ImportSettingGet; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix type casting for dependent_field_settings
The importSettings constant is well-structured, but there's an issue with the dependent_field_settings property. Setting it to null and then casting it to DependentFieldSetting is incorrect and may lead to runtime errors.
Consider one of these alternatives:
- If
dependent_field_settingscan be null:
dependent_field_settings: null as DependentFieldSetting | null,- If it should always be a
DependentFieldSettingobject:
dependent_field_settings: {} as DependentFieldSetting,Choose the appropriate option based on your use case.
Clickup
https://app.clickup.com/t/86cwh86d6
Summary by CodeRabbit
IntacctImportSettingsComponentto improve testing of service interactions and component behavior.intacct.fixture.tsto support expanded testing scenarios and configurations, including new constants for import settings and field mappings.