Skip to content

Commit a0c3a8d

Browse files
committed
Add enableApexApprovalLockUnlock to login scratch --setting Options
1 parent 7a49f9f commit a0c3a8d

File tree

4 files changed

+113
-27
lines changed

4 files changed

+113
-27
lines changed

command/login.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ const (
8181
EnableEnhancedNotes ScratchSetting = iota
8282
EnableQuote
8383
NetworksEnabled
84+
EnableApexApprovalLockUnlock
8485
)
8586

8687
var ScratchSettingIds = map[ScratchSetting][]string{
87-
EnableEnhancedNotes: {"enableEnhancedNotes"},
88-
EnableQuote: {"enableQuote"},
89-
NetworksEnabled: {"networksEnabled"},
88+
EnableEnhancedNotes: {"enableEnhancedNotes"},
89+
EnableQuote: {"enableQuote"},
90+
NetworksEnabled: {"networksEnabled"},
91+
EnableApexApprovalLockUnlock: {"enableApexApprovalLockUnlock"},
9092
}
9193

9294
var (
@@ -174,6 +176,7 @@ Available Settings (deployed after org creation):
174176
enableEnhancedNotes - Enable Enhanced Notes
175177
enableQuote - Enable Quotes
176178
networksEnabled - Enable Experience Cloud (Communities)
179+
enableApexApprovalLockUnlock - Allow Apex to lock/unlock approval processes
177180
178181
Examples:
179182
force login scratch --product fsc

command/login_test.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,33 @@ func TestExpandProductsToFeatures_CommunitiesProduct(t *testing.T) {
162162
}
163163
}
164164

165+
func TestExpandProductsToFeatures_HealthCloudProduct(t *testing.T) {
166+
result := expandProductsToFeatures([]ScratchProduct{HealthCloudProduct}, []ScratchFeature{}, map[string]string{})
167+
if len(result) != 2 {
168+
t.Errorf("Expected 2 features from health cloud product, got %d", len(result))
169+
}
170+
featureMap := make(map[string]bool)
171+
for _, f := range result {
172+
featureMap[f] = true
173+
}
174+
if !featureMap["HealthCloudAddOn"] {
175+
t.Error("Expected HealthCloudAddOn in health cloud product")
176+
}
177+
if !featureMap["HealthCloudUser"] {
178+
t.Error("Expected HealthCloudUser in health cloud product")
179+
}
180+
}
181+
182+
func TestExpandProductsToFeatures_ApexUserModeWithPermset(t *testing.T) {
183+
result := expandProductsToFeatures([]ScratchProduct{}, []ScratchFeature{ApexUserModeWithPermset}, map[string]string{})
184+
if len(result) != 1 {
185+
t.Fatalf("Expected 1 feature, got %d", len(result))
186+
}
187+
if result[0] != "ApexUserModeWithPermset" {
188+
t.Errorf("Expected ApexUserModeWithPermset, got %s", result[0])
189+
}
190+
}
191+
165192
func TestExpandProductsToSettings_NoProductsOrSettings(t *testing.T) {
166193
result := expandProductsToSettings([]ScratchProduct{}, []ScratchSetting{})
167194
if len(result) != 0 {
@@ -281,11 +308,22 @@ func TestConvertSettingsToStrings_NetworksEnabled(t *testing.T) {
281308
}
282309
}
283310

311+
func TestConvertSettingsToStrings_EnableApexApprovalLockUnlock(t *testing.T) {
312+
result := convertSettingsToStrings([]ScratchSetting{EnableApexApprovalLockUnlock})
313+
if len(result) != 1 {
314+
t.Errorf("Expected 1 setting, got %d", len(result))
315+
}
316+
if result[0] != "enableApexApprovalLockUnlock" {
317+
t.Errorf("Expected enableApexApprovalLockUnlock, got %s", result[0])
318+
}
319+
}
320+
284321
func TestScratchSettingIds_AllSettingsDefined(t *testing.T) {
285322
expectedSettings := map[string]bool{
286-
"enableEnhancedNotes": true,
287-
"enableQuote": true,
288-
"networksEnabled": true,
323+
"enableEnhancedNotes": true,
324+
"enableQuote": true,
325+
"networksEnabled": true,
326+
"enableApexApprovalLockUnlock": true,
289327
}
290328

291329
if len(ScratchSettingIds) != len(expectedSettings) {

lib/scratch.go

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,34 @@ func (s *ScratchOrg) getSession() (session ForceSession, err error) {
104104

105105
// DeploySettings deploys settings metadata to a scratch org
106106
func (f *Force) DeploySettings(settings []string) error {
107+
files := buildSettingsMetadata(settings)
108+
109+
// Deploy the metadata
110+
options := ForceDeployOptions{}
111+
result, err := f.Metadata.Deploy(files, options)
112+
if err != nil {
113+
return fmt.Errorf("settings deployment failed: %w", err)
114+
}
115+
116+
// Check if deployment succeeded
117+
if !result.Success {
118+
errorMsg := fmt.Sprintf("Settings deployment failed with status: %s", result.Status)
119+
if result.ErrorMessage != "" {
120+
errorMsg += fmt.Sprintf(": %s", result.ErrorMessage)
121+
}
122+
if len(result.Details.ComponentFailures) > 0 {
123+
errorMsg += "\nComponent failures:"
124+
for _, failure := range result.Details.ComponentFailures {
125+
errorMsg += fmt.Sprintf("\n - %s: %s", failure.FileName, failure.Problem)
126+
}
127+
}
128+
return errors.New(errorMsg)
129+
}
130+
131+
return nil
132+
}
133+
134+
func buildSettingsMetadata(settings []string) ForceMetadataFiles {
107135
files := make(ForceMetadataFiles)
108136

109137
// Create package.xml at root of zip
@@ -118,6 +146,8 @@ func (f *Force) DeploySettings(settings []string) error {
118146
files["unpackaged/package.xml"] = []byte(packageXml)
119147

120148
// Create settings file for each requested setting
149+
apexSettings := false
150+
121151
for _, setting := range settings {
122152
switch setting {
123153
case "enableEnhancedNotes":
@@ -139,32 +169,21 @@ func (f *Force) DeploySettings(settings []string) error {
139169
<enableNetworksEnabled>true</enableNetworksEnabled>
140170
</CommunitiesSettings>`
141171
files["unpackaged/settings/Communities.settings"] = []byte(communitiesSettings)
172+
case "enableApexApprovalLockUnlock":
173+
apexSettings = true
142174
}
143175
}
144176

145-
// Deploy the metadata
146-
options := ForceDeployOptions{}
147-
result, err := f.Metadata.Deploy(files, options)
148-
if err != nil {
149-
return err
177+
if apexSettings {
178+
var apexBuffer bytes.Buffer
179+
apexBuffer.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
180+
<ApexSettings xmlns="http://soap.sforce.com/2006/04/metadata">
181+
<enableApexApprovalLockUnlock>true</enableApexApprovalLockUnlock>
182+
</ApexSettings>`)
183+
files["unpackaged/settings/Apex.settings"] = apexBuffer.Bytes()
150184
}
151185

152-
// Check if deployment succeeded
153-
if !result.Success {
154-
errorMsg := fmt.Sprintf("Settings deployment failed with status: %s", result.Status)
155-
if result.ErrorMessage != "" {
156-
errorMsg += fmt.Sprintf(": %s", result.ErrorMessage)
157-
}
158-
if len(result.Details.ComponentFailures) > 0 {
159-
errorMsg += "\nComponent failures:"
160-
for _, failure := range result.Details.ComponentFailures {
161-
errorMsg += fmt.Sprintf("\n - %s: %s", failure.FileName, failure.Problem)
162-
}
163-
}
164-
return errors.New(errorMsg)
165-
}
166-
167-
return nil
186+
return files
168187
}
169188

170189
// Create a new Scratch Org from a Dev Hub Org

lib/scratch_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package lib
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestBuildSettingsMetadata_AddsOrgPreferenceSettings(t *testing.T) {
9+
files := buildSettingsMetadata([]string{"enableApexApprovalLockUnlock"})
10+
11+
content, ok := files["unpackaged/settings/Apex.settings"]
12+
if !ok {
13+
t.Fatalf("Apex.settings not generated")
14+
}
15+
if !strings.Contains(string(content), "<enableApexApprovalLockUnlock>true</enableApexApprovalLockUnlock>") {
16+
t.Errorf("Apex.settings missing enableApexApprovalLockUnlock preference:\n%s", content)
17+
}
18+
}
19+
20+
func TestBuildSettingsMetadata_ExcludesApexSettingsWhenUnused(t *testing.T) {
21+
files := buildSettingsMetadata([]string{"enableEnhancedNotes"})
22+
23+
if _, ok := files["unpackaged/settings/Apex.settings"]; ok {
24+
t.Fatalf("Apex.settings should not be generated when no Apex settings requested")
25+
}
26+
}

0 commit comments

Comments
 (0)