Skip to content

Commit 1d2af7e

Browse files
committed
Merge branch 'master' into develop
# Conflicts: # src/core/markdown/__test__/generating-custom-object-docs.spec.ts # src/core/markdown/__test__/test-helpers.ts
2 parents a282498 + 0bfe28b commit 1d2af7e

File tree

9 files changed

+115
-4
lines changed

9 files changed

+115
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ npm-debug.log
77
/.idea/
88
/dist/
99
/lib/
10+
.sfdx/

examples/vitepress/docs/custom-objects/Price_Component__c.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,9 @@ Use this when the Price Component represents a Flat Price. To represent a Percen
6666

6767
**Type**
6868

69-
*Picklist*
69+
*Picklist*
70+
71+
#### Possible values are
72+
* List Price
73+
* Surcharge
74+
* Discount

examples/vitepress/docs/custom-objects/Sales_Order_Line__c.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,8 @@ Represents a line item on a sales order.
6262

6363
**Type**
6464

65-
*Picklist*
65+
*Picklist*
66+
67+
#### Possible values are
68+
* Charge
69+
* Discount

src/core/markdown/__test__/generating-custom-object-docs.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@ describe('Generates Custom Object documentation', () => {
5858
assertEither(result, (data) => expect(data).firstDocContains('## Fields'));
5959
});
6060

61+
it('displays the pick list values name', async () => {
62+
const customObjectBundle = unparsedObjectBundleFromRawString({
63+
rawContent: customObjectGenerator(),
64+
filePath: 'src/object/TestObject__c.object-meta.xml',
65+
});
66+
67+
const customFieldBundle = unparsedFieldBundleFromRawString({
68+
rawContent: customFieldPickListValues,
69+
filePath: 'src/object/TestField__c.field-meta.xml',
70+
parentName: 'TestObject__c',
71+
});
72+
73+
const result = await generateDocs([customObjectBundle, customFieldBundle])();
74+
expect(result).documentationBundleHasLength(1);
75+
assertEither(result, (data) => expect(data).firstDocContains('* Staging'));
76+
assertEither(result, (data) => expect(data).firstDocContains('* Active'));
77+
assertEither(result, (data) => expect(data).firstDocContains('* Inactive'));
78+
});
79+
6180
it('does not display the Fields heading if no fields are present', async () => {
6281
const input = unparsedObjectBundleFromRawString({
6382
rawContent: customObjectGenerator(),

src/core/markdown/adapters/type-to-renderable.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ function fieldMetadataToRenderable(
281281
description: field.description ? [field.description] : [],
282282
apiName: getApiName(field.name, config),
283283
fieldType: field.type,
284+
pickListValues: field.pickListValues ? {
285+
headingLevel: headingLevel + 1,
286+
heading: 'Possible values are',
287+
value: field.pickListValues,
288+
} : undefined,
284289
};
285290
}
286291

src/core/markdown/templates/custom-object-template.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export const customObjectTemplate = `
2323
**Type**
2424
2525
*{{fieldType}}*
26+
27+
{{#if pickListValues}}
28+
{{ heading pickListValues.headingLevel pickListValues.heading }}
29+
{{#each pickListValues.value}}
30+
* {{{this}}}
31+
{{/each}}
32+
{{/if}}
2633
{{/if}}
2734
2835
{{#unless @last}}---{{/unless}}

src/core/reflection/sobject/__test__/reflect-custom-field-sources.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,52 @@ describe('when parsing custom field metadata', () => {
100100
assertEither(result, (data) => expect(data[0].type.description).toBe('A Photo URL field'));
101101
});
102102

103+
test('can parse picklist values', async() => {
104+
const unparsed: UnparsedCustomFieldBundle = {
105+
type: 'customfield',
106+
name: 'Status__c',
107+
parentName: 'MyFirstObject__c',
108+
filePath: 'src/field/Status__c.field-meta.xml',
109+
content: `
110+
<?xml version="1.0" encoding="UTF-8"?>
111+
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
112+
<fullName>Status__c</fullName>
113+
<externalId>false</externalId>
114+
<label>Status</label>
115+
<required>true</required>
116+
<trackFeedHistory>false</trackFeedHistory>
117+
<description>Status</description>
118+
<type>Picklist</type>
119+
<valueSet>
120+
<restricted>true</restricted>
121+
<valueSetDefinition>
122+
<sorted>false</sorted>
123+
<value>
124+
<fullName>Staging</fullName>
125+
<default>false</default>
126+
<label>Staging</label>
127+
</value>
128+
<value>
129+
<fullName>Active</fullName>
130+
<default>false</default>
131+
<label>Active</label>
132+
</value>
133+
<value>
134+
<fullName>Inactive</fullName>
135+
<default>false</default>
136+
<label>Inactive</label>
137+
</value>
138+
</valueSetDefinition>
139+
</valueSet>
140+
</CustomField>`,
141+
};
142+
143+
const result = await reflectCustomFieldSources([unparsed])();
144+
145+
assertEither(result, (data) => expect(data[0].type.description).toBe('Status'));
146+
assertEither(result, (data) => expect(data[0].type.pickListValues).toEqual(['Staging', 'Active', 'Inactive']));
147+
});
148+
103149
test('An error is returned when the XML is in an invalid format', async () => {
104150
const unparsed: UnparsedCustomFieldBundle = {
105151
type: 'customfield',

src/core/reflection/sobject/reflect-custom-field-source.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export type CustomFieldMetadata = {
1515
label?: string | null;
1616
type?: string | null;
1717
parentName: string;
18+
pickListValues?: string[];
1819
};
1920

2021
export function reflectCustomFieldSources(
@@ -58,12 +59,34 @@ function validate(parsedResult: unknown): E.Either<Error, { CustomField: unknown
5859
}
5960

6061
function toCustomFieldMetadata(parserResult: { CustomField: unknown }): CustomFieldMetadata {
61-
const customField = typeof parserResult.CustomField === 'object' ? parserResult.CustomField : {};
62+
const customField =
63+
parserResult?.CustomField != null && typeof parserResult.CustomField === 'object' ? parserResult.CustomField : {};
6264
const defaultValues = {
6365
description: null,
6466
};
6567

66-
return { ...defaultValues, ...customField, type_name: 'customfield' } as CustomFieldMetadata;
68+
const pickListValues =
69+
hasType(customField) && customField.type?.toLowerCase() === 'picklist' ? toPickListValues(customField) : undefined;
70+
return { ...defaultValues, ...customField, type_name: 'customfield', pickListValues } as CustomFieldMetadata;
71+
}
72+
73+
function toPickListValues(customField: object): string[] {
74+
if ('valueSet' in customField) {
75+
const valueSet = customField.valueSet as object;
76+
if ('valueSetDefinition' in valueSet) {
77+
const valueSetDefinition = valueSet.valueSetDefinition as object;
78+
if ('value' in valueSetDefinition) {
79+
const pickListValues = valueSetDefinition.value as object[];
80+
return pickListValues.filter((each) => 'fullName' in each).map((each) => each.fullName as string);
81+
}
82+
}
83+
}
84+
85+
return [];
86+
}
87+
88+
function hasType(customField: object): customField is CustomFieldMetadata {
89+
return !!(customField as CustomFieldMetadata).type;
6790
}
6891

6992
function addName(metadata: CustomFieldMetadata, name: string): CustomFieldMetadata {

src/core/renderables/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ export type RenderableCustomField = {
189189
heading: string;
190190
apiName: string;
191191
description: RenderableContent[];
192+
pickListValues?: RenderableSection<string[]>
192193
type: 'field';
193194
fieldType?: string | null;
194195
};

0 commit comments

Comments
 (0)