@@ -14,9 +14,11 @@ import { EmployeeFieldMapping, ExpenseGroupingFieldOption, ExportDateType, FyleF
1414import { ExportSettingOptionSearch , ExportSettingModel } from 'src/app/core/models/common/export-settings.model' ;
1515import { IntacctDestinationAttribute , PaginatedintacctDestinationAttribute } from 'src/app/core/models/intacct/db/destination-attribute.model' ;
1616import { SharedModule } from 'src/app/shared/shared.module' ;
17- import { brandingConfig } from 'src/app/branding/branding-config' ;
17+ import { brandingConfig , brandingContent } from 'src/app/branding/branding-config' ;
1818import { BrandingConfiguration } from 'src/app/core/models/branding/branding-configuration.model' ;
19- import { ExportSettingModel as IntacctExportSettingModel } from 'src/app/core/models/intacct/intacct-configuration/export-settings.model' ;
19+ import { ExportSettingGet , ExportSettingModel as IntacctExportSettingModel } from 'src/app/core/models/intacct/intacct-configuration/export-settings.model' ;
20+ import { TitleCasePipe } from '@angular/common' ;
21+
2022
2123describe ( 'IntacctExportSettingsComponent' , ( ) => {
2224 let component : IntacctExportSettingsComponent ;
@@ -171,16 +173,329 @@ describe('IntacctExportSettingsComponent', () => {
171173 } ) ;
172174 } ) ;
173175
174- it ( 'should handle refresh dimensions' , ( ) => {
175- component . refreshDimensions ( true ) ;
176- expect ( mappingService . refreshSageIntacctDimensions ) . toHaveBeenCalled ( ) ;
177- expect ( mappingService . refreshFyleDimensions ) . toHaveBeenCalled ( ) ;
178- expect ( toastService . displayToastMessage ) . toHaveBeenCalledWith ( ToastSeverity . SUCCESS , 'Syncing data dimensions from Sage Intacct' ) ;
176+ describe ( 'Utility Functions' , ( ) => {
177+ it ( 'should handle refresh dimensions' , ( ) => {
178+ component . refreshDimensions ( true ) ;
179+ expect ( mappingService . refreshSageIntacctDimensions ) . toHaveBeenCalled ( ) ;
180+ expect ( mappingService . refreshFyleDimensions ) . toHaveBeenCalled ( ) ;
181+ expect ( toastService . displayToastMessage ) . toHaveBeenCalledWith ( ToastSeverity . SUCCESS , 'Syncing data dimensions from Sage Intacct' ) ;
182+ } ) ;
183+
184+ it ( 'should navigate to previous step' , ( ) => {
185+ component . navigateToPreviousStep ( ) ;
186+ expect ( router . navigate ) . toHaveBeenCalledWith ( [ '/integrations/intacct/onboarding/connector' ] ) ;
187+ } ) ;
188+
189+ it ( 'should return the correct employee field mapping' , ( ) => {
190+ fixture . detectChanges ( ) ;
191+
192+ expect (
193+ component . getEmployeeFieldMapping ( FyleField . VENDOR , IntacctReimbursableExpensesObject . BILL )
194+ ) . toBe ( 'Vendor' ) ;
195+
196+ expect ( component . getEmployeeFieldMapping ( null , IntacctReimbursableExpensesObject . JOURNAL_ENTRY ) )
197+ . toBe ( new TitleCasePipe ( ) . transform ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. value ) ) ;
198+
199+ expect ( component . getEmployeeFieldMapping ( null , IntacctReimbursableExpensesObject . BILL ) )
200+ . toBe ( 'Vendor' ) ;
201+ } ) ;
202+
203+ it ( 'should get the correct export type' , ( ) => {
204+ expect ( component . getExportType ( IntacctReimbursableExpensesObject . JOURNAL_ENTRY ) ) . toBe ( 'Journal_entry' ) ;
205+ expect ( component . getExportType ( IntacctReimbursableExpensesObject . BILL ) ) . toBe ( 'Bill' ) ;
206+ expect ( component . getExportType ( IntacctReimbursableExpensesObject . EXPENSE_REPORT ) ) . toBe ( 'Expense_report' ) ;
207+ expect ( component . getExportType ( null ) ) . toBe ( 'export' ) ;
208+ } ) ;
209+ } ) ;
210+
211+ describe ( 'Watchers' , ( ) => {
212+ beforeEach ( ( ) => {
213+ fixture . detectChanges ( ) ;
214+ } ) ;
215+
216+ describe ( 'Reimbursable Expense Toggle Watcher' , ( ) => {
217+ it ( 'should enable fields on enabling reimbursable expenses' , fakeAsync ( ( ) => {
218+ component . exportSettingsForm . get ( 'reimbursableExpense' ) ?. setValue ( true ) ;
219+ tick ( ) ;
220+
221+ expect ( component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
222+ expect ( component . exportSettingsForm . get ( 'reimbursableExportGroup' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
223+ expect ( component . exportSettingsForm . get ( 'reimbursableExportDate' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
224+ } ) ) ;
225+
226+ it ( 'should disable fields on disabling reimbursable expenses' , fakeAsync ( ( ) => {
227+ component . exportSettingsForm . get ( 'reimbursableExpense' ) ?. setValue ( false ) ;
228+ tick ( ) ;
229+
230+ expect ( component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
231+ expect ( component . exportSettingsForm . get ( 'reimbursableExportGroup' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
232+ expect ( component . exportSettingsForm . get ( 'reimbursableExportDate' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
233+ expect ( component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. value ) . toBeNull ( ) ;
234+ } ) ) ;
235+ } ) ;
236+
237+ describe ( 'Reimbursable Export Type Watchers' , ( ) => {
238+
239+ it ( 'should handle reimbursableExportType being changed to Journal Entry' , fakeAsync ( ( ) => {
240+ component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. setValue ( IntacctReimbursableExpensesObject . JOURNAL_ENTRY ) ;
241+ tick ( ) ;
242+
243+ expect ( component . exportSettingsForm . get ( 'glAccount' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
244+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. enabled ) . toBeTrue ( ) ;
245+ } ) ) ;
246+
247+ it ( 'should handle reimbursableExportType being changed to Expense Report' , fakeAsync ( ( ) => {
248+ component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. setValue ( IntacctReimbursableExpensesObject . EXPENSE_REPORT ) ;
249+ tick ( ) ;
250+
251+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. value ) . toBe ( FyleField . EMPLOYEE ) ;
252+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. disabled ) . toBeTrue ( ) ;
253+ } ) ) ;
254+
255+ it ( 'should handle reimbursableExportType being changed to Bill' , fakeAsync ( ( ) => {
256+ component . exportSettingsForm . get ( 'reimbursableExportType' ) ?. setValue ( IntacctReimbursableExpensesObject . BILL ) ;
257+ tick ( ) ;
258+
259+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. value ) . toBe ( FyleField . VENDOR ) ;
260+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. disabled ) . toBeTrue ( ) ;
261+ } ) ) ;
262+ } ) ;
263+
264+ describe ( 'Credit Card Expense Toggle Watcher' , ( ) => {
265+ it ( 'should enable fields on enabling CCC expenses' , fakeAsync ( ( ) => {
266+ component . exportSettingsForm . get ( 'creditCardExpense' ) ?. setValue ( true ) ;
267+ tick ( ) ;
268+
269+ expect ( component . exportSettingsForm . get ( 'cccExportType' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
270+ expect ( component . exportSettingsForm . get ( 'cccExportGroup' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
271+ expect ( component . exportSettingsForm . get ( 'cccExportDate' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
272+ } ) ) ;
273+
274+ it ( 'should disable fields on disabling CCC expenses' , fakeAsync ( ( ) => {
275+ component . exportSettingsForm . get ( 'creditCardExpense' ) ?. setValue ( false ) ;
276+ tick ( ) ;
277+
278+ expect ( component . exportSettingsForm . get ( 'cccExportType' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
279+ expect ( component . exportSettingsForm . get ( 'cccExportGroup' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
280+ expect ( component . exportSettingsForm . get ( 'cccExportDate' ) ?. hasValidator ( Validators . required ) ) . toBeFalse ( ) ;
281+ expect ( component . exportSettingsForm . get ( 'cccExportType' ) ?. value ) . toBeNull ( ) ;
282+ } ) ) ;
283+ } ) ;
284+
285+ describe ( 'CCC Export Type Watchers' , ( ) => {
286+ it ( 'should handle cccExportType being changed to Charge Card Transaction' , fakeAsync ( ( ) => {
287+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . CHARGE_CARD_TRANSACTION ) ;
288+ tick ( ) ;
289+
290+ expect ( component . exportSettingsForm . get ( 'chargeCard' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
291+ expect ( component . exportSettingsForm . get ( 'cccExportGroup' ) ?. disabled ) . toBeTrue ( ) ;
292+ expect ( component . exportSettingsForm . get ( 'cccExportGroup' ) ?. value ) . toBe ( ExpenseGroupingFieldOption . EXPENSE_ID ) ;
293+ } ) ) ;
294+
295+ it ( 'should handle cccExportType being changed to Bill' , fakeAsync ( ( ) => {
296+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . BILL ) ;
297+ tick ( ) ;
298+
299+ expect ( component . exportSettingsForm . get ( 'creditCardVendor' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
300+ } ) ) ;
301+
302+ it ( 'should handle cccExportType being changed to Expense Report' , fakeAsync ( ( ) => {
303+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . EXPENSE_REPORT ) ;
304+ tick ( ) ;
305+
306+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. value ) . toBe ( EmployeeFieldMapping . EMPLOYEE ) ;
307+ expect ( component . exportSettingsForm . get ( 'cccExpensePaymentType' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
308+ } ) ) ;
309+
310+ it ( 'should handle cccExportType being changed to Journal Entry' , fakeAsync ( ( ) => {
311+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . JOURNAL_ENTRY ) ;
312+ tick ( ) ;
313+
314+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. enabled ) . toBeTrue ( ) ;
315+ expect ( component . exportSettingsForm . get ( 'creditCard' ) ?. hasValidator ( Validators . required ) ) . toBeTrue ( ) ;
316+ } ) ) ;
317+ } ) ;
318+
319+ describe ( 'Custom Watchers' , ( ) => {
320+ beforeEach ( ( ) => {
321+ brandingConfig . brandId = 'fyle' ;
322+ } ) ;
323+
324+ it ( 'should update reimbursable expense grouping date options when group changes' , fakeAsync ( ( ) => {
325+ fixture . detectChanges ( ) ;
326+ component . exportSettingsForm . get ( 'reimbursableExportGroup' ) ?. setValue ( ExpenseGroupingFieldOption . CLAIM_NUMBER ) ;
327+ tick ( ) ;
328+
329+ expect ( component . reimbursableExpenseGroupingDateOptions ) . not . toContain ( {
330+ label : 'Spend date' ,
331+ value : ExportDateType . SPENT_AT
332+ } ) ;
333+ } ) ) ;
334+
335+ it ( 'should update CCC expense grouping date options when group changes' , fakeAsync ( ( ) => {
336+ spyOn < IntacctExportSettingsComponent , any > ( component , 'setCCExpenseDateOptions' ) . and . callThrough ( ) ;
337+ spyOn ( IntacctExportSettingModel , 'getExpenseGroupingDateOptions' ) . and . callThrough ( ) ;
338+ spyOn ( ExportSettingModel , 'constructGroupingDateOptions' ) . and . callThrough ( ) ;
339+
340+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . CHARGE_CARD_TRANSACTION ) ;
341+ component . exportSettingsForm . get ( 'cccExportGroup' ) ?. setValue ( ExpenseGroupingFieldOption . CLAIM_NUMBER ) ;
342+
343+ tick ( ) ;
344+
345+ expect ( IntacctExportSettingModel . getExpenseGroupingDateOptions ) . toHaveBeenCalledWith ( ) ;
346+ expect ( ExportSettingModel . constructGroupingDateOptions ) . toHaveBeenCalledWith (
347+ ExpenseGroupingFieldOption . CLAIM_NUMBER ,
348+ IntacctExportSettingModel . getExpenseGroupingDateOptions ( )
349+ ) ;
350+ expect ( component [ 'setCCExpenseDateOptions' ] ) . toHaveBeenCalled ( ) ;
351+ } ) ) ;
352+ } ) ;
353+
354+ describe ( 'Export Selection Validator' , ( ) => {
355+ beforeEach ( ( ) => {
356+ fixture . detectChanges ( ) ;
357+ } ) ;
358+
359+ it ( 'should invalidate form when neither reimbursable nor credit card expense is selected' , ( ) => {
360+ component . exportSettingsForm . get ( 'reimbursableExpense' ) ?. setValue ( false ) ;
361+ component . exportSettingsForm . get ( 'creditCardExpense' ) ?. setValue ( false ) ;
362+
363+ expect ( component . exportSettingsForm . valid ) . toBeFalse ( ) ;
364+ } ) ;
365+
366+ it ( 'should validate the form when at least one export type is selected' , ( ) => {
367+ component . exportSettingsForm . get ( 'reimbursableExpense' ) ?. setValue ( true ) ;
368+ component . exportSettingsForm . get ( 'creditCardExpense' ) ?. setValue ( false ) ;
369+
370+ expect ( component . exportSettingsForm . valid ) . toBeTrue ( ) ;
371+ } ) ;
372+ } ) ;
373+
374+ describe ( 'Destination Options Handling' , ( ) => {
375+ beforeEach ( ( ) => {
376+ fixture . detectChanges ( ) ;
377+ } ) ;
378+
379+ it ( 'should handle option search for reimbursable expense payment type' , fakeAsync ( ( ) => {
380+ const searchEvent = {
381+ searchTerm : 'test' ,
382+ destinationOptionKey : 'EXPENSE_PAYMENT_TYPE'
383+ } as ExportSettingOptionSearch ;
384+
385+ mappingService . getPaginatedDestinationAttributes . and . returnValue (
386+ of ( mockPaginatedDestinationAttributes . EXPENSE_PAYMENT_TYPE as unknown as PaginatedintacctDestinationAttribute )
387+ ) ;
388+
389+ component . searchOptionsDropdown ( searchEvent ) ;
390+ tick ( 1000 ) ;
391+
392+ expect ( mappingService . getPaginatedDestinationAttributes ) . toHaveBeenCalledWith ( 'EXPENSE_PAYMENT_TYPE' , 'test' ) ;
393+
394+ const isReimbursable = ( option : IntacctDestinationAttribute ) => (
395+ option . detail ? option . detail . is_reimbursable : true
396+ ) ;
397+
398+ expect ( component . destinationOptions . EXPENSE_PAYMENT_TYPE . every ( isReimbursable ) ) . toBeTrue ( ) ;
399+ expect ( component . isOptionSearchInProgress ) . toBeFalse ( ) ;
400+ } ) ) ;
401+
402+ it ( 'should handle option search for CCC expense payment type' , fakeAsync ( ( ) => {
403+ const searchEvent = {
404+ searchTerm : 'test' ,
405+ destinationOptionKey : 'CCC_EXPENSE_PAYMENT_TYPE'
406+ } ;
407+
408+ mappingService . getPaginatedDestinationAttributes . and . returnValue (
409+ of ( mockPaginatedDestinationAttributes . EXPENSE_PAYMENT_TYPE as unknown as PaginatedintacctDestinationAttribute )
410+ ) ;
411+
412+ component . searchOptionsDropdown ( searchEvent as ExportSettingOptionSearch ) ;
413+ tick ( 1000 ) ;
414+
415+ expect ( mappingService . getPaginatedDestinationAttributes ) . toHaveBeenCalledWith ( 'EXPENSE_PAYMENT_TYPE' , 'test' ) ;
416+ expect ( component . destinationOptions . CCC_EXPENSE_PAYMENT_TYPE . every ( option => (
417+ option . detail ? ! option . detail . is_reimbursable : true
418+ ) ) ) . toBeTrue ( ) ;
419+ expect ( component . isOptionSearchInProgress ) . toBeFalse ( ) ;
420+ } ) ) ;
421+ } ) ;
422+
423+
424+ } ) ;
425+
426+ describe ( 'C1 Specific Behavior' , ( ) => {
427+ it ( 'should handle setup with c1 branding' , ( ) => {
428+ brandingConfig . brandId = 'co' ;
429+
430+ fixture = TestBed . createComponent ( IntacctExportSettingsComponent ) ;
431+ component = fixture . componentInstance ;
432+ fixture . detectChanges ( ) ;
433+
434+ expect ( component . exportSettingsForm . get ( 'creditCardExpense' ) ?. value ) . toBeTrue ( ) ;
435+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. value ) . toBe ( FyleField . VENDOR ) ;
436+ expect ( component . isMultiLineOption ) . toBeFalse ( ) ;
437+ } ) ;
438+
439+ afterAll ( ( ) => {
440+ brandingConfig . brandId = 'fyle' ;
441+ } ) ;
179442 } ) ;
180443
181- it ( 'should navigate to previous step' , ( ) => {
182- component . navigateToPreviousStep ( ) ;
183- expect ( router . navigate ) . toHaveBeenCalledWith ( [ '/integrations/intacct/onboarding/connector' ] ) ;
444+ describe ( 'Edge Cases' , ( ) => {
445+ it ( 'should set the correct CCC expense grouping date options when CCC expense object is unset' , ( ) => {
446+ component . exportSettings = {
447+ configurations : {
448+ corporate_credit_card_expenses_object : null
449+ }
450+ } as ExportSettingGet ;
451+ spyOn < any > ( component , 'setCCExpenseDateOptions' ) ;
452+
453+ component [ 'setupCCCExpenseGroupingDateOptions' ] ( ) ;
454+ expect ( component [ 'setCCExpenseDateOptions' ] ) . toHaveBeenCalledOnceWith ( IntacctCorporateCreditCardExpensesObject . CHARGE_CARD_TRANSACTION ) ;
455+ } ) ;
456+
457+ it ( 'should default CCC expense grouping date options to reimbursable grouping date options for non-charge card transactions' , ( ) => {
458+ fixture . detectChanges ( ) ;
459+
460+ component [ 'setCCExpenseDateOptions' ] ( IntacctCorporateCreditCardExpensesObject . BILL ) ;
461+ expect ( component . cccExpenseGroupingDateOptions ) . toEqual ( component . reimbursableExpenseGroupingDateOptions ) ;
462+ } ) ;
463+
464+ it ( 'should set the correct CCC expense grouping date options when grouping by report' , ( ) => {
465+ fixture . detectChanges ( ) ;
466+
467+ component . exportSettingsForm . get ( 'cccExportType' ) ?. setValue ( IntacctCorporateCreditCardExpensesObject . CHARGE_CARD_TRANSACTION ) ;
468+ component [ 'updateCCCGroupingDateOptions' ] ( ExpenseGroupingFieldOption . CLAIM_NUMBER ) ;
469+
470+ expect ( component . cccExpenseGroupingDateOptions ) . toEqual ( [
471+ {
472+ label : brandingContent . common . currentDate ,
473+ value : ExportDateType . CURRENT_DATE
474+ } ,
475+ {
476+ label : 'Last Spend Date' ,
477+ value : ExportDateType . LAST_SPENT_AT
478+ } ,
479+ {
480+ label : 'Approved Date' ,
481+ value : ExportDateType . APPROVAL_DATE
482+ } ,
483+ {
484+ label : 'Card Transaction Post date' ,
485+ value : ExportDateType . POSTED_AT
486+ }
487+ ] ) ;
488+ } ) ;
489+
490+ it ( 'should enable the employeeFieldMapping field when at least one export type is Journal Entry' , ( ) => {
491+ fixture . detectChanges ( ) ;
492+ component . exportSettings . configurations . reimbursable_expenses_object = IntacctReimbursableExpensesObject . JOURNAL_ENTRY ;
493+ component . exportSettings . configurations . corporate_credit_card_expenses_object = IntacctCorporateCreditCardExpensesObject . CHARGE_CARD_TRANSACTION ;
494+
495+ component [ 'exportFieldsWatcher' ] ( ) ;
496+
497+ expect ( component . exportSettingsForm . get ( 'employeeFieldMapping' ) ?. enabled ) . toBeTrue ( ) ;
498+ } ) ;
184499 } ) ;
185500
186501 describe ( 'Watchers' , ( ) => {
0 commit comments