import { Injectable } from '@angular/core'; import { ReferenceFieldAPI } from '@core/typings/api/reference-fields.typing'; import { ReferenceFieldsUI } from '@core/typings/ui/reference-fields.typing'; import { Form, FormAudience, FormDefinition, FormDefinitionComponent, FormDefinitionForUi, FormFieldPasteLocation, FormTypes, FormValueChange, ReportFieldDataOptions } from '@features/configure-forms/form.typing'; import { ExternalAPISelection } from '@features/formio/component-configuration/external-api-selector-settings/external-api-selector-settings.component'; import { FormulaEvaluationType, FormulaStepValueType } from '@features/formula-builder/formula-builder.typing'; import { ConditionalLogicResultType, EvaluationType } from '@features/logic-builder/logic-builder.typing'; import { YcFile } from '@yourcause/common'; import { CurrencyRadioOptions, CurrencyValue } from '@yourcause/common/masking'; import { AfterEach, Spec, TestCase } from '@yourcause/test-decorators'; import { DescribeAngularService } from '@yourcause/test-decorators/angular'; import { expect, spy } from 'chai'; import { FilterModalTypes } from 'frontend-common/src/models/grid.model'; import { ComponentHelperService, EMPLOYEE_SSO_TYPE_PREFIX, REF_COMPONENT_TYPE_PREFIX, Total_Columns } from './component-helper.service'; @Injectable({ providedIn: 'root' }) @DescribeAngularService(ComponentHelperService, { imports: [] }) export class ComponentHelperServiceSpec implements Spec { private readonly flattenColumnsField = { type: 'textfield', label: 'First Name', key: 'firstName' }; private readonly flattenWellField = { type: 'textfield', label: 'First Name', key: 'firstName', placeholder: 'Enter your first name', input: true, validate: { required: true } }; private readonly flattenFieldSetField = { type: 'textfield', key: 'textfield', label: 'Field set first name', input: true, validate: { required: true } }; private readonly flattenTableContentField = { key: 'content', type: 'content' }; private readonly flattenPanelField = { type: 'textfield', label: 'First Name', key: 'firstName', placeholder: 'Enter your first name', input: true, validate: { required: true } }; formDefinitionForFlatten: FormDefinition = { components: [ { type: 'columns', key: 'columns', columns: [ { key: 'columns-1', components: [ this.flattenColumnsField ] } ] }, { type: 'well', key: 'well', components: [ this.flattenWellField ] }, { type: 'fieldset', key: 'fieldset', components: [ this.flattenFieldSetField ] }, { type: 'table', label: 'Table', key: 'table', rows: [ [{ key: '', components: [this.flattenTableContentField] }] ] }, { type: 'panel', key: 'panel', components: [ this.flattenPanelField ] } ] }; uniqueId = '1234'; formId = 23532; revisionId = 2364; dateComponent: FormDefinitionComponent = { key: 'date', label: 'Project start date', type: 'referenceFields-projectStartDate', placeholder: '', validate: { required: false, customMessage: '' }, tooltip: '', title: '', legend: '', description: '', prefix: '', suffix: '', displayType: 1, customValidation: { evaluationType: 2, useAnd: false, identifier: '8be17519d03a46328f60f8a870d4e257ad792a3f706c46acb541c3670da009a2', conditions: [], result: '', resultType: 0 }, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: 'c6b96d79fe7d4743a47708ca6cb589769ee773e9bf204d0c8cb22891ff2d987e', conditions: [] }, conditionalValue: [], errorLabel: '', value: null }; textComponent: FormDefinitionComponent = { key: 'textField', label: 'Text', type: 'referenceFields-beginDate', placeholder: '', validate: { required: false, customMessage: '' }, tooltip: '', title: '', legend: '', description: '', prefix: '', suffix: '', displayType: 1, customValidation: { evaluationType: 2, useAnd: false, identifier: '0b5e630f284148508e755b71665309e4c41b45982955476abb42031587dc6295', conditions: [], result: '', resultType: 0 }, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: 'a75ccd0578a24d7ba9afd7d7908727aa7bf2c27f0838497081ef45195eb83244', conditions: [] }, conditionalValue: [], errorLabel: '', value: '' }; columnsComponent: FormDefinitionComponent = { key: 'columns', label: 'Columns', type: 'columns', placeholder: '', validate: { required: false }, tooltip: '', title: '', legend: '', description: '', prefix: '', suffix: '', displayType: 1, columns: [ { key: 'columns', components: [ this.dateComponent ], width: 6, offset: 0, push: 0, pull: 0 }, { key: 'columns2', components: [ this.textComponent ], width: 6, offset: 0, push: 0, pull: 0 } ], input: false, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: '1aaaef619bf140948896162b3889c886dcbb0b22b21f4dacbe4204f295140928', conditions: [] } }; numberComponent: FormDefinitionComponent = { key: 'number', label: 'Year Founded', type: 'referenceFields-yearFounded', placeholder: '', validate: { required: false, customMessage: '' }, tooltip: '', title: '', legend: '', description: '', prefix: '', suffix: '', displayType: 1, customValidation: { evaluationType: 2, useAnd: false, identifier: '06ee788f1b274cfebad031a73d82030db7d968decd1f405fa4647cdf68edacbf', conditions: [], result: '', resultType: 0 }, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: '33bc576daf4b48039dda2fee3f3af5e9454960dabd954f9abc62edf7b2aedeb1', conditions: [] }, conditionalValue: [], errorLabel: '', value: null }; fieldSetComponent: FormDefinitionComponent = { key: 'fieldset', label: 'Field set ', type: 'fieldset', placeholder: '', validate: { required: false }, tooltip: '', title: '', legend: 'Field Set', description: '', prefix: '', suffix: '', displayType: 1, components: [ this.numberComponent ], input: false, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: '661fd8ee307243ae96f049b567090b4d10ae253f7c6445cfa869259c22906810', conditions: [] } }; checkboxComponent: FormDefinitionComponent = { key: 'checkbox', label: 'Authorized', type: 'referenceFields-authorized', placeholder: '', validate: { required: false, customMessage: ' ' }, tooltip: '', title: '', legend: '', description: '', prefix: '', suffix: '', displayType: 1, customValidation: { evaluationType: 2, useAnd: false, identifier: '941540c06ada4acfb268f7bcbed06d804acc424f030542238a34e4adf6ae1864', conditions: [], result: '', resultType: 0 }, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: 'ea26b05c0fa64995a35cf4e05765f4db3bb834a0fcd04dec9537e3abfd21dfe4', conditions: [] }, conditionalValue: [], errorLabel: '', value: null }; panelComponent: FormDefinitionComponent = { key: 'panel', label: 'Panel', type: 'panel', placeholder: '', validate: { required: false }, tooltip: 'tooltip ', title: 'Panel', legend: '', description: '', prefix: '', suffix: '', displayType: 1, components: [ this.checkboxComponent, this.columnsComponent, this.fieldSetComponent ], input: false, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: '5e6e2c578998497fa6cbfff4f8fc00fec0af4b112ba2492d86149fe1a22d2260', conditions: [] }, collapsible: true }; wellComponent: FormDefinitionComponent = { key: 'well ', label: 'Well', type: 'well', placeholder: '', validate: { required: false }, tooltip: '', title: '', legend: '', description: 'desc ', prefix: '', suffix: '', displayType: 1, components: [ this.panelComponent ], input: false, conditionalLogic: { evaluationType: 2, useAnd: false, identifier: '349a0c5566c6451a9c234938d67cafa15ec2e2acc1e841f48eaafa74f9a0757b', conditions: [] } }; formDefinition: FormDefinitionForUi[] = [{ tabName: 'Page One', components: [ this.wellComponent ], uniqueId: '3ac43ccf-e30f-4aea-8f2c-8fbdf1b566cd', index: 0, logic: null }]; externalApiKey = 'external'; textFieldKey = 'text'; expectedResult = 588; tabs: FormDefinitionForUi[] = [{ tabName: 'tab1', logic: null, uniqueId: this.uniqueId, components: [{ type: `referenceFields-${this.textFieldKey}`, key: this.textFieldKey, conditionalValue: [ { evaluationType: 0, useAnd: false, identifier: '0c2b80d02da645fda27ce41625d483c7d315ee955ada45d29c41e51085983bb6', conditions: [ { sourceColumn: [ 'referenceFields', this.textFieldKey ], comparison: 'eq', value: true, useAnd: false, identifier: '8d85af50598a4487b559e06eb7079d9d48ad2f8052d94068b8748012c3873b8a' } as any ], result: this.expectedResult, resultType: ConditionalLogicResultType.STATIC_VALUE } ], validate: { required: true } }, { type: 'amountRequested', key: 'amountRequested', validate: { required: true }, formula: { property: 'referenceFields.budgetAmountTotal', step: { type: FormulaEvaluationType.Add, values: [ { value: 'referenceFields.amount2', type: FormulaStepValueType.ParentValue }, { value: 'referenceFields.budgetAmountQ2', type: FormulaStepValueType.ParentValue }, { type: FormulaStepValueType.ParentValue, value: 'referenceFields.budgetAmountQ3' }, { type: FormulaStepValueType.ParentValue, value: 'referenceFields.budgetAmountQ4' } ] } } }], index: 0 }, { tabName: 'tab2', logic: null, uniqueId: '1353464', components: [{ type: 'inKindItems', key: 'inKindItems', validate: { required: false }, conditionalLogic: { evaluationType: EvaluationType.ConditionallyTrue, useAnd: false, identifier: 'cfb9fded1d714d4bbe6575809b56527a4ffdb95f00ec4327aa352169a59d7b33', conditions: [ { sourceColumn: [ 'application', 'amountRequested' ], comparison: 'gt', value: 500, useAnd: false, identifier: '11901a36f65b4e86a86d2aca074ea7bda9ece5a4923c4a64af5b839eca6dbf59' } ] } as any }], index: 1 }]; form: Form = { title: '', name: 'Test Form', path: '', id: this.formId, description: '', createdDate: '', updatedDate: '', formDefinition: this.tabs, formType: FormTypes.REQUEST, version: 1, canModify: true, availableForTranslation: true, defaultLanguageId: '', externalApiRequestIds: [], referenceFieldIds: [], requireSignature: false, signatureDescription: '' }; contentComponents = [{ key: 'content1', type: 'content' }, { key: 'content2', type: 'content' }, { key: 'any', type: 'notContent' }]; tableComponent: FormDefinitionComponent = { key: 'table', rows: [ [{ components: [{ key: 'content', type: 'content' }] }], [{ components: [{ key: 'refField1', type: 'referenceFields-text' }, { key: 'columns', type: 'columns', columns: [{ key: 'column1', type: 'columns', components: [{ key: 'refField2', type: 'referenceFields-select' }] }] }] }], [{ components: [{ key: 'refField3', type: 'referenceFields-radio' }] }] ] as FormDefinitionComponent[][] }; subsetFieldPercent: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: true, aggregateType: null, referenceFieldId: 7964, parentReferenceFieldId: null, formCount: 1, usedOnReports: true, createdBy: '', createDate: '', updateDate: '', updatedBy: '', customDataTableGuid: '', name: 'Subset field - percent', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.Subset, key: 'subsetKey', supportsMultiple: false, categoryId: null, formAudience: FormAudience.MANAGER, isSingleResponse: true, tableAllowsImport: false, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: 32095, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: ReferenceFieldAPI.DataSetCollectionType.Percent }; tableField1: ReferenceFieldAPI.ReferenceFieldDisplayModel = { customDataTableGuid: '', name: 'Table 1', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.Table, key: 'tableKey1', supportsMultiple: false, categoryId: 0, formAudience: FormAudience.APPLICANT, referenceFieldId: 12421, formCount: 1, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', aggregateType: null, updateDate: '', parentReferenceFieldId: null, isEncrypted: false, isMasked: false, tableAllowsImport: false, isSingleResponse: true, isTableField: false, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; fileUploadFieldForTable: ReferenceFieldAPI.ReferenceFieldDisplayModel = { customDataTableGuid: '', name: 'File Upload For Table 1', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.FileUpload, key: 'fileUploadTableKey', supportsMultiple: false, categoryId: 0, formAudience: FormAudience.APPLICANT, referenceFieldId: 235237, formCount: 1, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', aggregateType: null, updateDate: '', parentReferenceFieldId: null, isEncrypted: false, isMasked: false, tableAllowsImport: false, isSingleResponse: true, isTableField: true, aggregateTableReferenceFieldId: null, referenceFieldTableId: null, standardComponentIsPublished: true, isStandardProductField: false, subsetCollectionType: null }; refResponseMap: ReferenceFieldsUI.RefResponseMap = { [this.subsetFieldPercent.key]: [], [this.tableField1.key]: [{ rowId: 1, columns: [{ referenceFieldId: this.fileUploadFieldForTable.referenceFieldId, referenceFieldKey: this.fileUploadFieldForTable.key, value: [ new YcFile( 'file name', null, `https://yourcausegrantsqa.com/apply/download-file?applicationId=160574&applicationFormId=157406&fileId=${this.fileUploadFieldForTable.referenceFieldId}&fileName=Screen%20Shot%202021-07-15%20at%2010.09.05%20AM.png`, this.fileUploadFieldForTable.referenceFieldId ) ], dateValue: null, currencyValue: null, numericValue: null, file: null, files: [], applicationFormId: 1, applicationId: 2 }] }] }; @AfterEach() restore () { spy.restore(); } @TestCase('should be able to flatten a form definition') testShouldFlattenFormDefinition (service: ComponentHelperService): void { const flattened = service.flattenFormDefinition(this.formDefinitionForFlatten); expect(flattened).to.deep.equal([ this.flattenColumnsField, this.flattenWellField, this.flattenFieldSetField, this.flattenTableContentField, this.flattenPanelField ]); } @TestCase('should be able to do each component - no layout comps') eachComponent (service: ComponentHelperService) { const compKeysIteratedOver: string[] = []; const func = (comp: FormDefinitionComponent) => { compKeysIteratedOver.push(comp.key); }; service.eachComponent(this.formDefinition[0].components, func); const expectedCompKeys = [ this.numberComponent.key, this.checkboxComponent.key, this.dateComponent.key, this.textComponent.key ]; expect(compKeysIteratedOver.length).to.be.equal(expectedCompKeys.length); const hasAll = expectedCompKeys.every((compKey) => { return compKeysIteratedOver.includes(compKey); }); expect(hasAll).to.be.true; } @TestCase('should be able to do each component - with layout comps') eachComponentWithLayoutComps (service: ComponentHelperService) { const compKeysIteratedOver: string[] = []; const func = (comp: FormDefinitionComponent) => { compKeysIteratedOver.push(comp.key); }; service.eachComponent(this.formDefinition[0].components, func, true); const expectedCompKeys = [ this.wellComponent.key, this.panelComponent.key, this.fieldSetComponent.key, this.columnsComponent.key, this.numberComponent.key, this.checkboxComponent.key, this.dateComponent.key, this.textComponent.key ]; expect(compKeysIteratedOver.length).to.be.equal(expectedCompKeys.length); const hasAll = expectedCompKeys.every((compKey) => { return compKeysIteratedOver.includes(compKey); }); expect(hasAll).to.be.true; } @TestCase('should be able to get is layout component') isLayoutComponent (service: ComponentHelperService) { let isLayout = service.isLayoutComponent('well'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('panel'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('content'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('table'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('panel'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('fieldset'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('columns'); expect(isLayout).to.be.true; isLayout = service.isLayoutComponent('referenceFields-type'); expect(isLayout).to.be.false; isLayout = service.isLayoutComponent('employeeInfo-field'); expect(isLayout).to.be.false; } @TestCase('should be able to get is standard component') isStandardComponent (service: ComponentHelperService) { let isStandard = service.isStandardComponent('amountRequested'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('designation'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('reviewerRecommendedFundingAmount'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('inKindItems'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('decision'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('specialHandling'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('careOf'); expect(isStandard).to.be.true; isStandard = service.isStandardComponent('content'); expect(isStandard).to.be.false; isStandard = service.isStandardComponent('employeeInfo-field'); expect(isStandard).to.be.false; } @TestCase('should be able to extract visibility') isCompVisible (service: ComponentHelperService) { let visible = service.isCompVisible({ key: 'visibleComp', isHidden: false }); expect(visible).to.be.true; visible = service.isCompVisible( { key: 'hiddenComp', isHidden: true } ); expect(visible).to.be.false; visible = service.isCompVisible( { key: 'hidden from parent', hiddenFromParent: true } ); expect(visible).to.be.false; } @TestCase('should be able to get nested components') getNestedComponents (service: ComponentHelperService) { const components = service.getNestedComponents(this.wellComponent); const expectedCompKeys = [ this.numberComponent.key, this.checkboxComponent.key, this.dateComponent.key, this.textComponent.key ]; const compKeys = components.map((comp) => { return comp.key; }); expect(components.length).to.be.equal(expectedCompKeys.length); const hasAll = expectedCompKeys.every((compKey) => { return compKeys.includes(compKey); }); expect(hasAll).to.be.true; } @TestCase('should be able to return flat list of components (non-layout)') testShouldReturnFlatListOfComponents (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2' }; const wellComp = { type: 'well', key: 'well1', components: [reportField] }; const amountRequestedComp = { type: 'amountRequested', key: 'amountRequested', validate: { required: true } }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [amountRequestedComp, wellComp], index: 0 }; const flatList = service.getAllComponents([formDef], false); expect(flatList).to.deep.equal([ amountRequestedComp, reportField ]); } @TestCase('should be able to return flat list of components (layout)') testShouldReturnFlatListOfComponents2 (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2' }; const wellComp = { type: 'well', key: 'well1', components: [reportField] }; const amountRequestedComp = { type: 'amountRequested', key: 'amountRequested', validate: { required: true } }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [amountRequestedComp, wellComp], index: 0 }; const flatList = service.getAllComponents([formDef], true); expect(flatList).to.deep.equal([ amountRequestedComp, wellComp, reportField ]); } @TestCase('should be able to get required components') getRequiredComponents (service: ComponentHelperService) { const requiredComps = service.getRequiredComponents( [{ tabName: 'One', uniqueId: '', index: 0, logic: null, components: [{ key: 'Hidden required comp', validate: { required: true }, hiddenFromParent: true }] }, { tabName: 'Two', uniqueId: '', index: 0, logic: null, components: [{ key: 'non required comp' }, { key: 'Visible required comp', validate: { required: true } }] }] ); expect(requiredComps.length).to.be.equal(1); const foundRequiredField = requiredComps.some((comp) => { return comp.key === 'Visible required comp'; }); expect(foundRequiredField).to.be.true; } @TestCase('should be able to get adapted type from component type') getAdaptedTypeFromComponentType (service: ComponentHelperService) { let adapted = service.getAdaptedTypeFromComponentType('referenceFields-key'); expect(adapted).to.be.equal('referenceField'); adapted = service.getAdaptedTypeFromComponentType(`${EMPLOYEE_SSO_TYPE_PREFIX}-key`); expect(adapted).to.be.equal('employeeSSO'); adapted = service.getAdaptedTypeFromComponentType('amountRequested'); expect(adapted).to.be.equal('amountRequested'); adapted = service.getAdaptedTypeFromComponentType('htmlelement'); expect(adapted).to.be.equal('content'); } @TestCase('should be able to get is comp applicable for pdf - dont skip visibility') isComponentApplicableForPdf (service: ComponentHelperService) { const skipVisibility = false; let isApplicable = service.isComponentApplicableForPdf( { ...this.numberComponent, hiddenFromParent: true }, skipVisibility ); // Hidden so not applicable expect(isApplicable).to.be.false; isApplicable = service.isComponentApplicableForPdf( { ...this.numberComponent, hiddenFromParent: false, isHidden: false }, skipVisibility ); // Not hidden so is applicable expect(isApplicable).to.be.true; } @TestCase('should be able to get is comp applicable for pdf - skip visibility') isComponentApplicableForPdf2 (service: ComponentHelperService) { const skipVisibility = true; const isApplicable = service.isComponentApplicableForPdf( { ...this.numberComponent, hiddenFromParent: true, isHidden: true }, skipVisibility ); // We don't care about visibility, so true expect(isApplicable).to.be.true; } @TestCase('should be able to get blank column comp - no existing columns') getBlankColumnComponent (service: ComponentHelperService) { const blankColumnComp = service.getBlankColumnComponent(); expect(blankColumnComp.key).to.be.equal('column'); expect(blankColumnComp.width).to.be.equal(6); expect(blankColumnComp.offset).to.be.equal(0); expect(blankColumnComp.pull).to.be.equal(0); expect(blankColumnComp.push).to.be.equal(0); expect(blankColumnComp.type).to.be.equal('column'); expect(blankColumnComp.components.length).to.be.equal(0); } @TestCase('should be able to get blank column comp - with existing columns') getBlankColumnComponentWithExisting (service: ComponentHelperService) { const columns: FormDefinitionComponent[] = [{ width: 3 } as FormDefinitionComponent]; const blankColumnComp = service.getBlankColumnComponent(columns); expect(blankColumnComp.key).to.be.equal('column'); expect(blankColumnComp.width).to.be.equal(Total_Columns - columns[0].width); expect(blankColumnComp.offset).to.be.equal(0); expect(blankColumnComp.pull).to.be.equal(0); expect(blankColumnComp.push).to.be.equal(0); expect(blankColumnComp.type).to.be.equal('column'); expect(blankColumnComp.components.length).to.be.equal(0); } @TestCase('should be able to get can column comp add columns') canColumnCompAddColumns (service: ComponentHelperService) { let columns: FormDefinitionComponent[] = [{ width: 10 } as FormDefinitionComponent]; let canAdd = service.canColumnCompAddColumns(columns); expect(canAdd).to.be.true; columns = [{ width: 12 } as FormDefinitionComponent]; canAdd = service.canColumnCompAddColumns(columns); expect(canAdd).to.be.false; } @TestCase('should be able to get can column comp add columns') getTotalColumnWidth (service: ComponentHelperService) { let columns: FormDefinitionComponent[] = [{ width: 10 } as FormDefinitionComponent, { width: 5 } as FormDefinitionComponent]; let total = service.getTotalColumnWidth(columns); expect(total).to.be.equal(15); columns = [{ width: 1 } as FormDefinitionComponent, { width: 4 } as FormDefinitionComponent]; total = service.getTotalColumnWidth(columns); expect(total).to.be.equal(5); } @TestCase('should be able to remove a component from a well') testShouldReplaceComponentFromWell (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2', label: 'old label' }; const reportField2 = { type: 'reportField', key: 'reportField2', label: 'new label' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'well', key: 'well1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }], index: 0 }; service.removeOrReplaceFormComponent(reportField, formDef, reportField2); expect(formDef.components).to.deep.equal([{ type: 'well', key: 'well1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField2] }]); } @TestCase('should be able to remove a component from a well') testShouldRemoveComponentFromWell (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'well', key: 'well1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }], index: 0 }; service.removeOrReplaceFormComponent(reportField, formDef); expect(formDef.components).to.deep.equal([{ type: 'well', key: 'well1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }] }]); } @TestCase('should be able to remove a component from columns') testShouldRemoveComponentFromColumns (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'columns', key: 'columns1', columns: [{ key: 'column1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }] }], index: 0 }; service.removeOrReplaceFormComponent(reportField, formDef); expect(formDef.components).to.deep.equal([{ type: 'columns', key: 'columns1', columns: [{ key: 'column1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }] }] }]); } @TestCase('should be able to remove a component from rows') testShouldRemoveComponentFromRows (service: ComponentHelperService) { const reportField = { type: 'reportField', key: 'reportField2' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'rows', key: 'rows1', rows: [[{ components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }]] as FormDefinitionComponent[][] }], index: 0 }; service.removeOrReplaceFormComponent(reportField, formDef); expect(formDef.components).to.deep.equal([{ type: 'rows', key: 'rows1', rows: [[{ components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }] }]] }]); } @TestCase('should be able to insert a component to a form definition') testShouldInsertComponentIntoFormDef (service: ComponentHelperService) { const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'reportField', key: 'reportField' }, { type: 'amountRequested', key: 'amountRequested', validate: { required: true } }], index: 0 }; const componentToInsert = { type: 'reportField', key: 'reportField2' }; const currentComponentLength = formDef.components.length; service.insertFormComponent( componentToInsert, formDef ); expect(formDef.components.length).to.equal(currentComponentLength + 1); expect(formDef.components[currentComponentLength]).to.equal(componentToInsert); } @TestCase('should be able to insert a component to a form definition relative to another component') testShouldInsertComponentIntoFormDefRelative (service: ComponentHelperService) { const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'reportField', key: 'reportField' }, { type: 'amountRequested', key: 'amountRequested', validate: { required: true } }], index: 0 }; const componentToInsert = { type: 'reportField', key: 'reportField2' }; const currentComponentLength = formDef.components.length; service.insertFormComponent( componentToInsert, formDef, formDef.components[0] ); expect(formDef.components.length).to.equal(currentComponentLength + 1); expect(formDef.components[1]).to.equal(componentToInsert); } @TestCase('should be able to insert form component into columns') insertFormComponentColumns (service: ComponentHelperService) { const componentToInsert = { type: 'referenceFields-gcStandardField_score115', key: 'PartnershipAlignmentScore' }; const relativeComponent = { type: 'content', key: 'content' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'fieldset', key: 'fieldset', components: [{ type: 'columns', key: 'columns', columns: [{ key: 'column', components: [{ key: componentToInsert.key }] }, { key: 'column', components: [{ key: relativeComponent.key, type: 'content' }] }] }] }], index: 0 }; service.insertFormComponent( componentToInsert, formDef, relativeComponent ); const columns = formDef.components[0].components[0].columns; const hasInserted = columns[1].components[1].key === componentToInsert.key; expect(hasInserted).to.be.true; } @TestCase('should be able to insert form component into rows') insertFormComponentRows (service: ComponentHelperService) { const componentToInsert = { type: 'referenceFields-gcStandardField_score115', key: 'PartnershipAlignmentScore' }; const relativeComponent = { type: 'content', key: 'content' }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'table', key: 'rows', rows: [ [{ components: [{ key: componentToInsert.key }], key: '' }, { components: [{ key: relativeComponent.key }], key: '' }, { components: [], key: '' }], [{ components: [], key: '' }, { components: [], key: '' }, { components: [], key: '' }], [{ components: [], key: '' }, { components: [], key: '' }, { components: [], key: '' }] ] }], index: 0 }; service.insertFormComponent( componentToInsert, formDef, relativeComponent ); const hasInserted = formDef.components[0].rows[0][1].components[1].key === componentToInsert.key; expect(hasInserted).to.be.true; } @TestCase('test cant find parent component') testCantFindComponentParent (service: ComponentHelperService) { const formDef = { components: [] } as FormDefinitionForUi; const field = { type: 'reportField', key: 'key' }; const found = service.getParentComponent(field, formDef); const notFound = !found; expect(notFound).to.be.true; } @TestCase('should be able to find a component by key') testShouldFindComponentParent (service: ComponentHelperService) { const compKey = 'reportField2'; const reportField = { type: 'reportField', key: compKey }; const wellComp = { type: 'well', key: 'well1', components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [wellComp], index: 0 }; const found = service.getParentComponent(reportField, formDef); expect(found).to.deep.equal(wellComp); } @TestCase('should be able to find a component by key - empty') testShouldFindComponentByKeyEmpty (service: ComponentHelperService) { const formDefs: FormDefinitionForUi[] = [{ components: [null] } as FormDefinitionForUi]; const result = service.findComponentByKey(formDefs, null); const noComp = !result; expect(noComp).to.be.true; } @TestCase('should be able to find a component by key') testShouldFindComponentByKey (service: ComponentHelperService) { const compKey = 'reportField2'; const reportField = { type: 'reportField', key: compKey }; const formDef: FormDefinitionForUi = { tabName: 'tab1', logic: null, uniqueId: 'qfj3235', components: [{ type: 'rows', key: 'rows1', rows: [[{ components: [{ type: 'amountRequested', key: 'amountRequested', validate: { required: true } }, reportField] }]] as FormDefinitionComponent[][] }], index: 0 }; const found = service.findComponentByKey([formDef], compKey); expect(found).to.deep.equal(reportField); } @TestCase('should be able to check if comp type exists on tab') checkIfCompTypeExistsOnTab (service: ComponentHelperService) { const formDef: FormDefinitionForUi = { tabName: 'One', logic: null, index: 0, uniqueId: '', components: [{ type: 'amountRequested' } as FormDefinitionComponent, { type: 'designation' } as FormDefinitionComponent] }; let exists = service.checkIfCompTypeExistsOnTab( 'amountRequested', formDef ); expect(exists).to.be.true; exists = service.checkIfCompTypeExistsOnTab( 'inKindItems', formDef ); expect(exists).to.be.false; } @TestCase('should be able to tell if form has amount requested') formHasAmountRequested (service: ComponentHelperService) { let hasAmountRequested = service.formHasAmountRequested([{ index: 0, tabName: 'one', logic: null, uniqueId: '23523523', components: [{ key: 'amount' }] }]); expect(hasAmountRequested).to.be.false; hasAmountRequested = service.formHasAmountRequested([{ index: 0, tabName: 'one', logic: null, uniqueId: '23523523', components: [{ key: 'amount', type: 'amountRequested' }] }]); expect(hasAmountRequested).to.be.true; } @TestCase('should be able to get is ref field comp type') isRefFieldCompType (service: ComponentHelperService) { let isRefField = service.isReferenceFieldComp('referenceFields-asdf'); expect(isRefField).to.be.true; isRefField = service.isReferenceFieldComp('employeeInfo-region'); expect(isRefField).to.be.false; } @TestCase('should be able to get is comp disabled - true') isCompDisabledTrue (service: ComponentHelperService) { const comp = { conditionalValue: [{ conditions: [], evaluationType: EvaluationType.ConditionallyTrue, useAnd: true, identifier: 'asdf' }] } as FormDefinitionComponent; let disabled = service.isCompDisabled(comp); expect(disabled).to.be.true; comp.disabled = true; comp.conditionalValue = []; disabled = service.isCompDisabled(comp); expect(disabled).to.be.true; } @TestCase('should be able to get is comp disabled - false') isCompDisabledFalse (service: ComponentHelperService) { const comp = { conditionalValue: [] } as FormDefinitionComponent; const disabled = service.isCompDisabled(comp); expect(disabled).to.be.false; } @TestCase('should be able to get is comp disabled - calculated override') isCompDisabledOverride (service: ComponentHelperService) { const comp = { allowCalculateOverride: true } as FormDefinitionComponent; const disabled = service.isCompDisabled(comp); expect(disabled).to.be.false; } @TestCase('should be able to get is comp disabled - empty') isCompDisabledEmpty (service: ComponentHelperService) { const disabled = service.isCompDisabled(undefined); expect(disabled).to.be.false; } @TestCase('should be able to get is comps from table column') getComponentFromTableColumn (service: ComponentHelperService) { const tableColumn: ReferenceFieldsUI.TableFieldForUi = { referenceFieldId: 3464, referenceFieldName: '% affected', label: '% affected', isRequired: true, showInTable: true, columnOrder: 1, aggregateColumnReferenceFieldId: 253, summarizeData: true, summarizeLabel: '', referenceField: { key: 'percentAffected' } as ReferenceFieldAPI.ReferenceFieldDisplayModel }; const comp = service.getComponentFromTableColumn(tableColumn); const expectedType = `referenceFields-${tableColumn.referenceField.key}`; expect(comp.type).to.be.equal(expectedType); expect(comp.key).to.be.equal(tableColumn.referenceField.key); expect(comp.validate.required).to.be.true; } @TestCase('should be able to adapt conditional value') adaptConditionalValue (service: ComponentHelperService) { const comp = { conditionalValue: [{}], type: 'amountRequested' } as FormDefinitionComponent; service.adaptConditionalValue(comp, true); comp; const hasEmptyConditions = comp.conditionalValue[0].conditions.length === 0; expect(hasEmptyConditions).to.be.true; } @TestCase('should be able to adapt conditional value - currencies') adaptConditionalValueCurrencies (service: ComponentHelperService) { const amount = 5; const comp = { key: '', conditionalValue: [{ conditions: [], useAnd: false, identifier: '', evaluationType: EvaluationType.ConditionallyTrue, resultType: ConditionalLogicResultType.STATIC_VALUE, result: { amount, currency: 'USD' } as any }], type: 'amountRequested' } as FormDefinitionComponent; service.adaptConditionalValue(comp, true); const converted = comp.conditionalValue[0]; const updatedResult = (converted.result as CurrencyValue).amountEquivalent === amount; expect(updatedResult).to.be.true; } @TestCase('should be able to adapt conditional logic') adaptConditionalLogic (service: ComponentHelperService) { const comp = { conditionalLogic: { evaluationType: EvaluationType.ConditionallyTrue, conditions: [] } } as FormDefinitionComponent; service.adaptConditionalLogic(comp); const hasAdapted = comp.conditionalLogic.evaluationType === EvaluationType.AlwaysTrue; expect(hasAdapted).to.be.true; } @TestCase('should be able to parse configuration options - report field') parseConfigurationOptionsReportField (service: ComponentHelperService) { const reportFieldDataOptions: ReportFieldDataOptions = { reportFieldObject: 'object', reportFieldDisplay: 'display' }; const comp = { type: 'reportField', key: 'reportKey', reportFieldDataOptions: JSON.stringify(reportFieldDataOptions) as any } as FormDefinitionComponent; service.parseConfigurationOptions(comp); expect(comp.reportFieldDataOptions).to.deep.equal(reportFieldDataOptions); } @TestCase('should be able to parse configuration options - in kind') parseConfigurationOptionsInKind (service: ComponentHelperService) { const items: string[] = ['item1', 'item2']; const comp = { type: 'inKindItems', key: 'inKind', items: JSON.stringify(items) as any } as FormDefinitionComponent; service.parseConfigurationOptions(comp); expect(comp.items).to.deep.equal(items); } @TestCase('should be able to parse configuration options - external api') parseConfigurationOptionsExternalApi (service: ComponentHelperService) { const apiConfig: ExternalAPISelection = { integrationId: '12423532', responseField: 'responseField' }; const comp = { type: `referenceFields-${this.externalApiKey}`, key: this.externalApiKey, apiConfig: JSON.stringify(apiConfig) as any } as FormDefinitionComponent; service.parseConfigurationOptions(comp); expect(comp.apiConfig).to.deep.equal(apiConfig); } @TestCase('should be able to get value / comparison for conditional logic adapting of checkbox field true') getValueAndConditionCheckboxTrue (service: ComponentHelperService) { const value = 'true'; const type = 'list'; const compType = 'panel'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.equals); expect(result.value).to.be.equal(true); } @TestCase('should be able to get value / comparison for conditional logic adapting of checkbox field false') getValueAndConditionCheckboxFalse (service: ComponentHelperService) { const value = 'false'; const type = 'list'; const compType = 'panel'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.equals); expect(result.value).to.be.equal(false); } @TestCase('should be able to get value / comparison for conditional logic adapting of text field') getValueAndConditionNumber (service: ComponentHelperService) { const value = 'sample text'; const type = 'text'; const compType = 'amountRequested'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.equals); expect(result.value).to.be.equal(value); } @TestCase('should be able to get value / comparison for conditional logic adapting of decision field') getValueAndConditionDecision (service: ComponentHelperService) { const value = '1'; const type = 'multi-list'; const compType = 'decision'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.equals); expect(result.value).to.deep.equal([1]); } @TestCase('should be able to get value / comparison for conditional logic - multi') getValueAndConditionMultiList (service: ComponentHelperService) { const value = 'text'; const type = 'multi-list'; const compType = 'multiListField'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.equals); expect(result.value).to.deep.equal(['text']); } @TestCase('should be able to get value / comparison for conditional logic adapting of multi value text field') getValueAndConditionMultiValueText (service: ComponentHelperService) { const value = '1'; const type = 'multiValueText'; const compType = 'amountRequested'; const result = service.getValueAndCondition( value, type, compType ); expect(result.comparison).to.be.equal(FilterModalTypes.multiValueEquals); expect(result.value).to.deep.equal([value]); } @TestCase('should be able to get the components from a tab') getComponentsFromTab (service: ComponentHelperService) { const compsFromTab = service.getComponentsFromTab( this.form, this.uniqueId ); const expectedComps = this.tabs[0].components; expect(compsFromTab).to.deep.equal(expectedComps); } @TestCase('should be able to validate when adding comps from another page - pass') testAddingCompsFromAnotherPagePass (service: ComponentHelperService) { const { duplicateFields, duplicateKeys } = service.getDuplicateKeysAndFields( this.form, this.uniqueId, [] ); expect(duplicateKeys.length).to.be.equal(0); expect(duplicateFields.length).to.be.equal(0); } @TestCase('should be able to validate when adding comps from another page - fail') testAddingCompsFromAnotherPageFail (service: ComponentHelperService) { const { duplicateFields, duplicateKeys } = service.getDuplicateKeysAndFields( this.form, this.uniqueId, [ { key: this.tabs[0].components[0].key } as FormDefinitionComponent, { type: 'amountRequested' } as FormDefinitionComponent ] ); const duplicateKey = this.tabs[0].components[0].key; expect(duplicateKeys.length).to.be.equal(1); expect(duplicateKeys[0].key).to.be.equal(duplicateKey); const duplicateFieldType = this.tabs[0].components[1].type; expect(duplicateFields.length).to.be.equal(1); expect(duplicateFields[0].type).to.be.equal(duplicateFieldType); } @TestCase('should be able to get currency from form field control - stored') getCurrencyForFormFieldControlStored (service: ComponentHelperService) { const stored = 'CAD'; const currency = service.getCurrencyForFormFieldControl( stored, CurrencyRadioOptions.USE_ANY_CURRENCY, 'CAD', [], 'USD', '' ); expect(currency).to.be.equal(stored); } @TestCase('should be able to get currency from form field control - comp setting') getCurrencyForFormFieldControlComp (service: ComponentHelperService) { const compSetting = 'EUR'; const currency = service.getCurrencyForFormFieldControl( '', CurrencyRadioOptions.USE_ONE_CURRENCY, compSetting, [], 'USD', '' ); expect(currency).to.be.equal(compSetting); } @TestCase('should be able to get currency from form field control - last selected found') getCurrencyForFormFieldControlCompLastSelectedFound (service: ComponentHelperService) { const lastSelected = 'EUR'; const currency = service.getCurrencyForFormFieldControl( '', CurrencyRadioOptions.USE_ANY_CURRENCY, '', [{ label: 'EUR', value: 'EUR' }, { label: 'USD', value: 'USD' }], 'USD', lastSelected ); expect(currency).to.be.equal(lastSelected); } @TestCase('should be able to get currency from form field control - last selected not found') getCurrencyForFormFieldControlCompLastSelectedNotFound (service: ComponentHelperService) { const lastSelected = 'CAD'; const defaultCurrency = 'USD'; const currency = service.getCurrencyForFormFieldControl( '', CurrencyRadioOptions.USE_ANY_CURRENCY, '', [{ label: 'EUR', value: 'EUR' }, { label: 'USD', value: 'USD' }], defaultCurrency, lastSelected ); expect(currency).to.be.equal(defaultCurrency); } @TestCase('should be able to replace standard text') replaceStandardText (service: ComponentHelperService) { const translation = 'Translated checkbox label'; service.replaceStandardText( this.formDefinition, { [this.checkboxComponent.label]: translation } ); let labelIsTranslated = false; this.formDefinition.forEach((tab) => { service.eachComponent(tab.components, (comp) => { if (comp.key === this.checkboxComponent.key) { labelIsTranslated = comp.label === translation; } }); }); expect(labelIsTranslated).to.be.true; } @TestCase('should be able to replace rich text') replaceRichText (service: ComponentHelperService) { const translation = 'Translated html'; const html = '

some html

'; const formDef: FormDefinitionForUi[] = [{ tabName: 'Page One', components: [{ type: 'content', key: 'content', html }], uniqueId: '3ac43ccf-e30f-4aea-8f2c-8fbdf1b566cd', index: 0, logic: null }]; service.replaceRichText( formDef, { [html]: translation } ); let htmlIsTranslated = false; formDef.forEach((tab) => { service.eachComponent(tab.components, (comp) => { if (comp.key === 'content') { htmlIsTranslated = comp.html === translation; } }); }); expect(htmlIsTranslated).to.be.true; } @TestCase('should be able to apply translations to components') applyTranslationsToComponents (service: ComponentHelperService) { spy.on(service, 'replaceStandardText'); spy.on(service, 'replaceRichText'); service.applyTranslationsToComponents( this.formDefinition, {}, {} ); expect(service.replaceStandardText).to.have.been.called.once; expect(service.replaceRichText).to.have.been.called.once; } @TestCase('should be able to adapt initial custom validation') adaptInitialCustomValidation (service: ComponentHelperService) { const adapted = service.adaptInitialCustomValidation('return null;'); const isCleared = !adapted; expect(isCleared).to.be.equal(true); } @TestCase('should be able to clear conditional') clearConditional (service: ComponentHelperService) { const comp = { conditional: { show: 'one', when: 'two', eq: 'true' } } as FormDefinitionComponent; service.clearConditional(comp); const isCleared = !comp.conditional?.show; expect(isCleared).to.be.true; const hasOldConditional = !!comp.oldConditonal; expect(hasOldConditional).to.be.true; } @TestCase('should be able to determine correct calculated value result - no override') determineCorrectCalculatedValueNoOverride (service: ComponentHelperService) { const currentRunResult = 34; const result = service.determineCorrectCalculatedValueResult( true, currentRunResult, 4, 2, 'amountRequested', false ); expect(result.usedRunResult).to.be.true; expect(result.currentValue).to.be.equal(currentRunResult); } @TestCase('should be able to determine correct calculated value result - first run') determineCorrectCalculatedValueFirstRun (service: ComponentHelperService) { const currentRunResult = 34; const currentValue = 2; const isFirst = true; const result = service.determineCorrectCalculatedValueResult( isFirst, currentRunResult, 4, currentValue, 'amountRequested', true ); result; expect(result.usedRunResult).to.be.false; expect(result.currentValue).to.be.equal(currentValue); } @TestCase('should be able to determine correct calculated value result - not first run') determineCorrectCalculatedValueNotFirstRun (service: ComponentHelperService) { const currentRunResult = 34; const currentValue = 4; const previous = 4; const isFirst = false; const result = service.determineCorrectCalculatedValueResult( isFirst, currentRunResult, previous, currentValue, 'amountRequested', true ); result; expect(result.usedRunResult).to.be.true; expect(result.currentValue).to.be.equal(currentRunResult); } @TestCase('should be able to get comp input data') getComponentInputData (service: ComponentHelperService) { const comp = { key: 'compKey', label: 'Comp label', type: 'amountRequested' } as FormDefinitionComponent; const data = service.getComponentInputData(comp); expect(data.key).to.be.equal(comp.key); expect(data.label).to.be.equal(comp.label); expect(data.type).to.be.equal(comp.type); } @TestCase('should be able to get comp input data - button') getComponentInputDataButton (service: ComponentHelperService) { const comp = { key: 'compKey', label: 'Comp label', type: 'button' } as FormDefinitionComponent; const data = service.getComponentInputData(comp); const noData = !data; expect(noData).to.be.true; } @TestCase('should be able to trim form definition data') trimFromDefinitionData (service: ComponentHelperService) { service.trimFromDefinitionData(this.formDefinition); let keyPasses = false; let customMessagePasses = false; let tooltipPasses = false; let labelPasses = false; this.formDefinition.forEach((tab) => { service.eachComponent(tab.components, (comp) => { switch (comp.type) { case this.wellComponent.type: keyPasses = comp.description === this.wellComponent.description.trim(); break; case this.checkboxComponent.type: customMessagePasses = comp.validate.customMessage === this.checkboxComponent.validate.customMessage.trim(); break; case this.panelComponent.type: tooltipPasses = comp.tooltip === this.panelComponent.tooltip.trim(); break; case this.fieldSetComponent.type: labelPasses = comp.label === this.fieldSetComponent.label.trim(); break; } }, true); }); expect(keyPasses).to.be.true; expect(customMessagePasses).to.be.true; expect(labelPasses).to.be.true; expect(tooltipPasses).to.be.true; } @TestCase('should be able to get content keys from form def') getContentKeysFromFormDef (service: ComponentHelperService) { const contentKeys = service.getContentKeysFromFormDef([{ index: 0, tabName: 'one', logic: null, uniqueId: '23523523', components: this.contentComponents }]); expect(contentKeys.length).to.be.equal(2); } @TestCase('should be able to remove content from form data') removeContentFromFormData (service: ComponentHelperService) { const formData = { content1: '', content2: '', notContent: '' }; const formDef: FormDefinitionForUi[] = [{ index: 0, tabName: 'one', logic: null, uniqueId: '23523523', components: this.contentComponents }]; service.removeContentFromFormData(formData, formDef); expect(Object.keys(formData).length).to.be.equal(1); expect(formData.notContent).to.not.be.undefined; } @TestCase('should be able to extract ref field components') extractReferenceFieldComponents (service: ComponentHelperService) { const refComponent: FormDefinitionComponent = { key: 'refField', type: `${REF_COMPONENT_TYPE_PREFIX}${this.textFieldKey}` }; const refFields = [ { key: 'non ref field', type: 'content' }, refComponent ]; const extracted = service.extractReferenceFieldComponents(refFields); expect(extracted.length).to.be.equal(1); const hasRefField = extracted[0].key === refComponent.key; expect(hasRefField).to.be.true; } @TestCase('should be able to get ref field components to copy from cut') getRefFieldComponentsFromComponentFromCut (service: ComponentHelperService) { const refComponents = service.getRefFieldComponentsToCopy( this.tableComponent, [] ); // These fields no longer live on form, so we don't include them expect(refComponents.length).to.be.equal(0); } @TestCase('should be able to get ref field components to copy not from cut') getRefFieldComponentsFromComponent (service: ComponentHelperService) { const refComponents = service.getRefFieldComponentsToCopy( this.tableComponent, [{ index: 0, logic: null, uniqueId: '23523523', tabName: '1', components: [this.tableComponent] }] ); // These fields still live on form, so we include them expect(refComponents.length).to.be.equal(3); } @TestCase('should be able to prep component for paste') prepComponentForPaste (service: ComponentHelperService) { const cloned = service.prepComponentForPaste(this.wellComponent, this.formDefinition); let wellPasses = false; let checkboxPasses = false; let panelPasses = false; let fieldSetPasses = false; service.eachComponent([cloned], (comp) => { switch (comp.type) { case this.wellComponent.type: wellPasses = comp.key !== this.wellComponent.key; break; case this.checkboxComponent.type: checkboxPasses = comp.key !== this.checkboxComponent.key; break; case this.panelComponent.type: panelPasses = comp.key !== this.panelComponent.key; break; case this.fieldSetComponent.type: fieldSetPasses = comp.key !== this.fieldSetComponent.key; break; } }, true); expect(wellPasses).to.be.true; expect(checkboxPasses).to.be.true; expect(panelPasses).to.be.true; expect(fieldSetPasses).to.be.true; } @TestCase('should be able to guess keys') guessKeys (service: ComponentHelperService) { const formDef: FormDefinitionForUi[] = [{ ...this.formDefinition[0], components: [ ...this.formDefinition[0].components, { ...this.wellComponent, label: 'Well 2' } ] }]; service.guessKeys(formDef); // Form def should have updated so the wells have unique keys const page1Comps = formDef[0].components; const well1Key = page1Comps[0].key; const well2Key = page1Comps[1].key; const areDifferent = well1Key !== well2Key; expect(areDifferent).to.be.true; } @TestCase('should be able to get is table totaled') getIsTableTotaled (service: ComponentHelperService) { const visibleCols: ReferenceFieldsUI.TableFieldForUi[] = [{ summarizeData: true, summarizeLabel: '', referenceField: null } as ReferenceFieldsUI.TableFieldForUi, { summarizeData: false, summarizeLabel: '', referenceField: null } as ReferenceFieldsUI.TableFieldForUi]; let summarize = service.getIsTableTotaled(visibleCols); expect(summarize).to.be.true; visibleCols[0].summarizeData = false; summarize = service.getIsTableTotaled(visibleCols); expect(summarize).to.be.false; } @TestCase('should be able to get field group total') getFieldGroupTotal (service: ComponentHelperService) { const val1 = 4425; const val2 = 235; const rows: ReferenceFieldsUI.TableResponseRowForUi[] = [{ rowId: 1, columns: [{ value: val1 } as ReferenceFieldAPI.ApplicationRefFieldResponse, { value: null } as ReferenceFieldAPI.ApplicationRefFieldResponse, { value: val2 } as ReferenceFieldAPI.ApplicationRefFieldResponse] }]; const total = service.getFieldGroupTotal(rows); expect(total).to.be.equal(val1 + val2); } @TestCase('should be able to update applicable components array') updateApplicableComponentsArray (service: ComponentHelperService) { spy.on(service, 'isComponentApplicableForPdf'); const applicableComps: FormDefinitionComponent[] = []; service.updateApplicableComponentsArray(this.wellComponent, false, applicableComps); expect(service['isComponentApplicableForPdf']).to.have.been.called.once; expect(applicableComps[0]).to.deep.equal(this.wellComponent); } @TestCase('should be able to get key from form component type') getRefFieldKeyFromCompType (service: ComponentHelperService) { const type = `referenceFields-textfield`; const key = service.getRefFieldKeyFromCompType(type); expect(key).to.be.equal('textfield'); } @TestCase('should be able to find form data to add to responses') findFormDataToAddToResponses (service: ComponentHelperService) { const notAKey = 'notAKey'; const formData = { [this.checkboxComponent.key]: 'true', [this.dateComponent.key]: '01/04/2022', [notAKey]: 'dont include' }; const map = service.findFormDataToAddToResponses(formData, this.formDefinition); const checkboxRefKey = service.getRefFieldKeyFromCompType(this.checkboxComponent.type); const dateRefKey = service.getRefFieldKeyFromCompType(this.dateComponent.type); const hasRefKeys = !!map[checkboxRefKey] && !!map[dateRefKey]; expect(Object.keys(map).length).to.be.equal(2); expect(!map[notAKey]).to.be.true; expect(hasRefKeys).to.be.true; } @TestCase('should be able to get show table on pdf and record count - table') getShowTableOnPdfAndRecordCountTable (service: ComponentHelperService) { const { showTableOnPdf, totalTableRows } = service.getShowTableOnPdfAndRecordCount( this.refResponseMap, this.tableField1, 8 ); const refResponse = this.refResponseMap[this.tableField1.key] as ReferenceFieldsUI.TableResponseRowForUi[]; expect(showTableOnPdf).to.be.false; expect(totalTableRows).to.be.equal(refResponse.length); } @TestCase('should be able to get show table on pdf and record count - subset') getShowTableOnPdfAndRecordCountSubset (service: ComponentHelperService) { const numberOfCols = 0; const { showTableOnPdf, totalTableRows } = service.getShowTableOnPdfAndRecordCount( this.refResponseMap, this.subsetFieldPercent, numberOfCols ); expect(showTableOnPdf).to.be.true; expect(totalTableRows).to.be.equal(numberOfCols); } @TestCase('should be able to determine whether a layout component supports paste into') getLayoutComponentSupportsPasteInto (service: ComponentHelperService) { const supportedTypes = [ 'well', 'fieldset', 'panel', 'table' ]; const allSupportedTypesEvaluatedCorreclty = supportedTypes.every((type) => { return service.allowPasteIntoContainer(type); }); expect(allSupportedTypesEvaluatedCorreclty).to.be.true; const unsupportedTypes = ['content', 'columns']; const unsupporedTypeEvaluated = unsupportedTypes.every((type) => { return !service.allowPasteIntoContainer(type); }); expect(unsupporedTypeEvaluated).to.be.true; } @TestCase('should be able to reduce component into array - default') reduceComponentIntoArrayDefault (service: ComponentHelperService) { const updatedArray = service.reduceComponentIntoArray( this.wellComponent, this.wellComponent, this.dateComponent, [ this.checkboxComponent ], null ); // should insert dateComponent below (after) columns component const expectedArray = [ this.checkboxComponent, this.wellComponent, this.dateComponent ]; expect(updatedArray).to.deep.equal(expectedArray); } @TestCase('should be able to reduce component into array - below') reduceComponentIntoArrayBelow (service: ComponentHelperService) { const updatedArray = service.reduceComponentIntoArray( this.wellComponent, this.wellComponent, this.dateComponent, [ this.checkboxComponent ], FormFieldPasteLocation.BELOW ); // should insert dateComponent below (after) columns component const expectedArray = [ this.checkboxComponent, this.wellComponent, this.dateComponent ]; expect(updatedArray).to.deep.equal(expectedArray); } @TestCase('should be able to reduce component into array - above') reduceComponentIntoArrayAbove (service: ComponentHelperService) { const updatedArray = service.reduceComponentIntoArray( this.wellComponent, this.wellComponent, this.dateComponent, [ this.checkboxComponent ], FormFieldPasteLocation.ABOVE ); // should insert dateComponent above (before) columns component const expectedArray = [ this.checkboxComponent, this.dateComponent, this.wellComponent ]; expect(updatedArray).to.deep.equal(expectedArray); } @TestCase('should be able to reduce component into array - into container') reduceComponentIntoArrayIntoContainer (service: ComponentHelperService) { const updatedArray = service.reduceComponentIntoArray( this.wellComponent, this.wellComponent, this.checkboxComponent, [ this.dateComponent ], FormFieldPasteLocation.INSIDE_CONTAINER ); // should insert dateComponent into container const expectedArray = [ this.dateComponent, { ...this.wellComponent, components: [ this.checkboxComponent, ...this.wellComponent.components ] } ]; expect(updatedArray).to.deep.equal(expectedArray); } @TestCase('should be able to adapt to formio changes - ref field') adaptToFormChanges (service: ComponentHelperService) { const component = { type: `referenceFields-checkboxKey`, key: 'compKey' } as FormDefinitionComponent; const change: FormValueChange = { value: true, updateFormGroup: false }; const adapted = service.adaptToFormChanges( component, change.value, change.updateFormGroup ); expect(adapted.isReferenceField).to.be.true; expect(adapted.value).to.be.equal(change.value); expect(adapted.componentKey).to.be.equal(component.key); expect(adapted.type).to.be.equal(component.type); } @TestCase('should be able to adapt to formio changes - standard field') adaptToFormChangesStandard (service: ComponentHelperService) { const component = { type: 'designation', key: 'compKey' } as FormDefinitionComponent; const change: FormValueChange = { value: 'des', updateFormGroup: false }; const adapted = service.adaptToFormChanges( component, change.value, change.updateFormGroup ); expect(adapted.isReferenceField).to.be.false; expect(adapted.value).to.be.equal(change.value); expect(adapted.componentKey).to.be.equal(component.key); expect(adapted.type).to.be.equal(component.type); } }