diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33a0fac..d50f5d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,46 @@
# Change Log
+## [2.7.0] [PR#35](https://github.com/jdschleicher/Salesforce-Data-Treecipe/pull/35) - Feature: Enhanced Text & Numeric Field Precision Handling
+
+### 🎯 Major Features
+
+#### 1. **Text and Numeric Value Constraints**
+Added new methods for building text and numeric recipe values with constraints, enhancing control over generated data ranges and formats.
+
+### 🔧 Technical Details
+
+**Code Example - Currency Field XML to FakerJS YAML**:
+
+Given a custom object field XML markup with precision and scale:
+
+```xml
+
+ Price__c
+ Product price
+ false
+
+ 8
+ false
+ 2
+ Currency
+ false
+
+```
+
+The generated recipe automatically creates a faker expression that respects the precision (8) and scale (2):
+
+```yaml
+- object: My_Custom_Object__c
+ fields:
+ Price__c: ${{ faker.finance.amount({ min: 0, max: 999999, dec: 2 }) }}
+```
+
+This ensures the generated currency values:
+- Have at most 8 total digits (precision)
+- Have exactly 2 decimal places (scale)
+- Are within the valid range (0 to 99,999.99)
+- Match Salesforce field constraints
+
## [2.6.0] [PR#34](https://github.com/jdschleicher/Salesforce-Data-Treecipe/pull/34) - Feature: Relationship Service & Bug Fix for Special Characters in Picklists
### 🎯 Major Features
diff --git a/package.json b/package.json
index 90cce0b..17b42cb 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"displayName": "Salesforce Data Treecipe",
"description": "source-fidelity driven development, pairs well with cumulus-ci",
"icon": "images/datatreecipe.webp",
- "version": "2.6.0",
+ "version": "2.7.0",
"engines": {
"vscode": "^1.94.0"
},
diff --git a/src/treecipe/src/RecipeFakerService.ts/FakerJSRecipeFakerService/FakerJSRecipeFakerService.ts b/src/treecipe/src/RecipeFakerService.ts/FakerJSRecipeFakerService/FakerJSRecipeFakerService.ts
index 2b381c0..275786a 100644
--- a/src/treecipe/src/RecipeFakerService.ts/FakerJSRecipeFakerService/FakerJSRecipeFakerService.ts
+++ b/src/treecipe/src/RecipeFakerService.ts/FakerJSRecipeFakerService/FakerJSRecipeFakerService.ts
@@ -504,7 +504,37 @@ ${this.generateTabs(5)}${randomChoicesBreakdown}`;
getMultipicklistTODOPlaceholderWithExample():string {
const emptyMultiSelectXMLDetailPlaceholder = `### TODO: POSSIBLE GLOBAL OR STANDARD VALUE SET USED FOR THIS MULTIPICKLIST AS DETAILS ARE NOT IN FIELD XML MARKUP -- FIND ASSOCIATED VALUE SET AND REPLACE COMMA SEPARATED FRUITS WITH VALUE SET OPTIONS: \${{ (faker.helpers.arrayElements(['apple', 'orange', 'banana']) ).join(';') }}`;
- return emptyMultiSelectXMLDetailPlaceholder;
+ return emptyMultiSelectXMLDetailPlaceholder;
+
+ }
+
+ buildTextRecipeValueWithLength(length: number): string {
+ return `${this.openingRecipeSyntax} faker.lorem.text(${length}).substring(0, ${length}) ${this.closingRecipeSyntax}`;
+ }
+
+ buildNumericRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string {
+
+ const effectiveScale = scale ?? 0;
+ const maxNumbersLeftOfDecimal = '9'.repeat(precision - effectiveScale);
+
+ if (effectiveScale === 0) {
+ return `|
+ ${this.openingRecipeSyntax} faker.number.int({min: 0, max: ${maxNumbersLeftOfDecimal}}) ${this.closingRecipeSyntax}`;
+ } else {
+ return `|
+ ${this.openingRecipeSyntax} faker.finance.amount({min: 0, max: ${maxNumbersLeftOfDecimal}, dec: ${effectiveScale}}) ${this.closingRecipeSyntax}`;
+ }
+
+ }
+
+ buildCurrencyRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string {
+ // Special handling for currency fields - use full precision as left_digits
+
+ const effectiveScale = scale ?? 0;
+ const maxNumbersLeftOfDecimal = '9'.repeat(precision - effectiveScale);
+
+ return `|
+ ${this.openingRecipeSyntax} faker.finance.amount({min: 0, max: ${maxNumbersLeftOfDecimal}, dec: ${effectiveScale}}) ${this.closingRecipeSyntax}`;
}
diff --git a/src/treecipe/src/RecipeFakerService.ts/IRecipeFakerService.ts b/src/treecipe/src/RecipeFakerService.ts/IRecipeFakerService.ts
index 87aa6c1..375577c 100644
--- a/src/treecipe/src/RecipeFakerService.ts/IRecipeFakerService.ts
+++ b/src/treecipe/src/RecipeFakerService.ts/IRecipeFakerService.ts
@@ -28,4 +28,7 @@ export interface IRecipeFakerService {
controllingValue: string): string
getMultipicklistTODOPlaceholderWithExample(): string
getStandardAndGlobalValueSetTODOPlaceholderWithExample(): string
-}
\ No newline at end of file
+ buildTextRecipeValueWithLength(length: number): string
+ buildNumericRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string
+ buildCurrencyRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string
+}
diff --git a/src/treecipe/src/RecipeFakerService.ts/SnowfakeryRecipeFakerService/SnowfakeryRecipeFakerService.ts b/src/treecipe/src/RecipeFakerService.ts/SnowfakeryRecipeFakerService/SnowfakeryRecipeFakerService.ts
index 07c90bc..2d210ad 100644
--- a/src/treecipe/src/RecipeFakerService.ts/SnowfakeryRecipeFakerService/SnowfakeryRecipeFakerService.ts
+++ b/src/treecipe/src/RecipeFakerService.ts/SnowfakeryRecipeFakerService/SnowfakeryRecipeFakerService.ts
@@ -397,7 +397,32 @@ ${this.generateTabs(5)}${randomChoicesBreakdown}`;
const emptyMultiSelectXMLDetailPlaceholder = `### TODO: POSSIBLE GLOBAL OR STANDARD VALUE SET USED FOR THIS MULTIPICKLIST AS DETAILS ARE NOT IN FIELD XML MARKUP -- FIND ASSOCIATED VALUE SET AND REPLACE COMMA SEPARATED FRUITS WITH VALUE SET OPTIONS: \${{ (';').join((fake.random_sample(elements=('apple', 'orange', 'banana')))) }}`;
return emptyMultiSelectXMLDetailPlaceholder;
+
+ }
+
+ buildTextRecipeValueWithLength(length: number): string {
+ return `${this.openingRecipeSyntax}fake.text(max_nb_chars=${length})${this.closingRecipeSyntax}`;
+ }
+
+ buildNumericRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string {
+
+ const effectiveScale = scale ?? 0;
+ const maxNumbersLeftOfDecimal = '9'.repeat(precision - effectiveScale);
+
+ if (effectiveScale === 0) {
+ return `${this.openingRecipeSyntax}fake.random_int(min=0, max=${maxNumbersLeftOfDecimal})${this.closingRecipeSyntax}`;
+ } else {
+ return `${this.openingRecipeSyntax}fake.pydecimal(left_digits=${maxNumbersLeftOfDecimal}, right_digits=${effectiveScale}, positive=True)${this.closingRecipeSyntax}`;
+ }
+
+ }
+
+ buildCurrencyRecipeValueWithPrecisionAndScale(precision: number, scale?: number): string {
+ const effectiveScale = scale ?? 0;
+ const maxNumbersLeftOfDecimal = precision - effectiveScale;
+ return `${this.openingRecipeSyntax}fake.pydecimal(left_digits=${maxNumbersLeftOfDecimal}, right_digits=${effectiveScale}, positive=True)${this.closingRecipeSyntax}`;
+
}
-}
\ No newline at end of file
+}
diff --git a/src/treecipe/src/RecipeService/RecipeService.ts b/src/treecipe/src/RecipeService/RecipeService.ts
index 25e2730..3facf15 100644
--- a/src/treecipe/src/RecipeService/RecipeService.ts
+++ b/src/treecipe/src/RecipeService/RecipeService.ts
@@ -95,32 +95,50 @@ export class RecipeService {
return fakeRecipeValue;
case 'multiselectpicklist':
-
+
if ( !(xmlFieldDetail.picklistValues) ) {
// THIS SCENARIO INDICATEDS THAT THE PICKLIST FIELD UTILIZED A GLOBAL VALUE SET
const emptyMultiSelectXMLDetailPlaceholder = this.fakerService.getMultipicklistTODOPlaceholderWithExample();
return emptyMultiSelectXMLDetailPlaceholder;
}
const availablePicklistChoices = xmlFieldDetail.picklistValues.map(picklistOption => picklistOption.picklistOptionApiName);
- fakeRecipeValue = this.fakerService.buildMultiSelectPicklistRecipeValueByXMLFieldDetail(availablePicklistChoices,
+ fakeRecipeValue = this.fakerService.buildMultiSelectPicklistRecipeValueByXMLFieldDetail(availablePicklistChoices,
recordTypeApiToRecordTypeWrapperMap,
xmlFieldDetail.apiName
);
-
+
return fakeRecipeValue;
-
- // case 'masterdetail':
-
- // return {
- // type: 'lookup'
- // };
-
- // case 'lookup':
-
- // return 'test';
-
- default:
-
+
+ case 'text':
+ case 'textarea':
+ case 'longtextarea':
+ case 'html':
+
+ if (xmlFieldDetail.length) {
+ fakeRecipeValue = this.fakerService.buildTextRecipeValueWithLength(xmlFieldDetail.length);
+ return fakeRecipeValue;
+ }
+ // Fall through to default if no length
+
+ case 'number':
+ case 'percent':
+
+ if (xmlFieldDetail.precision) {
+ fakeRecipeValue = this.fakerService.buildNumericRecipeValueWithPrecisionAndScale(xmlFieldDetail.precision, xmlFieldDetail.scale);
+ return fakeRecipeValue;
+ }
+ // Fall through to default if no precision
+
+ case 'currency':
+
+ if (xmlFieldDetail.precision) {
+ fakeRecipeValue = this.fakerService.buildCurrencyRecipeValueWithPrecisionAndScale(xmlFieldDetail.precision, xmlFieldDetail.scale);
+ return fakeRecipeValue;
+ }
+ // Fall through to default if no precision
+
+ default:
+
fakeRecipeValue = this.getFakeValueIfExpectedSalesforceFieldType(fieldType);
return fakeRecipeValue;
@@ -296,4 +314,4 @@ ${this.generateTabs(1)}${fieldPropertAndRecipeValue}`;
}
-}
\ No newline at end of file
+}
diff --git a/src/treecipe/src/RecipeService/tests/FakerJSRecipeService.test.ts b/src/treecipe/src/RecipeService/tests/FakerJSRecipeService.test.ts
index e1d8759..92cc12d 100644
--- a/src/treecipe/src/RecipeService/tests/FakerJSRecipeService.test.ts
+++ b/src/treecipe/src/RecipeService/tests/FakerJSRecipeService.test.ts
@@ -191,9 +191,9 @@ describe('FakerJSRecipeService IRecipeService Implementation Shared Intstance Te
test('given expected number XMLFieldDetail, returns the expected fakerJS YAML recipe value', () => {
const expectedXMLDetailForNumber:XMLFieldDetail = XMLMarkupMockService.getNumberXMLFieldDetail();
- const expectedFakerJSExpressionForNumber = `|
- \${{ faker.number.int({min: 0, max: 999999}) }}`;
- const recordTypeNameByRecordTypeNameToXMLMarkup = {};
+ const expectedFakerJSExpressionForNumber = `|
+ \${{ faker.number.int({min: 0, max: 999999999999999999}) }}`;
+ const recordTypeNameByRecordTypeNameToXMLMarkup = {};
const actualFakerJSForNumber = recipeServiceWithFakerJS.getRecipeFakeValueByXMLFieldDetail(expectedXMLDetailForNumber, recordTypeNameByRecordTypeNameToXMLMarkup);
expect(actualFakerJSForNumber).toBe(expectedFakerJSExpressionForNumber);
@@ -203,7 +203,8 @@ describe('FakerJSRecipeService IRecipeService Implementation Shared Intstance Te
test('given expected currency XMLFieldDetail, returns the expected fakerJS YAML recipe value', () => {
const expectedXMLDetailForCurrency:XMLFieldDetail = XMLMarkupMockService.getCurrencyFieldDetail();
- const expectedFakerJSExpressionForCurrency = "\${{ faker.finance.amount(0, 999999, 2) }}";
+ const expectedFakerJSExpressionForCurrency = `|
+ \${{ faker.finance.amount({min: 0, max: 9999999999999999, dec: 2}) }}`;
const recordTypeNameByRecordTypeNameToXMLMarkup = {};
const actualFakerJSForCurrency = recipeServiceWithFakerJS.getRecipeFakeValueByXMLFieldDetail(expectedXMLDetailForCurrency, recordTypeNameByRecordTypeNameToXMLMarkup);
diff --git a/src/treecipe/src/RecipeService/tests/RecipeService.test.ts b/src/treecipe/src/RecipeService/tests/RecipeService.test.ts
index f0173cf..97e43e7 100644
--- a/src/treecipe/src/RecipeService/tests/RecipeService.test.ts
+++ b/src/treecipe/src/RecipeService/tests/RecipeService.test.ts
@@ -124,8 +124,8 @@ describe('SnowfakeryRecipeService IRecipeService Implementation Shared Intstance
test('given expected number XMLFieldDetail, returns the expected snowfakery YAML recipe value', () => {
const expectedXMLDetailForNumber:XMLFieldDetail = XMLMarkupMockService.getNumberXMLFieldDetail();
- const expectedSnowfakeryValueForNumber = '${{fake.random_int(min=0, max=999999)}}';
- const recordTypeNameByRecordTypeNameToXMLMarkup = {};
+ const expectedSnowfakeryValueForNumber = '${{fake.random_int(min=0, max=999999999999999999)}}';
+ const recordTypeNameByRecordTypeNameToXMLMarkup = {};
const actualSnowfakeryValueForNumber = recipeServiceWithSnow.getRecipeFakeValueByXMLFieldDetail(expectedXMLDetailForNumber, recordTypeNameByRecordTypeNameToXMLMarkup);
@@ -136,7 +136,7 @@ describe('SnowfakeryRecipeService IRecipeService Implementation Shared Intstance
test('given expected currency XMLFieldDetail, returns the expected snowfakery YAML recipe value', () => {
const expectedXMLDetailForCurrency:XMLFieldDetail = XMLMarkupMockService.getCurrencyFieldDetail();
- const expectedSnowfakeryValueForCurrency = '${{fake.pydecimal(left_digits=6, right_digits=2, positive=True)}}';
+ const expectedSnowfakeryValueForCurrency = '${{fake.pydecimal(left_digits=16, right_digits=2, positive=True)}}';
const recordTypeNameByRecordTypeNameToXMLMarkup = {};
const actualSnowfakeryValueForCurrency = recipeServiceWithSnow.getRecipeFakeValueByXMLFieldDetail(expectedXMLDetailForCurrency, recordTypeNameByRecordTypeNameToXMLMarkup);
@@ -144,6 +144,17 @@ describe('SnowfakeryRecipeService IRecipeService Implementation Shared Intstance
});
+ test('given expected text XMLFieldDetail with length, returns the expected snowfakery YAML recipe value with length limit', () => {
+
+ const expectedXMLDetailForTextWithLength:XMLFieldDetail = XMLMarkupMockService.getTextXMLFieldDetailWithLength();
+ const expectedSnowfakeryValueForTextWithLength = '${{fake.text(max_nb_chars=50)}}';
+ const recordTypeNameByRecordTypeNameToXMLMarkup = {};
+ const actualSnowfakeryValueForTextWithLength = recipeServiceWithSnow.getRecipeFakeValueByXMLFieldDetail(expectedXMLDetailForTextWithLength, recordTypeNameByRecordTypeNameToXMLMarkup);
+
+ expect(actualSnowfakeryValueForTextWithLength).toBe(expectedSnowfakeryValueForTextWithLength);
+
+ });
+
});
describe('initiateRecipeByObjectName', () => {
@@ -407,4 +418,3 @@ describe('SnowfakeryRecipeService IRecipeService Implementation Shared Intstance
});
});
-
diff --git a/src/treecipe/src/XMLProcessingService/XMLFieldDetail.ts b/src/treecipe/src/XMLProcessingService/XMLFieldDetail.ts
index f4e39a8..f4f5d80 100644
--- a/src/treecipe/src/XMLProcessingService/XMLFieldDetail.ts
+++ b/src/treecipe/src/XMLProcessingService/XMLFieldDetail.ts
@@ -10,4 +10,7 @@ export class XMLFieldDetail {
public controllingField?: string;
public xmlMarkup: string;
public isStandardValueSet?: boolean;
-}
\ No newline at end of file
+ public precision?: number;
+ public scale?: number;
+ public length?: number;
+}
diff --git a/src/treecipe/src/XMLProcessingService/XmlFileProcessor.ts b/src/treecipe/src/XMLProcessingService/XmlFileProcessor.ts
index 152f878..7109019 100644
--- a/src/treecipe/src/XMLProcessingService/XmlFileProcessor.ts
+++ b/src/treecipe/src/XMLProcessingService/XmlFileProcessor.ts
@@ -37,6 +37,22 @@ export class XmlFileProcessor {
xmlFieldDetail.fieldType = typeValue;
xmlFieldDetail.fieldLabel = fieldLabel;
+ // Parse precision, scale, and length properties (only if they exist in XML)
+ const precision = fieldXML?.CustomField?.precision?.[0];
+ if (precision !== undefined && precision !== null) {
+ xmlFieldDetail.precision = parseInt(precision, 10);
+ }
+
+ const scale = fieldXML?.CustomField?.scale?.[0];
+ if (scale !== undefined && scale !== null) {
+ xmlFieldDetail.scale = parseInt(scale, 10);
+ }
+
+ const length = fieldXML?.CustomField?.length?.[0];
+ if (length !== undefined && length !== null) {
+ xmlFieldDetail.length = parseInt(length, 10);
+ }
+
if ( typeValue === 'Picklist' || typeValue === "MultiselectPicklist") {
let picklistValueSetMarkup = fieldXML.CustomField.valueSet?.[0];
@@ -215,8 +231,3 @@ export class XmlFileProcessor {
}
-
-
-
-
-
diff --git a/src/treecipe/src/XMLProcessingService/tests/XmlFileProcessor.test.ts b/src/treecipe/src/XMLProcessingService/tests/XmlFileProcessor.test.ts
index a81c2c8..2b3b192 100644
--- a/src/treecipe/src/XMLProcessingService/tests/XmlFileProcessor.test.ts
+++ b/src/treecipe/src/XMLProcessingService/tests/XmlFileProcessor.test.ts
@@ -367,45 +367,93 @@ describe('processXmlFieldContent', () => {
});
+ test('given text field with length XML tag, parses length property correctly', async () => {
-});
+ const xmlFieldMarkup = XMLMarkupMockService.getTextFieldTypeWithLengthXMLMarkup();
+ const fakeFieldName = 'TextWithLength__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getTextXMLFieldDetailWithLength();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.length).toBe(50);
+
+ });
-describe('isXMLFileType', () => {
+ test('given number field with precision and scale XML tags, parses properties correctly', async () => {
- test('given expected xml file extension and valid filetype enum, returns true', () => {
+ const xmlFieldMarkup = XMLMarkupMockService.getNumberFieldTypeXMLMarkup();
+ const fakeFieldName = 'Number__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getNumberXMLFieldDetail();
- const validXMLFileExtensionName = 'Checkbox__c.field-meta.xml';
- const expectedVSCodeFileTypeEnum = 1;
- const isXMLFileType:boolean = XmlFileProcessor.isXMLFileType(validXMLFileExtensionName, expectedVSCodeFileTypeEnum);
- expect(isXMLFileType).toBeTruthy();
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.precision).toBe(18);
+ expect(actualFieldDetail.scale).toBe(0);
});
- test('given expected INVALID xml file extension and valid filetype enum, returns true', () => {
+ test('given currency field with precision and scale XML tags, parses properties correctly', async () => {
+
+ const xmlFieldMarkup = XMLMarkupMockService.getCurrencyFieldTypeXMLMarkup();
+ const fakeFieldName = 'Currency__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getCurrencyFieldDetail();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.precision).toBe(18);
+ expect(actualFieldDetail.scale).toBe(2);
- const invalidXMLFileExtensionName = 'noxmlextensionhere.notme';
- const expectedVSCodeFileTypeEnum = 1;
- const isXMLFileType:boolean = XmlFileProcessor.isXMLFileType(invalidXMLFileExtensionName, expectedVSCodeFileTypeEnum);
- expect(isXMLFileType).toBeFalsy();
-
});
- test('given expected valid xml file extension and INVALID filetype enum, returns true', () => {
+ test('given percent field with precision and scale XML tags, parses properties correctly', async () => {
+
+ const xmlFieldMarkup = XMLMarkupMockService.getPercentFieldTypeXMLMarkup();
+ const fakeFieldName = 'Percent__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getPercentXMLFieldDetail();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.precision).toBe(5);
+ expect(actualFieldDetail.scale).toBe(2);
- const validXMLFileExtensionName = 'Checkbox__c.field-meta.xml';
- const directoryTypeEnum = 2;
- const isXMLFileType:boolean = XmlFileProcessor.isXMLFileType(validXMLFileExtensionName, directoryTypeEnum);
- expect(isXMLFileType).toBeFalsy();
-
});
- test('given expected INVALID xml file extension and INVALID filetype enum, returns true', () => {
+ test('given field without precision/scale/length XML tags, does not set properties', async () => {
+
+ const xmlFieldMarkup = XMLMarkupMockService.getEmailFieldTypeXMLMarkup();
+ const fakeFieldName = 'Email__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getEmailXMLFieldDetail();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.precision).toBeUndefined();
+ expect(actualFieldDetail.scale).toBeUndefined();
+ expect(actualFieldDetail.length).toBeUndefined();
+
+ });
+
+ test('given long textarea field with length XML tag, parses length property correctly', async () => {
+
+ const xmlFieldMarkup = XMLMarkupMockService.getLongTextAreaFieldTypeXMLMarkup();
+ const fakeFieldName = 'LongTextArea__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getLongTextAreaXMLFieldDetail();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.length).toBe(131072);
+
+ });
+
+ test('given rich text area field with length XML tag, parses length property correctly', async () => {
+
+ const xmlFieldMarkup = XMLMarkupMockService.getRichTextAreaFieldTypeXMLMarkup();
+ const fakeFieldName = 'RichTextArea__c.field-meta.xml';
+ const actualFieldDetail = await XmlFileProcessor.processXmlFieldContent(xmlFieldMarkup, fakeFieldName);
+ const expectedXMLFieldDetail = XMLMarkupMockService.getRichTextAreaXMLFieldDetail();
+
+ expect(actualFieldDetail).toEqual(expectedXMLFieldDetail);
+ expect(actualFieldDetail.length).toBe(32768);
- const invalidXMLFileExtensionName = 'noxmlextensionhere.notme';
- const directoryTypeEnum = 2;
- const isXMLFileType:boolean = XmlFileProcessor.isXMLFileType(invalidXMLFileExtensionName, directoryTypeEnum);
- expect(isXMLFileType).toBeFalsy();
-
});
});
\ No newline at end of file
diff --git a/src/treecipe/src/XMLProcessingService/tests/mocks/XMLMarkupMockService.ts b/src/treecipe/src/XMLProcessingService/tests/mocks/XMLMarkupMockService.ts
index b9c1e10..126dac2 100644
--- a/src/treecipe/src/XMLProcessingService/tests/mocks/XMLMarkupMockService.ts
+++ b/src/treecipe/src/XMLProcessingService/tests/mocks/XMLMarkupMockService.ts
@@ -102,6 +102,7 @@ export class XMLMarkupMockService {
fieldType: "Html",
apiName: "TextAreaRich__c",
fieldLabel: "TextAreaRich",
+ length: 32768,
xmlMarkup: this.getRichTextAreaFieldTypeXMLMarkup() };
return richTextAreaXMLField;
@@ -130,6 +131,7 @@ export class XMLMarkupMockService {
const longTextAreaXMLField: XMLFieldDetail = {
fieldType: "LongTextArea",
apiName: "Text_Area_Long__c",
+ length: 131072,
fieldLabel: "Text Area Long",
xmlMarkup: this.getLongTextAreaFieldTypeXMLMarkup() };
@@ -190,10 +192,12 @@ export class XMLMarkupMockService {
fieldType: "Number",
apiName: "Number__c",
fieldLabel: "Number",
+ precision: 18,
+ scale: 0,
xmlMarkup: this.getNumberFieldTypeXMLMarkup() };
- return numberXMLField;
-
+ return numberXMLField;
+
}
static getNumberFieldTypeXMLMarkup() {
@@ -233,7 +237,6 @@ export class XMLMarkupMockService {
false
false
- 2
false
Location
@@ -263,9 +266,7 @@ export class XMLMarkupMockService {
$Organization.Longitude
BlankAsZero
- 18
false
- 2
false
Number
false
@@ -995,6 +996,8 @@ export class XMLMarkupMockService {
fieldType: "Currency",
apiName: "Currency__c",
fieldLabel: "Currency",
+ precision: 18,
+ scale: 2,
xmlMarkup: this.getCurrencyFieldTypeXMLMarkup()
};
@@ -1002,6 +1005,40 @@ export class XMLMarkupMockService {
}
+ static getPercentXMLFieldDetail() {
+
+ let xmlFieldDetail: XMLFieldDetail = {
+ fieldType: "Percent",
+ apiName: "Percent__c",
+ fieldLabel: "Percent",
+ precision: 5,
+ scale: 2,
+ xmlMarkup: this.getPercentFieldTypeXMLMarkup()
+ };
+
+ return xmlFieldDetail;
+
+ }
+
+ static getPercentFieldTypeXMLMarkup() {
+
+ const percentXMLMarkup = `
+
+
+ Percent__c
+
+ 5
+ false
+ 2
+ false
+ Percent
+
+`;
+
+ return percentXMLMarkup;
+
+ }
+
static getCurrencyFieldTypeXMLMarkup() {
const currencyXMLMarkup = `
@@ -1509,17 +1546,49 @@ export class XMLMarkupMockService {
}
static getTextXMLFieldDetail():XMLFieldDetail {
-
+
let textXMLFieldDetail: XMLFieldDetail = {
fieldType: "Text",
apiName: "Text__c",
fieldLabel: "Text",
+ length: 255,
xmlMarkup: this.getTextFieldTypeXMLMarkup()
};
return textXMLFieldDetail;
}
+ static getTextXMLFieldDetailWithLength():XMLFieldDetail {
+
+ let textXMLFieldDetail: XMLFieldDetail = {
+ fieldType: "Text",
+ apiName: "TextWithLength__c",
+ fieldLabel: "Text With Length",
+ length: 50,
+ xmlMarkup: this.getTextFieldTypeWithLengthXMLMarkup()
+ };
+
+ return textXMLFieldDetail;
+ }
+
+ static getTextFieldTypeWithLengthXMLMarkup():string {
+ const xmlTextMarkup = `
+
+
+ TextWithLength__c
+ false
+
+ 50
+ false
+ false
+ Text
+ false
+
+`;
+ return xmlTextMarkup;
+
+ }
+
static getParseStringCLEGlobalValueSetMock() {
const parseCLEGlobalAny = {
GlobalValueSet: {