Skip to content

Commit

Permalink
Use formula-based references instead
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsellek committed Aug 12, 2024
1 parent b14a2c4 commit 2bf2c0f
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 64 deletions.
15 changes: 13 additions & 2 deletions packages/salesforce-adapter/src/filters/formula_ref_fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,30 @@ import { Element, Field, ReadOnlyElementsSource, ReferenceExpression, Value } fr
import { parseFormulaIdentifier } from '@salto-io/salesforce-formula-parser'
import { collections } from '@salto-io/lowerdash'
import { TransformFunc, transformValues } from '@salto-io/adapter-utils'
import {logger} from '@salto-io/logging'
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 log = logger(module)

const typesWithFieldsWithFormulaReferences = [FLOW_METADATA_TYPE, FLEXI_PAGE_TYPE]

const referenceFieldsWithFormulaIdentifiers: Record<string, string> = {
FlowCondition: 'leftValueReference',
FlowTestCondition: 'leftValueReference',
FlowTestParameter: 'leftValueReference',
FlowAssignmentItem: 'assignToReference',
ComponentInstancePropertyListItem: 'value',
}

const referenceExpressionFromFieldValue = async (
topLevelTypeName: string,
field: Field,
value: Value,
value: string,
allElements: ReadOnlyElementsSource,
): Promise<ReferenceExpression | Value> => {
const topLevelParentInstanceElemId = field.elemID.createTopLevelParentID().parent
Expand Down Expand Up @@ -71,6 +76,12 @@ 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()
log.debug('%o', globalElements)
return new ReferenceExpression(globalElements[0].elemID, globalElements[0])
}
return referenceExpressionFromFieldValue(topLevelTypeName, field, value, allElements)
}

Expand Down
218 changes: 156 additions & 62 deletions packages/salesforce-adapter/test/filters/formula_ref_fields.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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))
})
})
})
})

0 comments on commit 2bf2c0f

Please sign in to comment.