diff --git a/packages/salesforce-adapter/src/filters/formula_ref_fields.ts b/packages/salesforce-adapter/src/filters/formula_ref_fields.ts index d0a232b0567..4044ab2f0da 100644 --- a/packages/salesforce-adapter/src/filters/formula_ref_fields.ts +++ b/packages/salesforce-adapter/src/filters/formula_ref_fields.ts @@ -20,22 +20,25 @@ import { TransformFunc, transformValues } from '@salto-io/adapter-utils' import { apiNameSync, buildElementsSourceForFetch, ensureSafeFilterFetch, isInstanceOfTypeSync } from './utils' import { LocalFilterCreator } from '../filter' import { logInvalidReferences, referencesFromIdentifiers, referenceValidity } from './formula_utils' +import { FLEXI_PAGE_TYPE, FLOW_METADATA_TYPE } from '../constants' const { awu, groupByAsync } = collections.asynciterable -const typesWithFieldsWithFormulaReferences = ['Flow'] + +const typesWithFieldsWithFormulaReferences = [FLOW_METADATA_TYPE, FLEXI_PAGE_TYPE] const referenceFieldsWithFormulaIdentifiers: Record = { FlowCondition: 'leftValueReference', FlowTestCondition: 'leftValueReference', FlowTestParameter: 'leftValueReference', FlowAssignmentItem: 'assignToReference', + ComponentInstancePropertyListItem: 'value', } const referenceExpressionFromFieldValue = async ( topLevelTypeName: string, field: Field, - value: Value, + value: string, allElements: ReadOnlyElementsSource, ): Promise => { const topLevelParentInstanceElemId = field.elemID.createTopLevelParentID().parent @@ -71,6 +74,11 @@ const transformFieldsToReferences = async ( if (field.name !== expectedFieldName) { return value } + if ((value as string).startsWith('Global.')) { + const apiName = (value as string).substring(7) + const globalElements = await awu(await allElements.getAll()).filter(e => apiNameSync(e) === apiName).toArray() + return new ReferenceExpression(globalElements[0].elemID, globalElements[0]) + } return referenceExpressionFromFieldValue(topLevelTypeName, field, value, allElements) } diff --git a/packages/salesforce-adapter/test/filters/formula_ref_fields.test.ts b/packages/salesforce-adapter/test/filters/formula_ref_fields.test.ts index e73dbf20af0..831978daae7 100644 --- a/packages/salesforce-adapter/test/filters/formula_ref_fields.test.ts +++ b/packages/salesforce-adapter/test/filters/formula_ref_fields.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { BuiltinTypes, ElemID, InstanceElement, ListType, ObjectType, ReferenceExpression } from '@salto-io/adapter-api' -import { METADATA_TYPE, SALESFORCE } from '../../src/constants' +import { FLEXI_PAGE_TYPE, LIGHTNING_PAGE_TYPE, METADATA_TYPE, SALESFORCE } from '../../src/constants' import { mockTypes } from '../mock_elements' import { FilterWith } from './mocks' import { defaultFilterContext } from '../utils' @@ -28,81 +28,175 @@ describe('Formula reference fields', () => { filter = filterCreator({ config }) as FilterWith<'onFetch'> }) - const flowConditionObjectType = new ObjectType({ - elemID: new ElemID(SALESFORCE, 'FlowCondition'), - annotations: { [METADATA_TYPE]: 'FlowCondition' }, - fields: { - leftValueReference: { - refType: BuiltinTypes.STRING, + describe('Flow', () => { + const flowConditionObjectType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'FlowCondition'), + annotations: { [METADATA_TYPE]: 'FlowCondition' }, + fields: { + leftValueReference: { + refType: BuiltinTypes.STRING, + }, }, - }, - }) - - const flowRuleObjectType = new ObjectType({ - elemID: new ElemID(SALESFORCE, 'FlowRule'), - annotations: { [METADATA_TYPE]: 'FlowRule' }, - fields: { conditions: { refType: new ListType(flowConditionObjectType) } }, - }) + }) - const flowDecisionObjectType = new ObjectType({ - elemID: new ElemID(SALESFORCE, 'FlowDecision'), - annotations: { [METADATA_TYPE]: 'FlowDecision' }, - fields: { rules: { refType: new ListType(flowRuleObjectType) } }, - }) + const flowRuleObjectType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'FlowRule'), + annotations: { [METADATA_TYPE]: 'FlowRule' }, + fields: { conditions: { refType: new ListType(flowConditionObjectType) } }, + }) - const flowType = new ObjectType({ - elemID: new ElemID(SALESFORCE, 'Flow'), - annotations: { [METADATA_TYPE]: 'Flow' }, - fields: { - decisions: { refType: flowDecisionObjectType }, - }, - }) + const flowDecisionObjectType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'FlowDecision'), + annotations: { [METADATA_TYPE]: 'FlowDecision' }, + fields: { rules: { refType: new ListType(flowRuleObjectType) } }, + }) - const referringInstance = new InstanceElement('SomeFlow', flowType, { - decisions: [ - { - rules: [ - { - conditions: [ - { - leftValueReference: '$Label.SomeLabel', - }, - ], - }, - ], + const flowType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'Flow'), + annotations: { [METADATA_TYPE]: 'Flow' }, + fields: { + decisions: { refType: flowDecisionObjectType }, }, - ], - }) + }) + + const referringInstance = new InstanceElement('SomeFlow', flowType, { + decisions: [ + { + rules: [ + { + conditions: [ + { + leftValueReference: '$Label.SomeLabel', + }, + ], + }, + ], + }, + ], + }) - describe('when there is a valid reference', () => { - const referredInstance = new InstanceElement('SomeLabel', mockTypes.CustomLabel, { fullName: 'SomeLabel' }) - const elements = [flowConditionObjectType, referringInstance, referredInstance].map(element => element.clone()) + describe('when there is a valid reference', () => { + const referredInstance = new InstanceElement('SomeLabel', mockTypes.CustomLabel, { fullName: 'SomeLabel' }) + const elements = [flowConditionObjectType, referringInstance, referredInstance].map(element => element.clone()) - beforeEach(async () => { - await filter.onFetch(elements) + beforeEach(async () => { + await filter.onFetch(elements) + }) + + it('should replace the field value with a reference expression', () => { + const referringInstanceAfterTest = elements.find(elem => + elem.elemID.isEqual(referringInstance.elemID), + ) as InstanceElement + expect(referringInstanceAfterTest.value.decisions?.[0].rules?.[0].conditions?.[0].leftValueReference).toEqual( + new ReferenceExpression(referredInstance.elemID), + ) + }) }) + describe('when the reference is not valid', () => { + const elements = [flowConditionObjectType, referringInstance].map(element => element.clone()) + + beforeEach(async () => { + await filter.onFetch(elements) + }) - it('should replace the field value with a reference expression', () => { - const referringInstanceAfterTest = elements.find(elem => - elem.elemID.isEqual(referringInstance.elemID), - ) as InstanceElement - expect(referringInstanceAfterTest.value.decisions?.[0].rules?.[0].conditions?.[0].leftValueReference).toEqual( - new ReferenceExpression(referredInstance.elemID), - ) + it('should replace the field value with a reference expression', () => { + const referringInstanceAfterTest = elements.find(elem => + elem.elemID.isEqual(referringInstance.elemID), + ) as InstanceElement + expect(referringInstanceAfterTest.value.leftValueReference).toEqual(referringInstance.value.leftValueReference) + }) }) }) - describe('when the reference is not valid', () => { - const elements = [flowConditionObjectType, referringInstance].map(element => element.clone()) - beforeEach(async () => { - await filter.onFetch(elements) + describe('LightningPage', () => { + const componentInstancePropertyListItemType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'ComponentInstancePropertyListItem'), + annotations: { [METADATA_TYPE]: 'ComponentInstancePropertyListItem' }, + fields: { + value: { refType: BuiltinTypes.STRING }, + }, + }) + const componentInstancePropertyListType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'ComponentInstancePropertyList'), + annotations: { [METADATA_TYPE]: 'ComponentInstancePropertyList' }, + fields: { + valueListItems: { refType: new ListType(componentInstancePropertyListItemType) }, + }, + }) + const componentInstancePropertyType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'ComponentInstanceProperty'), + annotations: { [METADATA_TYPE]: 'ComponentInstanceProperty' }, + fields: { + valueList: { refType: new ListType(componentInstancePropertyListType) }, + }, + }) + const componentInstanceType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'ComponentInstance'), + annotations: { [METADATA_TYPE]: 'ComponentInstance' }, + fields: { + componentInstanceProperties: { refType: new ListType(componentInstancePropertyType) }, + }, + }) + const itemInstanceType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'ItemInstance'), + annotations: { [METADATA_TYPE]: 'ItemInstance' }, + fields: { + componentInstances: { refType: new ListType(componentInstanceType) }, + }, + }) + const flexiPageRegionType = new ObjectType({ + elemID: new ElemID(SALESFORCE, 'FlexiPageRegion'), + annotations: { [METADATA_TYPE]: 'FlexiPageRegion' }, + fields: { + itemInstances: { refType: new ListType(itemInstanceType) }, + }, + }) + const lightningPageType = new ObjectType({ + elemID: new ElemID(SALESFORCE, LIGHTNING_PAGE_TYPE), + annotations: { [METADATA_TYPE]: FLEXI_PAGE_TYPE }, + fields: { + flexiPageRegions: { refType: new ListType(flexiPageRegionType) }, + }, + }) + + const referringInstance = new InstanceElement('SomePage', lightningPageType, { + flexiPageRegions: [ + { + itemInstances: [ + { + componentInstances: [ + { + componentInstanceProperties: [ + { + valueList: { + valueListItems: [{ value: '$Label.SomeLabel' }], + }, + }, + ], + }, + ], + }, + ], + }, + ], }) + describe('when there is a valid reference', () => { + const referredInstance = new InstanceElement('SomeLabel', mockTypes.CustomLabel, { fullName: 'SomeLabel' }) + const elements = [lightningPageType, referringInstance, referredInstance].map(element => element.clone()) + + beforeEach(async () => { + await filter.onFetch(elements) + }) - it('should replace the field value with a reference expression', () => { - const referringInstanceAfterTest = elements.find(elem => - elem.elemID.isEqual(referringInstance.elemID), - ) as InstanceElement - expect(referringInstanceAfterTest.value.leftValueReference).toEqual(referringInstance.value.leftValueReference) + it('should replace the field value with a reference expression', () => { + const referringInstanceAfterTest = elements.find(elem => + elem.elemID.isEqual(referringInstance.elemID), + ) as InstanceElement + expect( + referringInstanceAfterTest.value.flexiPageRegions?.[0].itemInstances?.[0].componentInstances?.[0] + .componentInstanceProperties?.[0].valueList?.valueListItems?.[0].value, + ).toEqual(new ReferenceExpression(referredInstance.elemID)) + }) }) }) })