import { Injectable } from '@angular/core'; import { CLIENT_SETTINGS_SERVICE_MOCK } from '@core/mocks/client-settings.service.mock'; import { CURRENCY_SERVICE_MOCK } from '@core/mocks/currency.service.mock'; import { GCMockModule } from '@core/mocks/gc-module.mock'; import { ReferenceFieldAPI } from '@core/typings/api/reference-fields.typing'; import { ReferenceFieldsUI } from '@core/typings/ui/reference-fields.typing'; import { FormAudience, FormDefinitionComponent } from '@features/configure-forms/form.typing'; import { BeforeEach, Spec, TestCase } from '@yourcause/test-decorators'; import { DescribeAngularService } from '@yourcause/test-decorators/angular'; import { expect } from 'chai'; import { ComponentConfigurationService } from './component-configuration.service'; import { Advanced_Validation_Setting, Calculated_Value_Setting, ComponentConfigTabType, ComponentTabOptions, Conditional_Logic_Setting, Old_Calculated_Value_Setting, Old_Conditional_Logic_Setting, Old_Custom_Validation_Setting } from './component-configuration.typing'; type GetCompConfigFuncNames = 'getEmployeeSsoConfig'|'getCareOfConfig'|'getDecisionConfig'|'getInKindConfig'|'getDesignationConfig'|'getReportFieldConfig'|'getSpecialHandlingConfig'|'getContentConfig'|'getColumnsConfig'|'getFieldSetConfig'|'getPanelConfig'|'getTableConfig'|'getWellConfig'; @Injectable({ providedIn: 'root' }) @DescribeAngularService(ComponentConfigurationService, { imports: [ GCMockModule ], providers: [ CLIENT_SETTINGS_SERVICE_MOCK, CURRENCY_SERVICE_MOCK ] }) export class ComponentConfigurationServiceSpec implements Spec { textFieldId = 1; textAreaId = 2; dataTableId = 4; numberId = 5; dataTableId2 = 7; fileUploadId = 9; parentFieldId = 13; subsetId = 14; numberKey = 'number'; dataTable1Key = 'customDataTable'; dataTable2Key = 'customDataTable2'; fileUploadKey = 'fileUploadKey'; textFieldKey = 'textfield'; textAreaKey = 'textarea'; subsetKey = 'subsetKey'; cdtId1 = 1; cdtId2 = 2; cdtGuid1 = 'guid1'; cdtGuid2 = 'guid2'; numberField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.numberId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: '', name: 'Number', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.Number, key: this.numberKey, supportsMultiple: false, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; multiTextField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.textFieldId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: '', name: 'Text field', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.TextField, key: this.textFieldKey, supportsMultiple: true, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; childField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.dataTableId2, parentReferenceFieldId: this.parentFieldId, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: this.cdtGuid1, name: 'Child custom data table', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.CustomDataTable, key: this.dataTable2Key, supportsMultiple: true, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; parentField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.parentFieldId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: '', name: 'Parent picklist', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.CustomDataTable, key: 'parentFieldKey', supportsMultiple: false, categoryId: null, formAudience: FormAudience.MANAGER, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; subsetTableId = 456; subsetFieldPercent: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: true, aggregateType: null, referenceFieldId: this.subsetId, parentReferenceFieldId: null, formCount: 1, usedOnReports: true, createdBy: '', createDate: '', updateDate: '', updatedBy: '', customDataTableGuid: '', name: 'Subset field - percent', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.Subset, key: this.subsetKey, supportsMultiple: false, categoryId: null, formAudience: FormAudience.MANAGER, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: this.subsetTableId, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: ReferenceFieldAPI.DataSetCollectionType.Percent }; fileUpload: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.fileUploadId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: '', name: 'File Upload', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.FileUpload, key: this.fileUploadKey, supportsMultiple: false, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; textArea: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.textAreaId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: '', name: 'Text area', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.TextArea, key: this.textAreaKey, supportsMultiple: false, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: true, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; multiCdt: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: this.dataTableId, parentReferenceFieldId: null, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: this.cdtGuid2, name: 'Custom data table', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.CustomDataTable, key: this.dataTable1Key, supportsMultiple: true, categoryId: null, formAudience: FormAudience.APPLICANT, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; allReferenceFields: ReferenceFieldAPI.ReferenceFieldDisplayModel[] = [ this.multiTextField, this.textArea, this.multiCdt, this.parentField, this.childField, this.numberField, this.fileUpload, this.subsetFieldPercent ]; @BeforeEach() mock (service: ComponentConfigurationService) { service['referenceFieldService']['referenceFieldsResources'].searchReferenceFields = async () => { return { records: this.allReferenceFields, recordCount: this.allReferenceFields.length }; }; service['referenceFieldService']['referenceFieldsResources'].getCategories = async () => { return []; }; service['referenceFieldService'].resolve(); } @TestCase('should be able to get tabs for comp config') getTabsForComponentConfiguration (service: ComponentConfigurationService) { const component = { type: 'designation' } as FormDefinitionComponent; const tabs = service.getTabsForComponentConfiguration(component, FormAudience.APPLICANT); const displayIsActive = tabs.find((tab) => { return tab.context === ComponentConfigTabType.Display; }).active === true; expect(displayIsActive).to.be.true; } @TestCase('should be able to get label by config tab type') getLabelByConfigTabType (service: ComponentConfigurationService) { let label = service.getLabelByConfigTabType(ComponentConfigTabType.Api); expect(label).to.be.equal('API'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Calculated_Value); expect(label).to.be.equal('Calculated Value'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Conditional_Visibility); expect(label).to.be.equal('Display'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Data); expect(label).to.be.equal('Data'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Display); expect(label).to.be.equal('Details'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Set_Value); expect(label).to.be.equal('Set Value'); label = service.getLabelByConfigTabType(ComponentConfigTabType.Validation); expect(label).to.be.equal('Validation'); } @TestCase('should be able to get value for comp setting') getValueForComponentSetting (service: ComponentConfigurationService) { const label = 'Phone number'; const pattern = 'pattern'; const comp = { label, validate: { pattern } } as FormDefinitionComponent; let result = service.getValueForComponentSetting(comp, 'validate.pattern'); expect(result).to.be.equal(pattern); result = service.getValueForComponentSetting(comp, 'label'); expect(result).to.be.equal(label); } @TestCase('should be able to get conditional logic components') getConditionalLogicComponents (service: ComponentConfigurationService) { let logic = ''; let result = service.getConditionalLogicComponents(logic); let expectedResult = [ Conditional_Logic_Setting ]; expect(result).to.deep.equal(expectedResult); logic = 'some custom logic'; result = service.getConditionalLogicComponents(logic); expectedResult = [ Old_Conditional_Logic_Setting, Conditional_Logic_Setting ]; expect(result).to.deep.equal(expectedResult); } @TestCase('should be able to get calculated value components') getCalculatedValueComponents (service: ComponentConfigurationService) { let calcValue = ''; let result = service.getCalculatedValueComponents(calcValue); let expectedResult = [ Calculated_Value_Setting ]; expect(result).to.deep.equal(expectedResult); calcValue = 'some calculated value'; result = service.getCalculatedValueComponents(calcValue); expectedResult = [ Old_Calculated_Value_Setting, Calculated_Value_Setting ]; expect(result).to.deep.equal(expectedResult); } @TestCase('should be able to get custom validation components') getCustomValidationComponents (service: ComponentConfigurationService) { let customValidation = ''; let result = service.getCustomValidationComponents(customValidation); let expectedResult = [ Advanced_Validation_Setting ]; expect(result).to.deep.equal(expectedResult); customValidation = 'some custom validation'; result = service.getCustomValidationComponents(customValidation); expectedResult = [ Old_Custom_Validation_Setting, Advanced_Validation_Setting ]; expect(result).to.deep.equal(expectedResult); } private getTabsWithComponents ( service: ComponentConfigurationService, funcName: GetCompConfigFuncNames ) { const config = service[funcName](''); const tabsWithComps = this.filterTabsToVisible(config); return tabsWithComps; } private filterTabsToVisible ( config: Record ) { return Object.keys(config).filter((key) => { return config[ +key as ComponentConfigTabType ].components.length > 0; }).map((key) => { return +key as ComponentConfigTabType; }); } @TestCase('should be able to get ref field config - text') getReferenceFieldConfigText (service: ComponentConfigurationService) { const config = service.getReferenceFieldConfig( `referenceFields-${this.multiTextField.key}`, '', '', '', this.multiTextField.formAudience ); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); // Multi fields do not support these settings const doesNotHaveMaskOrPattern = config[ComponentConfigTabType.Data].components.every((comp) => { return comp.key !== 'inputMask' && comp.key !== 'validate.pattern'; }); expect(doesNotHaveMaskOrPattern).to.be.true; } @TestCase('should be able to get ref field config - number') getReferenceFieldConfigNumber (service: ComponentConfigurationService) { const config = service.getReferenceFieldConfig( `referenceFields-${this.numberField.key}`, '', '', '', this.numberField.formAudience ); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value, ComponentConfigTabType.Calculated_Value ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get ref field config - picklist') getReferenceFieldConfigPicklist (service: ComponentConfigurationService) { const config = service.getReferenceFieldConfig( `referenceFields-${this.childField.key}`, '', '', '', this.childField.formAudience ); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); const hasHideWithoutParentVal = config[ComponentConfigTabType.Data].components.some((comp) => { return comp.key === 'hideWithoutParentVal'; }); expect(hasHideWithoutParentVal).to.be.true; } @TestCase('should be able to get ref field config - for display only') getReferenceFieldConfigForDisplayOnly (service: ComponentConfigurationService) { const config = service.getReferenceFieldConfig( `referenceFields-${this.parentField.key}`, '', '', '', FormAudience.APPLICANT // Parent field is a GM field on an Applicant form ); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; // Data & Set Value tabs are not visible because it's only for display const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get ref field config - subset') getReferenceFieldConfigSubset (service: ComponentConfigurationService) { const config = service.getReferenceFieldConfig( `referenceFields-${this.subsetFieldPercent.key}`, '', '', '', this.subsetFieldPercent.formAudience ); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get employee sso config') getEmployeeSsoConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getEmployeeSsoConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get amount requested config') getAmountRequestedConfig (service: ComponentConfigurationService) { const config = service.getAmountRequestedConfig('', '', ''); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value, ComponentConfigTabType.Calculated_Value ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get in kind config') getInKindConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Validation, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getInKindConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get care of config') getCareOfConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getCareOfConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get decision config') getDecisionConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Validation, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value ]; const tabsWithComps = this.getTabsWithComponents( service, 'getDecisionConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get designation config') getDesignationConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value ]; const tabsWithComps = this.getTabsWithComponents( service, 'getDesignationConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get report field config') getReportFieldConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getReportFieldConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get recommended funding config') getRecommendedFundingConfig (service: ComponentConfigurationService) { const config = service.getRecommendedFundingConfig('', '', ''); const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Data, ComponentConfigTabType.Validation, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility, ComponentConfigTabType.Set_Value, ComponentConfigTabType.Calculated_Value ]; const tabsWithComps = this.filterTabsToVisible(config); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get special handling config') getSpecialHandlingConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getSpecialHandlingConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get content config') getContentConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getContentConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get columns config') getColumnsConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getColumnsConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get field set config') getFieldSetConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getFieldSetConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get panel config') getPanelConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Display, ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getPanelConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get table config') getTableConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getTableConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } @TestCase('should be able to get well config') getWellConfig (service: ComponentConfigurationService) { const expectedTabsWithComps = [ ComponentConfigTabType.Api, ComponentConfigTabType.Conditional_Visibility ]; const tabsWithComps = this.getTabsWithComponents( service, 'getWellConfig' ); expect(tabsWithComps).to.deep.equal(expectedTabsWithComps); } }