Skip to content

Commit

Permalink
#1042 - Support for data mapper enum fields (#1104)
Browse files Browse the repository at this point in the history
* Decouple the static value 'widget' so we can extend it for enums

* Map enum values into the spec, and add the ability to force reading an overriden spec since the spec lives on prod

* Missed the custom field for support of openapi spec override

* Final changes

* Add test coverage to the apex changes

* Add some toolchain safety for dev debug settings

* Fix bug in check-dev-settings

* Added note to say Use_Local_OpenAPI_Spec__c should always be false in prod.
  • Loading branch information
jmather-c authored Jun 15, 2023
1 parent ff84565 commit a23845b
Show file tree
Hide file tree
Showing 14 changed files with 1,910 additions and 30 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ jobs:
- checkout
- sfdx/install: &sfdx_version
version: '7.170.0'
- run: sfdx/bin/check-dev-settings
- run: sfdx/bin/run-tests <<parameters.account>>
- store_test_results:
path: sfdx/test-results
Expand Down
59 changes: 59 additions & 0 deletions sfdx/bin/check-dev-settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# Usage: bin/check-dev-settings
# Purpose: Make sure we didn't leave any developer settings enabled

cd "$(dirname "$0")/.."

HAS_ERROR=0

echo "🔁 Making sure we don't have any developer settings enabled";

# Check local openapi override
CHECK_PATH="force-app/main/default/objects/Setup_Connection_Data__mdt/fields/Use_Local_OpenAPI_Spec__c.field-meta.xml"
CHECK_DEFAULT_VALUE=`grep "defaultValue" $CHECK_PATH | sed "s/.*>\\(.*\\)<.*/\1/"`
if [ "$CHECK_DEFAULT_VALUE" != "false" ]; then
echo "❌ Setup_Connection_Data__mdt.Use_Local_OpenAPI_Spec__c.defaultValue is not false."
HAS_ERROR=1
else
echo "👍 Setup_Connection_Data__mdt.Use_Local_OpenAPI_Spec__c.defaultValue is false."
fi

# Check apex debug
CHECK_PATH="force-app/main/default/classes"
CHECK_ENABLE_DEBUG=`grep -R enableDebug $CHECK_PATH | grep true`

if [ ! -z "$CHECK_ENABLE_DEBUG" ]; then
echo "❌ Debug_Helper is enabled globally."
HAS_ERROR=1
else
echo "👍 Debug_Helper is disabled globally."
fi

OLD_IFS=$IFS
IFS=$'\n'
SEEN_FILES=""
CHECK_DEBUG_HELPER=`grep -R Debug_Helper $CHECK_PATH`
for line in $CHECK_DEBUG_HELPER; do
filepath=`echo $line | sed "s/\\(.*\\):.*/\1/"`
code=`echo $line | sed "s/.*:\\(.*\\)/\1/"`
filename=`echo $filepath | sed "s/.*\\///"`
# Skip
if [[ $SEEN_FILES == *$filename* ]]; then
continue
fi
if [[ $filename == *[Tt][Ee][Ss][Tt]* ]]; then
echo "👍 $filename is a test, skipping..."
SEEN_FILES="$SEEN_FILES $filename"
else
if [[ $code == *'Debug_Helper(true'* ]]; then
echo "❌ Debug_Helper is enabled in $filename."
HAS_ERROR=1
else
echo "👍 Reference in $filename has been cleared."
fi
fi
done

IFS=$OLD_IFS

exit $HAS_ERROR
4 changes: 4 additions & 0 deletions sfdx/bin/openapi-spec-generator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ function formatStripeObjectsForMapper(stripeObjectToFormat, objectExcludedReadOn
fieldMap = getStripeFieldDescription(fieldMap, field);
}

if (fieldData['enum']) {
fieldMap['enum'] = fieldData['enum'];
}

// standard field section is always at the top of the array
stripeObjectMappings[0].fields.push(fieldMap);
continue;
Expand Down
29 changes: 24 additions & 5 deletions sfdx/force-app/main/default/classes/setupAssistant.cls
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,26 @@ public with sharing class setupAssistant {
};

String route = constants.RUBY_SERVICE_BASE_URI + '/openapi.json';
HttpResponse response = utilities.makeCallout(route,'GET', headers);
Map<String, Object> responseBody = null;

Setup_Connection_Data__mdt connectionData = utilities.getConnectionData();
if (connectionData.Use_Local_OpenAPI_Spec__c) {
String NS = constants.NAMESPACE == 'c' ? null : constants.NAMESPACE;
List<StaticResource> resources = [SELECT Body FROM StaticResource WHERE Name = 'OpenApiOverride' AND NamespacePrefix = :NS];
if (resources.size() > 0) {
responseBody = (Map<String, Object>)JSON.deserializeUntyped(resources[0].Body.toString());
}
}

Map<String, Object> responseBody;
if(response.getStatusCode() == 200) {
responseBody = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
HttpResponse response;
if (responseBody == null) {
response = utilities.makeCallout(route,'GET', headers);
if (response.getStatusCode() == 200) {
responseBody = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
}
}

if(responseBody != null) {
rd.put('formattedStripeCustomerFields', (List<Object>)responseBody.get('formattedStripeCustomerFields'));
rd.put('formattedStripeProductItemFields', (List<Object>)responseBody.get('formattedStripeProductItemFields'));
rd.put('formattedStripeSubscriptionFields', (List<Object>)responseBody.get('formattedStripeSubscriptionFields'));
Expand All @@ -234,7 +249,11 @@ public with sharing class setupAssistant {
rd.put('formattedStripePriceOrderItemFields', (List<Object>)responseBody.get('formattedStripePriceFields'));
rd.put('formattedStripeCouponFields', (List<Object>)responseBody.get('formattedStripeCouponFields'));
} else {
errorLogger.create('getFormattedStripeObjectFields', String.valueOf(response.getStatusCode()), (String)response.getStatus(), 'Failed to get mapping configuration from ruby service.');
if (response != null) {
errorLogger.create('getFormattedStripeObjectFields', String.valueOf(response.getStatusCode()), (String)response.getStatus(), 'Failed to get mapping configuration from ruby service.');
} else {
errorLogger.create('getFormattedStripeObjectFields', 'An unknown error occurred', null, null);
}
}
} catch (Exception e) {
rd.addError(e);
Expand Down
31 changes: 22 additions & 9 deletions sfdx/force-app/main/default/classes/test_setupAssistant.cls
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,24 @@ public with sharing class test_setupAssistant {
Setup_Connection_Data__mdt testSetupData = getTestStripeConnectionKey();
setTestGlobalKey(testSetupData);
insertTestConnectedRecord();
stripeSuccessMock callMock = new stripeSuccessMock();
Test.setMock(HttpCalloutMock.class, callMock);

Test.startTest();
Test.setMock(HttpCalloutMock.class, new stripeSuccessMock());
testSetupData.Use_Local_OpenAPI_Spec__c = true;
String staticResourceResponse = setupAssistant.getFormattedStripeObjectFields();
System.assertEquals(0, callMock.calls);

testSetupData.Use_Local_OpenAPI_Spec__c = false;
String response = setupAssistant.getFormattedStripeObjectFields();
Map<String, Object> responseMap = (Map<String, Object>)JSON.deserializeUntyped(response);
System.assertEquals(1, callMock.calls);

Test.stopTest();

// ensure we got semi-assured response for our static resource call...
System.assert(staticResourceResponse.length() > 200, 'Response for static resource call is non-trivial length');

Map<String, Object> responseMap = (Map<String, Object>)JSON.deserializeUntyped(response);
System.assert((Boolean)responseMap.get('isSuccess'), responseMap.get('error'));

Map<String, Object> resultsMap = (Map<String, Object>)responseMap.get('results');
Expand Down Expand Up @@ -578,16 +589,15 @@ public with sharing class test_setupAssistant {
}

public static void setTestGlobalKey(Setup_Connection_Data__mdt testSetupData) {
List<Setup_Connection_Data__mdt> setupConfigList = [
SELECT Global_Key__c
FROM Setup_Connection_Data__mdt
];

if(!setupConfigList.isEmpty()) {
if (utilities.setupConfigMetadata.isEmpty() == false) {
utilities.setupConfigMetadata[0] = testSetupData;
setupAssistant.setupConfigMetadata[0] = testSetupData;
} else {
utilities.setupConfigMetadata.add(testSetupData);
}

if (setupAssistant.setupConfigMetadata.isEmpty() == false) {
setupAssistant.setupConfigMetadata[0] = testSetupData;
} else {
setupAssistant.setupConfigMetadata.add(testSetupData);
}
}
Expand Down Expand Up @@ -679,7 +689,10 @@ public with sharing class test_setupAssistant {
}

private class stripeSuccessMock implements HttpCalloutMock {
public Integer calls = 0;
public HttpResponse respond(HttpRequest req) {
calls++;

HttpResponse res = new HttpResponse();
System.assertEquals(req.getHeader('Salesforce-Account-Id'), (String)constants.ORG_ID);
System.assertEquals(req.getHeader('Salesforce-Type'), String.valueOf(Sentry_Environment.getInstanceType()));
Expand Down
19 changes: 14 additions & 5 deletions sfdx/force-app/main/default/classes/utilities.cls
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,16 @@ public with sharing class utilities {
return rd.getJsonString();
}

public static Setup_Connection_Data__mdt getConnectionData() {
if (setupConfigMetadata != null && setupConfigMetadata.isEmpty() == false) {
return setupConfigMetadata[0];
}

return new Setup_Connection_Data__mdt();
}

public static List<Setup_Connection_Data__mdt> getStripeConnectionKey() {
return [SELECT Global_Key__c
FROM Setup_Connection_Data__mdt
LIMIT 1];
return setupConfigMetadata;
}

// generates package level key and sends to ruby. Named `salesforce_organization_key` on the ruby side
Expand Down Expand Up @@ -408,8 +414,11 @@ public with sharing class utilities {
//Creates a test metadata record in test context
@testVisible static List<Setup_Connection_Data__mdt> setupConfigMetadata {
get {
if (setupConfigMetadata == null)
setupConfigMetadata = getStripeConnectionKey();
if (setupConfigMetadata == null) {
setupConfigMetadata = [SELECT Global_Key__c, Use_Local_OpenAPI_Spec__c
FROM Setup_Connection_Data__mdt
LIMIT 1];
}
return setupConfigMetadata;
} set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ <h4 class="slds-m-top_xx-small slds-m-bottom_small">Salesforce Object: <strong>{
<template if:false={field.hasOverride}>
<template if:false={field.hasRequiredValue}>
<div class="slds-col slds-has-flexi-truncate">
<lightning-input if:true={field.staticValue} type="text" label="Salesforce Value" value={field.sfValue} onchange={updateStaticValueChoice} variant="label-hidden" placeholder="Enter Static Value..."></lightning-input>
<c-dm-static-value if:true={field.staticValue} field={field} onupdate={updateStaticValueChoice} field-index={fieldIndex} section-index={sectionIndex}></c-dm-static-value>
<c-field-picker if:false={field.staticValue} root-object={defaultSfObject} label="Record Type" options={sfFieldOptions} hash={field.sfValue} variant="label-hidden" onselect={updatePicklist} onobjectchange={updateFieldList} onpicklistclick={updatePicklistChoices} searchable placeholder="Select Salesforce Field..."></c-field-picker>
</div>
</template>
</template>
<template if:true={field.hasOverride}>
<div class="slds-col slds-has-flexi-truncate">
<template if:true={field.staticValue}>
<lightning-input type="text" label="Salesforce Value" value={field.sfValue} onchange={updateStaticValueChoice} variant="label-hidden" placeholder="Enter Static Value..."></lightning-input>
<c-dm-static-value field={field} onupdate={updateStaticValueChoice} field-index={fieldIndex} section-index={sectionIndex}></c-dm-static-value>
<div if:true={field.defaultValue} class="slds-text-title slds-m-top_x-small slds-truncate">Default: {field.defaultValue}</div>
</template>
<template if:false={field.staticValue}>
Expand All @@ -117,7 +117,7 @@ <h4 class="slds-m-top_xx-small slds-m-bottom_small">Salesforce Object: <strong>{
<template if:true={field.hasRequiredValue}>
<div class="slds-col slds-has-flexi-truncate">
<template if:true={field.staticValue}>
<lightning-input type="text" label="Salesforce Value" value={field.sfValue} onchange={updateStaticValueChoice} variant="label-hidden" placeholder="Enter Static Value..."></lightning-input>
<c-dm-static-value field={field} onupdate={updateStaticValueChoice} field-index={fieldIndex} section-index={sectionIndex}></c-dm-static-value>
<div if:true={field.requiredValue} class="slds-text-title slds-m-top_x-small slds-has-flexi-truncate"><strong>Required field.</strong> Default: {field.requiredValue}</div>
</template>
<template if:false={field.staticValue}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,18 +386,16 @@ export default class DataMappingStep extends LightningElement {
}

updateStaticValueChoice(event) {
this[event.target.name] = event.target.value;
this.staticValue = this[event.target.name];
const targetSectionIndex = event.currentTarget.closest('lightning-accordion-section').dataset.index;
const targetFieldIndex = event.currentTarget.closest('tr').dataset.index;
if (targetSectionIndex && targetFieldIndex ) {
let updatedSelection = {
const targetSectionIndex = event.detail.sectionIndex;
const targetFieldIndex = event.detail.fieldIndex;
if (this.activeObjectFields[targetSectionIndex].fields[targetFieldIndex]) {
const updatedSelection = {
hasSfValue: true,
staticValue: true,
sfValue: this.staticValue,
sfValue: event.detail.value,
sfValueType: 'static'
};
Object.assign(this.activeObjectFields[targetSectionIndex].fields[parseInt(targetFieldIndex)] , updatedSelection)
Object.assign(this.activeObjectFields[targetSectionIndex].fields[targetFieldIndex] , updatedSelection)
this.valueChange();
}
}
Expand Down Expand Up @@ -899,6 +897,8 @@ export default class DataMappingStep extends LightningElement {

const payload = JSON.parse(JSON.stringify(this.allMappingList));
payload.configuration_hash = this.configurationHash;
delete payload.default_mappings;
delete payload.required_mappings;

try {
const saveMappingData = await saveMappingConfigurations({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!--
- Created by jmather-c on 5/11/23.
-->

<!-- Dm Static Value -->
<template>
<lightning-input if:false={isEnum} type="text" label="Salesforce Value" value={field.sfValue} onchange={valueChange} variant="label-hidden" placeholder="Enter Static Value..."></lightning-input>
<lightning-combobox if:true={isEnum} value={field.sfValue} onchange={valueChange} variant="label-hidden" options={enumOptions}></lightning-combobox>
</template>
40 changes: 40 additions & 0 deletions sfdx/force-app/main/default/lwc/dmStaticValue/dmStaticValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Created by jmather-c on 5/11/23.
*/

import {LightningElement, api} from 'lwc';

export default class DmStaticValue extends LightningElement {
@api field;
@api fieldIndex;
@api sectionIndex;
@api valueUpdate;

get isEnum() {
return this.field.enum !== undefined && this.field.enum instanceof Array;
}

get enumOptions() {
const options = [];
if (this.isEnum === false) {
return options;
}

for (let i = 0; i < this.field.enum.length; i++) {
const opt = this.field.enum[i];
options.push({value: opt, label: opt});
}

return options;
}

valueChange(event) {
this.dispatchEvent(new CustomEvent('update', {
detail: {
value: event.target.value,
sectionIndex: parseInt(this.sectionIndex, 10),
fieldIndex: parseInt(this.fieldIndex, 10),
}
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<description>Dm Static Value</description>
<isExposed>false</isExposed>
<masterLabel>Dm Static Value</masterLabel>
</LightningComponentBundle>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Use_Local_OpenAPI_Spec__c</fullName>
<defaultValue>false</defaultValue>
<description>Developer config to target using an openapi.json from Salesforce assets. This should only ever be false in production.</description>
<externalId>false</externalId>
<fieldManageability>DeveloperControlled</fieldManageability>
<label>Use Local OpenAPI Spec</label>
<type>Checkbox</type>
</CustomField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Public</cacheControl>
<contentType>text/plain</contentType>
<description>OpenApiOverride</description>
</StaticResource>
Loading

0 comments on commit a23845b

Please sign in to comment.