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: {