import { Injectable } from '@angular/core'; 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 } from '@features/configure-forms/form.typing'; import { CustomDataTable, PicklistDataType } from '@features/custom-data-tables/custom-data-tables.typing'; import { BeforeEach, Spec, TestCase } from '@yourcause/test-decorators'; import { DescribeAngularService } from '@yourcause/test-decorators/angular'; import { expect } from 'chai'; import { FormFieldValidatorExtras, ReferenceFieldsValidatorService } from './reference-fields-validator.service'; @Injectable({ providedIn: 'root' }) @DescribeAngularService(ReferenceFieldsValidatorService, { imports: [ GCMockModule ] }) export class ReferenceFieldsValidatorServiceSpec implements Spec { parentFieldId = 13; cdtId1 = 1; cdtId2 = 2; cdtId3 = 3; parentPicklistGuid = 'guid1'; childPicklistGuid = 'guid2'; cdtGuid3 = 'guid3'; applicantTextField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { customDataTableGuid: '', name: 'Text', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.TextField, key: 'text', supportsMultiple: false, categoryId: 0, formAudience: FormAudience.APPLICANT, referenceFieldId: 1, 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 }; childField: ReferenceFieldAPI.ReferenceFieldDisplayModel = { isEncrypted: false, isMasked: false, aggregateType: null, referenceFieldId: 12, parentReferenceFieldId: this.parentFieldId, formCount: 0, usedOnReports: false, createdBy: '', createDate: '', updatedBy: '', updateDate: '', customDataTableGuid: this.childPicklistGuid, name: 'Child custom data table', description: '', type: ReferenceFieldsUI.ReferenceFieldTypes.CustomDataTable, key: 'childTable', 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: this.parentPicklistGuid, 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 }; allReferenceFields = [ this.applicantTextField, this.childField, this.parentField ]; customDataTables: CustomDataTable[] = [{ id: this.cdtId1, name: 'Parent Table', guid: this.parentPicklistGuid, createdDate: '', updatedDate: '', createdBy: '', updatedBy: '', isSystem: false, hasOptions: true, defaultLanguageId: '', dataType: PicklistDataType.Numeric, parentPicklistId: null }, { id: this.cdtId2, name: 'Child Table', guid: this.childPicklistGuid, createdDate: '', updatedDate: '', createdBy: '', updatedBy: '', isSystem: false, hasOptions: true, dataType: PicklistDataType.Text, defaultLanguageId: '', parentPicklistId: this.cdtId1 }, { id: this.cdtId3, name: 'Standalone Table', guid: this.cdtGuid3, createdDate: '', updatedDate: '', createdBy: '', dataType: PicklistDataType.Numeric, updatedBy: '', isSystem: false, hasOptions: true, defaultLanguageId: '', parentPicklistId: null }]; @BeforeEach() async mock (service: ReferenceFieldsValidatorService) { service['referenceFieldService']['referenceFieldsResources'].searchReferenceFields = async () => { return { records: this.allReferenceFields, recordCount: this.allReferenceFields.length }; }; service['referenceFieldService']['referenceFieldsResources'].getCategories = async () => { return []; }; await service['referenceFieldService'].resolve(); service['customDataTableService']['customDataTableResources']['getCustomTableDataList'] = async () => { return this.customDataTables; }; await service['customDataTableService']['setCustomDataTables'](); } @TestCase('should be able to get validation model by audience map') getValidationModelByAudienceMap (service: ReferenceFieldsValidatorService) { const map = service.getValidationModelByAudienceMap(); const hasManagerMap = !!map[FormAudience.MANAGER]; const hasApplicantMap = !!map[FormAudience.APPLICANT]; expect(hasManagerMap).to.be.true; expect(hasApplicantMap).to.be.true; } @TestCase('should be able to get validation model by audience') getValidationModelByAudience (service: ReferenceFieldsValidatorService) { const applicantMap = service.getValidationModelByAudience(FormAudience.APPLICANT); const doesNotHaveAggregate = !applicantMap[ReferenceFieldsUI.ReferenceFieldTypes.Aggregate]; expect(doesNotHaveAggregate).to.be.true; const managerMap = service.getValidationModelByAudience(FormAudience.MANAGER); const hasAggregate = !!managerMap[ReferenceFieldsUI.ReferenceFieldTypes.Aggregate]; expect(hasAggregate).to.be.true; } @TestCase('should be able to get validation key does not exist') validateKeyDoesNotExist (service: ReferenceFieldsValidatorService) { let result = service.validateKeyDoesNotExist(this.applicantTextField.key); let noErrors = result instanceof Array; // Key already exists, so throw error expect(noErrors).to.be.false; result = service.validateKeyDoesNotExist('randomNewKey'); noErrors = result instanceof Array; // Key does not exist, so it's valid expect(noErrors).to.be.true; } @TestCase('should be able to get validate data table guid exists') validateDataTableGuidExists (service: ReferenceFieldsValidatorService) { let result = service.validateDataTableGuidExists(this.parentPicklistGuid); let noErrors = result instanceof Array; // CDT exists, so no errors expect(noErrors).to.be.true; result = service.validateDataTableGuidExists('randomGuidThatDoesNotExist'); noErrors = result instanceof Array; // CDT does not exist, so throw error expect(noErrors).to.be.false; } @TestCase('should be able to get validate parent field exists') validateParentFieldExists (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: 'asdf', Key: 'pdf', ['Parent Form Field Key']: 'asdf', ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry, { ...entry, Key: 'otherKey' } ] }; let result = service.validateParentFieldExists(null, extras); let noErrors = result instanceof Array; // Parent key does not exist, so throw error expect(noErrors).to.be.false; extras.ent['Parent Form Field Key'] = this.parentField.key; result = service.validateParentFieldExists(null, extras); noErrors = result instanceof Array; // Parent key exists, so no errors expect(noErrors).to.be.true; } @TestCase('should be able to get validate form field exists') validateFormFieldExists (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: 'asdf', Key: 'pdf', ['Form Field Key']: 'unknownKey', ['Parent Form Field Key']: 'asdf', ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateFormFieldAggregateExists(null, extras); let noErrors = result instanceof Array; // Form field key does not exist, so throw error expect(noErrors).to.be.false; extras.ent['Form Field Key'] = this.parentField.key; result = service.validateFormFieldAggregateExists(null, extras); noErrors = result instanceof Array; // Form field key exists, so no errors expect(noErrors).to.be.true; extras.ent['Form Field Key'] = this.applicantTextField.key; result = service.validateFormFieldAggregateExists(null, extras); noErrors = result instanceof Array; // Form field key exists, but it's not an aggregate, so throw errors expect(noErrors).to.be.false; } @TestCase('should be able to get validate aggregate type exists') validateAggregateTypeExists (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: 'asdf', Key: 'pdf', ['Aggregation type']: 'sum', ['Parent Form Field Key']: 'asdf', ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateAggregateTypeExists(null, extras); let noErrors = result instanceof Array; // Aggregate type exists, so no error expect(noErrors).to.be.true; extras.ent['Aggregation type'] = 'not an aggregate type'; result = service.validateAggregateTypeExists(null, extras); noErrors = result instanceof Array; // Aggregate type does no exist, so throw error expect(noErrors).to.be.false; } @TestCase('should be able to get validate parent field required') validateParentFieldRequired (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: this.childPicklistGuid, Key: 'pdf', ['Parent Form Field Key']: this.parentField.key, ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateParentFieldRequired(null, extras); let noErrors = result instanceof Array; // Parent field required, and exists, so no errors expect(noErrors).to.be.true; extras.ent['Parent Form Field Key'] = ''; result = service.validateParentFieldRequired(null, extras); noErrors = result instanceof Array; // Parent field required, and does no exist, so throw error expect(noErrors).to.be.false; } @TestCase('should be able to get validate parent field') validateParentField (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: this.childPicklistGuid, Key: 'pdf', ['Parent Form Field Key']: this.parentField.key, ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateParentField(null, extras); let noErrors = result instanceof Array; // Parent field valid, so no errors expect(noErrors).to.be.true; extras.ent['Parent Form Field Key'] = 'newParentFieldKey'; result = service.validateParentField(null, extras); noErrors = result instanceof Array; // Parent field not found, and does not exist in import, so invalid expect(noErrors).to.be.false; } @TestCase('should be able to get validate parent field - other scenarios') validateParentFieldOtherScenarios (service: ReferenceFieldsValidatorService) { const entry = { ['Custom Data Table Id']: this.childPicklistGuid, Key: 'pdf', ['Parent Form Field Key']: this.childField.key, ['Supports multiple values']: '' }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateParentField(null, extras); let noErrors = result instanceof Array; // Parent field valid, so no errors expect(noErrors).to.be.false; extras.ent['Parent Form Field Key'] = 'newParentFieldKey'; const newEntry = { ...entry, ['Key']: 'newParentFieldKey', ['Custom Data Table Id']: this.parentPicklistGuid }; extras.group = [ entry, newEntry ]; result = service.validateParentField(null, extras); noErrors = result instanceof Array; // Parent field not found, and does exist in import, so valid expect(noErrors).to.be.true; extras.group = [ entry, { ...newEntry, ['Key']: 'newParentFieldKey', ['Custom Data Table Id']: this.childPicklistGuid } ]; result = service.validateParentField(null, extras); noErrors = result instanceof Array; // Parent field not found, but wrong cdt so invalid expect(noErrors).to.be.false; } @TestCase('should be able to get validate supports multi cant be table field') validateSupportsMultiCantBeTableField (service: ReferenceFieldsValidatorService) { const entry = { ['Is table field']: true, ['Supports multiple values']: true }; const extras: FormFieldValidatorExtras = { attr: 'Parent Form Field Key', context: {}, ent: entry, injector: null, externalContext: null, group: [ entry ] }; let result = service.validateSupportsMultiCantBeTableField(null, extras); let noErrors = result instanceof Array; // Can't be table field and support multiple expect(noErrors).to.be.false; extras.ent['Is table field'] = false; result = service.validateSupportsMultiCantBeTableField(null, extras); noErrors = result instanceof Array; // Isn't table field so it's valid expect(noErrors).to.be.true; } }