cumulusci-plus 5.0.19__py3-none-any.whl → 5.0.35__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cumulusci/__about__.py +1 -1
- cumulusci/cli/logger.py +2 -2
- cumulusci/cli/service.py +20 -0
- cumulusci/cli/task.py +17 -0
- cumulusci/cli/tests/test_error.py +3 -1
- cumulusci/cli/tests/test_flow.py +279 -2
- cumulusci/cli/tests/test_service.py +15 -12
- cumulusci/cli/tests/test_task.py +88 -2
- cumulusci/cli/tests/utils.py +1 -4
- cumulusci/core/config/base_task_flow_config.py +26 -1
- cumulusci/core/config/project_config.py +2 -20
- cumulusci/core/config/tests/test_config_expensive.py +9 -3
- cumulusci/core/config/universal_config.py +3 -4
- cumulusci/core/dependencies/base.py +1 -1
- cumulusci/core/dependencies/dependencies.py +1 -1
- cumulusci/core/dependencies/github.py +1 -2
- cumulusci/core/dependencies/resolvers.py +1 -1
- cumulusci/core/dependencies/tests/test_dependencies.py +1 -1
- cumulusci/core/dependencies/tests/test_resolvers.py +1 -1
- cumulusci/core/flowrunner.py +90 -6
- cumulusci/core/github.py +1 -1
- cumulusci/core/sfdx.py +3 -1
- cumulusci/core/source_transforms/tests/test_transforms.py +1 -1
- cumulusci/core/source_transforms/transforms.py +1 -1
- cumulusci/core/tasks.py +13 -2
- cumulusci/core/tests/test_flowrunner.py +100 -0
- cumulusci/core/tests/test_tasks.py +65 -0
- cumulusci/core/utils.py +3 -1
- cumulusci/core/versions.py +1 -1
- cumulusci/cumulusci.yml +55 -0
- cumulusci/oauth/client.py +1 -1
- cumulusci/plugins/plugin_base.py +5 -3
- cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +1 -1
- cumulusci/salesforce_api/rest_deploy.py +1 -1
- cumulusci/schema/cumulusci.jsonschema.json +64 -0
- cumulusci/tasks/apex/anon.py +1 -1
- cumulusci/tasks/apex/testrunner.py +416 -142
- cumulusci/tasks/apex/tests/test_apex_tasks.py +917 -1
- cumulusci/tasks/bulkdata/extract.py +0 -1
- cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +1 -1
- cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +1 -1
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +1 -1
- cumulusci/tasks/bulkdata/generate_and_load_data.py +136 -12
- cumulusci/tasks/bulkdata/mapping_parser.py +139 -44
- cumulusci/tasks/bulkdata/select_utils.py +1 -1
- cumulusci/tasks/bulkdata/snowfakery.py +100 -25
- cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +159 -0
- cumulusci/tasks/bulkdata/tests/test_load.py +0 -2
- cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +763 -1
- cumulusci/tasks/bulkdata/tests/test_select_utils.py +26 -0
- cumulusci/tasks/bulkdata/tests/test_snowfakery.py +133 -0
- cumulusci/tasks/create_package_version.py +190 -16
- cumulusci/tasks/datadictionary.py +1 -1
- cumulusci/tasks/metadata_etl/base.py +7 -3
- cumulusci/tasks/metadata_etl/layouts.py +1 -1
- cumulusci/tasks/metadata_etl/permissions.py +1 -1
- cumulusci/tasks/metadata_etl/remote_site_settings.py +2 -2
- cumulusci/tasks/push/README.md +15 -17
- cumulusci/tasks/release_notes/README.md +13 -13
- cumulusci/tasks/release_notes/generator.py +13 -8
- cumulusci/tasks/robotframework/tests/test_robotframework.py +6 -1
- cumulusci/tasks/salesforce/Deploy.py +53 -2
- cumulusci/tasks/salesforce/SfPackageCommands.py +363 -0
- cumulusci/tasks/salesforce/__init__.py +1 -0
- cumulusci/tasks/salesforce/assign_ps_psg.py +448 -0
- cumulusci/tasks/salesforce/composite.py +1 -1
- cumulusci/tasks/salesforce/custom_settings_wait.py +1 -1
- cumulusci/tasks/salesforce/enable_prediction.py +5 -1
- cumulusci/tasks/salesforce/getPackageVersion.py +89 -0
- cumulusci/tasks/salesforce/profiles.py +13 -9
- cumulusci/tasks/salesforce/sourcetracking.py +1 -1
- cumulusci/tasks/salesforce/tests/test_Deploy.py +316 -1
- cumulusci/tasks/salesforce/tests/test_SfPackageCommands.py +554 -0
- cumulusci/tasks/salesforce/tests/test_assign_ps_psg.py +1055 -0
- cumulusci/tasks/salesforce/tests/test_getPackageVersion.py +651 -0
- cumulusci/tasks/salesforce/tests/test_profiles.py +43 -3
- cumulusci/tasks/salesforce/tests/test_update_dependencies.py +1 -1
- cumulusci/tasks/salesforce/tests/test_update_external_credential.py +912 -0
- cumulusci/tasks/salesforce/tests/test_update_named_credential.py +1042 -0
- cumulusci/tasks/salesforce/update_dependencies.py +2 -2
- cumulusci/tasks/salesforce/update_external_credential.py +562 -0
- cumulusci/tasks/salesforce/update_named_credential.py +441 -0
- cumulusci/tasks/salesforce/update_profile.py +17 -13
- cumulusci/tasks/salesforce/users/permsets.py +62 -5
- cumulusci/tasks/salesforce/users/tests/test_permsets.py +237 -11
- cumulusci/tasks/sfdmu/__init__.py +0 -0
- cumulusci/tasks/sfdmu/sfdmu.py +363 -0
- cumulusci/tasks/sfdmu/tests/__init__.py +1 -0
- cumulusci/tasks/sfdmu/tests/test_runner.py +212 -0
- cumulusci/tasks/sfdmu/tests/test_sfdmu.py +1012 -0
- cumulusci/tasks/tests/test_create_package_version.py +716 -1
- cumulusci/tasks/tests/test_util.py +42 -0
- cumulusci/tasks/util.py +37 -1
- cumulusci/tasks/utility/copyContents.py +402 -0
- cumulusci/tasks/utility/credentialManager.py +256 -0
- cumulusci/tasks/utility/directoryRecreator.py +30 -0
- cumulusci/tasks/utility/env_management.py +1 -1
- cumulusci/tasks/utility/secretsToEnv.py +135 -0
- cumulusci/tasks/utility/tests/test_copyContents.py +1719 -0
- cumulusci/tasks/utility/tests/test_credentialManager.py +564 -0
- cumulusci/tasks/utility/tests/test_directoryRecreator.py +439 -0
- cumulusci/tasks/utility/tests/test_secretsToEnv.py +1091 -0
- cumulusci/tests/test_integration_infrastructure.py +3 -1
- cumulusci/tests/test_utils.py +70 -6
- cumulusci/utils/__init__.py +54 -9
- cumulusci/utils/classutils.py +5 -2
- cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +31 -30
- cumulusci/utils/options.py +23 -1
- cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +1 -1
- cumulusci/utils/yaml/cumulusci_yml.py +7 -3
- cumulusci/utils/yaml/model_parser.py +2 -2
- cumulusci/utils/yaml/tests/test_cumulusci_yml.py +1 -1
- cumulusci/utils/yaml/tests/test_model_parser.py +3 -3
- cumulusci/vcs/base.py +23 -15
- cumulusci/vcs/bootstrap.py +5 -4
- cumulusci/vcs/utils/list_modified_files.py +189 -0
- cumulusci/vcs/utils/tests/test_list_modified_files.py +588 -0
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/METADATA +12 -10
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/RECORD +123 -98
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/WHEEL +0 -0
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/entry_points.txt +0 -0
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/licenses/AUTHORS.rst +0 -0
- {cumulusci_plus-5.0.19.dist-info → cumulusci_plus-5.0.35.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,912 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
import responses
|
|
6
|
+
|
|
7
|
+
from cumulusci.core.exceptions import SalesforceDXException
|
|
8
|
+
from cumulusci.tasks.salesforce.update_external_credential import (
|
|
9
|
+
ExternalCredential,
|
|
10
|
+
ExternalCredentialParameter,
|
|
11
|
+
ExtParameter,
|
|
12
|
+
HttpHeader,
|
|
13
|
+
TransformExternalCredentialParameter,
|
|
14
|
+
UpdateExternalCredential,
|
|
15
|
+
)
|
|
16
|
+
from cumulusci.tests.util import CURRENT_SF_API_VERSION
|
|
17
|
+
|
|
18
|
+
from .util import create_task
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestExtParameter:
|
|
22
|
+
"""Test ExtParameter model"""
|
|
23
|
+
|
|
24
|
+
def test_ext_parameter_defaults(self):
|
|
25
|
+
"""Test default values for ext parameter"""
|
|
26
|
+
param = ExtParameter(name="test-param", value="test-value")
|
|
27
|
+
assert param.name == "test-param"
|
|
28
|
+
assert param.value == "test-value"
|
|
29
|
+
assert param.group is None
|
|
30
|
+
assert param.sequence_number is None
|
|
31
|
+
|
|
32
|
+
def test_ext_parameter_with_all_fields(self):
|
|
33
|
+
"""Test ext parameter with all fields"""
|
|
34
|
+
param = ExtParameter(
|
|
35
|
+
name="test-param", value="test-value", group="TestGroup", sequence_number=1
|
|
36
|
+
)
|
|
37
|
+
assert param.name == "test-param"
|
|
38
|
+
assert param.value == "test-value"
|
|
39
|
+
assert param.group == "TestGroup"
|
|
40
|
+
assert param.sequence_number == 1
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TestHttpHeader:
|
|
44
|
+
"""Test HttpHeader model"""
|
|
45
|
+
|
|
46
|
+
def test_http_header_defaults(self):
|
|
47
|
+
"""Test default values for http header"""
|
|
48
|
+
header = HttpHeader(name="test-header", value="test-value")
|
|
49
|
+
assert header.name == "test-header"
|
|
50
|
+
assert header.value == "test-value"
|
|
51
|
+
assert header.secret is False
|
|
52
|
+
assert header.sequence_number is None
|
|
53
|
+
|
|
54
|
+
def test_http_header_with_secret(self):
|
|
55
|
+
"""Test http header with secret flag"""
|
|
56
|
+
header = HttpHeader(
|
|
57
|
+
name="api-key", value="secret123", secret=True, sequence_number=1
|
|
58
|
+
)
|
|
59
|
+
assert header.name == "api-key"
|
|
60
|
+
assert header.value == "secret123"
|
|
61
|
+
assert header.secret is True
|
|
62
|
+
assert header.sequence_number == 1
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class TestExternalCredential:
|
|
66
|
+
"""Test ExternalCredential model"""
|
|
67
|
+
|
|
68
|
+
def test_external_credential_defaults(self):
|
|
69
|
+
"""Test default values for external credential"""
|
|
70
|
+
cred = ExternalCredential(name="test-cred", value="test-value")
|
|
71
|
+
assert cred.name == "test-cred"
|
|
72
|
+
assert cred.value == "test-value"
|
|
73
|
+
assert cred.client_secret is None
|
|
74
|
+
assert cred.client_id is None
|
|
75
|
+
assert cred.auth_protocol == "OAuth"
|
|
76
|
+
|
|
77
|
+
def test_external_credential_with_oauth(self):
|
|
78
|
+
"""Test external credential with OAuth fields"""
|
|
79
|
+
cred = ExternalCredential(
|
|
80
|
+
name="oauth-cred",
|
|
81
|
+
value="test-value",
|
|
82
|
+
client_id="client123",
|
|
83
|
+
client_secret="secret456",
|
|
84
|
+
auth_protocol="OAuth2",
|
|
85
|
+
)
|
|
86
|
+
assert cred.name == "oauth-cred"
|
|
87
|
+
assert cred.value == "test-value"
|
|
88
|
+
assert cred.client_id == "client123"
|
|
89
|
+
assert cred.client_secret == "secret456"
|
|
90
|
+
assert cred.auth_protocol == "OAuth2"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TestExternalCredentialParameter:
|
|
94
|
+
"""Test ExternalCredentialParameter model"""
|
|
95
|
+
|
|
96
|
+
def test_parameter_with_auth_header(self):
|
|
97
|
+
"""Test parameter with auth header"""
|
|
98
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer token123")
|
|
99
|
+
param = ExternalCredentialParameter(auth_header=auth_header)
|
|
100
|
+
assert param.auth_header == auth_header
|
|
101
|
+
result = param.get_external_credential_parameter()
|
|
102
|
+
assert result["parameterType"] == "AuthHeader"
|
|
103
|
+
assert result["parameterValue"] == "Bearer token123"
|
|
104
|
+
assert result["parameterName"] == "Authorization"
|
|
105
|
+
|
|
106
|
+
def test_parameter_with_auth_provider(self):
|
|
107
|
+
"""Test parameter with auth provider"""
|
|
108
|
+
param = ExternalCredentialParameter(auth_provider="MyAuthProvider")
|
|
109
|
+
assert param.auth_provider == "MyAuthProvider"
|
|
110
|
+
result = param.get_external_credential_parameter()
|
|
111
|
+
assert result["parameterType"] == "AuthProvider"
|
|
112
|
+
assert result["parameterValue"] == "MyAuthProvider"
|
|
113
|
+
assert result["parameterName"] == "AuthProvider"
|
|
114
|
+
|
|
115
|
+
def test_parameter_with_auth_provider_url(self):
|
|
116
|
+
"""Test parameter with auth provider URL"""
|
|
117
|
+
param = ExternalCredentialParameter(
|
|
118
|
+
auth_provider_url="https://auth.example.com"
|
|
119
|
+
)
|
|
120
|
+
assert param.auth_provider_url == "https://auth.example.com"
|
|
121
|
+
result = param.get_external_credential_parameter()
|
|
122
|
+
assert result["parameterType"] == "AuthProviderUrl"
|
|
123
|
+
assert result["parameterValue"] == "https://auth.example.com"
|
|
124
|
+
|
|
125
|
+
def test_parameter_with_jwt_body_claim(self):
|
|
126
|
+
"""Test parameter with JWT body claim"""
|
|
127
|
+
jwt_claim = ExtParameter(name="sub", value='{"sub":"user123"}')
|
|
128
|
+
param = ExternalCredentialParameter(jwt_body_claim=jwt_claim)
|
|
129
|
+
assert param.jwt_body_claim == jwt_claim
|
|
130
|
+
result = param.get_external_credential_parameter()
|
|
131
|
+
assert result["parameterType"] == "JwtBodyClaim"
|
|
132
|
+
assert result["parameterValue"] == '{"sub":"user123"}'
|
|
133
|
+
assert result["parameterName"] == "sub"
|
|
134
|
+
|
|
135
|
+
def test_parameter_with_named_principal(self):
|
|
136
|
+
"""Test parameter with named principal"""
|
|
137
|
+
named_principal = ExternalCredential(
|
|
138
|
+
name="MyPrincipal",
|
|
139
|
+
value="test-value",
|
|
140
|
+
client_id="client123",
|
|
141
|
+
client_secret="secret456",
|
|
142
|
+
)
|
|
143
|
+
param = ExternalCredentialParameter(named_principal=named_principal)
|
|
144
|
+
assert param.named_principal == named_principal
|
|
145
|
+
result = param.get_external_credential_parameter()
|
|
146
|
+
assert result["parameterType"] == "NamedPrincipal"
|
|
147
|
+
assert result["parameterName"] == "MyPrincipal"
|
|
148
|
+
|
|
149
|
+
def test_parameter_with_signing_certificate(self):
|
|
150
|
+
"""Test parameter with signing certificate"""
|
|
151
|
+
param = ExternalCredentialParameter(signing_certificate="MyCertificate")
|
|
152
|
+
assert param.signing_certificate == "MyCertificate"
|
|
153
|
+
result = param.get_external_credential_parameter()
|
|
154
|
+
assert result["parameterType"] == "SigningCertificate"
|
|
155
|
+
assert result["parameterValue"] == "MyCertificate"
|
|
156
|
+
assert result["parameterName"] == "SigningCertificate"
|
|
157
|
+
|
|
158
|
+
def test_parameter_validation_error_no_params(self):
|
|
159
|
+
"""Test that at least one parameter must be provided"""
|
|
160
|
+
with pytest.raises(
|
|
161
|
+
ValueError, match="At least and only one parameter must be provided"
|
|
162
|
+
):
|
|
163
|
+
ExternalCredentialParameter()
|
|
164
|
+
|
|
165
|
+
def test_parameter_validation_error_multiple_params(self):
|
|
166
|
+
"""Test that only one parameter can be provided"""
|
|
167
|
+
auth_header = HttpHeader(name="Auth", value="Bearer token")
|
|
168
|
+
with pytest.raises(
|
|
169
|
+
ValueError, match="At least and only one parameter must be provided"
|
|
170
|
+
):
|
|
171
|
+
ExternalCredentialParameter(
|
|
172
|
+
auth_header=auth_header, auth_provider="MyProvider"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def test_get_principal_credential(self):
|
|
176
|
+
"""Test get_principal_credential method"""
|
|
177
|
+
named_principal = ExternalCredential(name="MyPrincipal", value="test")
|
|
178
|
+
param = ExternalCredentialParameter(named_principal=named_principal)
|
|
179
|
+
result = param.get_principal_credential("MyExternalCredential")
|
|
180
|
+
assert result["principalType"] == "NamedPrincipal"
|
|
181
|
+
assert result["principalName"] == "MyPrincipal"
|
|
182
|
+
assert result["externalCredential"] == "MyExternalCredential"
|
|
183
|
+
|
|
184
|
+
def test_get_credential_parameter(self):
|
|
185
|
+
"""Test get_credential_parameter method"""
|
|
186
|
+
named_principal = ExternalCredential(
|
|
187
|
+
name="MyPrincipal",
|
|
188
|
+
value="test",
|
|
189
|
+
client_id="client123",
|
|
190
|
+
client_secret="secret456",
|
|
191
|
+
)
|
|
192
|
+
param = ExternalCredentialParameter(named_principal=named_principal)
|
|
193
|
+
result = param.get_credential_parameter()
|
|
194
|
+
assert result["clientId"]["value"] == "client123"
|
|
195
|
+
assert result["clientSecret"]["value"] == "secret456"
|
|
196
|
+
assert result["clientId"]["encrypted"] is False
|
|
197
|
+
assert result["clientSecret"]["encrypted"] is True
|
|
198
|
+
|
|
199
|
+
def test_get_credential(self):
|
|
200
|
+
"""Test get_credential method"""
|
|
201
|
+
named_principal = ExternalCredential(
|
|
202
|
+
name="MyPrincipal",
|
|
203
|
+
value="test",
|
|
204
|
+
client_id="client123",
|
|
205
|
+
client_secret="secret456",
|
|
206
|
+
auth_protocol="OAuth2",
|
|
207
|
+
)
|
|
208
|
+
param = ExternalCredentialParameter(named_principal=named_principal)
|
|
209
|
+
result = param.get_credential("MyExternalCredential")
|
|
210
|
+
assert result["principalType"] == "NamedPrincipal"
|
|
211
|
+
assert result["principalName"] == "MyPrincipal"
|
|
212
|
+
assert result["externalCredential"] == "MyExternalCredential"
|
|
213
|
+
assert result["authenticationProtocol"] == "OAuth2"
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class TestTransformExternalCredentialParameter:
|
|
217
|
+
"""Test TransformExternalCredentialParameter model"""
|
|
218
|
+
|
|
219
|
+
def test_transform_parameter_from_env(self):
|
|
220
|
+
"""Test parameter transformation from environment variable"""
|
|
221
|
+
with mock.patch.dict(os.environ, {"MY_AUTH_HEADER": "Bearer token456"}):
|
|
222
|
+
auth_header = HttpHeader(name="Authorization", value="MY_AUTH_HEADER")
|
|
223
|
+
param = TransformExternalCredentialParameter(auth_header=auth_header)
|
|
224
|
+
result = param.get_external_credential_parameter()
|
|
225
|
+
assert result["parameterValue"] == "Bearer token456"
|
|
226
|
+
|
|
227
|
+
def test_transform_parameter_auth_provider_from_env(self):
|
|
228
|
+
"""Test auth provider transformation from environment variable"""
|
|
229
|
+
with mock.patch.dict(os.environ, {"MY_AUTH_PROVIDER": "EnvAuthProvider"}):
|
|
230
|
+
param = TransformExternalCredentialParameter(
|
|
231
|
+
auth_provider="MY_AUTH_PROVIDER"
|
|
232
|
+
)
|
|
233
|
+
result = param.get_external_credential_parameter()
|
|
234
|
+
assert result["parameterValue"] == "EnvAuthProvider"
|
|
235
|
+
|
|
236
|
+
def test_transform_parameter_missing_env(self):
|
|
237
|
+
"""Test parameter transformation with missing environment variable"""
|
|
238
|
+
auth_header = HttpHeader(name="Auth", value="NONEXISTENT_ENV_VAR")
|
|
239
|
+
param = TransformExternalCredentialParameter(auth_header=auth_header)
|
|
240
|
+
result = param.get_external_credential_parameter()
|
|
241
|
+
assert result["parameterValue"] is None
|
|
242
|
+
|
|
243
|
+
def test_transform_credential_parameter_from_env(self):
|
|
244
|
+
"""Test credential parameter transformation from environment variable"""
|
|
245
|
+
with mock.patch.dict(os.environ, {"CLIENT_SECRET": "secret123"}):
|
|
246
|
+
named_principal = ExternalCredential(
|
|
247
|
+
name="MyPrincipal",
|
|
248
|
+
value="test",
|
|
249
|
+
client_id="client123",
|
|
250
|
+
client_secret="CLIENT_SECRET",
|
|
251
|
+
)
|
|
252
|
+
param = TransformExternalCredentialParameter(
|
|
253
|
+
named_principal=named_principal
|
|
254
|
+
)
|
|
255
|
+
result = param.get_credential_parameter()
|
|
256
|
+
assert result["clientSecret"]["value"] == "secret123"
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
class TestUpdateExternalCredential:
|
|
260
|
+
"""Test UpdateExternalCredential task"""
|
|
261
|
+
|
|
262
|
+
@responses.activate
|
|
263
|
+
def test_update_external_credential_success(self):
|
|
264
|
+
"""Test successful update of external credential"""
|
|
265
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer newtoken123")
|
|
266
|
+
task = create_task(
|
|
267
|
+
UpdateExternalCredential,
|
|
268
|
+
{
|
|
269
|
+
"name": "testExtCred",
|
|
270
|
+
"namespace": "",
|
|
271
|
+
"parameters": [{"auth_header": auth_header}],
|
|
272
|
+
},
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
276
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
277
|
+
|
|
278
|
+
# Mock query for external credential ID
|
|
279
|
+
responses.add(
|
|
280
|
+
method="GET",
|
|
281
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
282
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
283
|
+
status=200,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Mock get external credential object
|
|
287
|
+
responses.add(
|
|
288
|
+
method="GET",
|
|
289
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
290
|
+
json={
|
|
291
|
+
"Metadata": {
|
|
292
|
+
"description": "Old description",
|
|
293
|
+
"externalCredentialParameters": [
|
|
294
|
+
{
|
|
295
|
+
"parameterType": "AuthHeader",
|
|
296
|
+
"parameterValue": "Bearer oldtoken123",
|
|
297
|
+
"description": None,
|
|
298
|
+
"parameterName": None,
|
|
299
|
+
"sequenceNumber": None,
|
|
300
|
+
}
|
|
301
|
+
],
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
status=200,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# Mock update external credential
|
|
308
|
+
responses.add(
|
|
309
|
+
method="PATCH",
|
|
310
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
311
|
+
json={},
|
|
312
|
+
status=200,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
task()
|
|
316
|
+
assert len(responses.calls) == 3
|
|
317
|
+
|
|
318
|
+
@responses.activate
|
|
319
|
+
def test_update_external_credential_with_named_principal(self):
|
|
320
|
+
"""Test update with named principal and credential management"""
|
|
321
|
+
named_principal = ExternalCredential(
|
|
322
|
+
name="MyPrincipal",
|
|
323
|
+
value="test-value",
|
|
324
|
+
client_id="client123",
|
|
325
|
+
client_secret="secret456",
|
|
326
|
+
auth_protocol="OAuth2",
|
|
327
|
+
)
|
|
328
|
+
task = create_task(
|
|
329
|
+
UpdateExternalCredential,
|
|
330
|
+
{
|
|
331
|
+
"name": "testExtCred",
|
|
332
|
+
"parameters": [{"named_principal": named_principal}],
|
|
333
|
+
},
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
337
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
338
|
+
connect_url = (
|
|
339
|
+
f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}"
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Mock query for external credential ID
|
|
343
|
+
responses.add(
|
|
344
|
+
method="GET",
|
|
345
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
346
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
347
|
+
status=200,
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# Mock get external credential object
|
|
351
|
+
responses.add(
|
|
352
|
+
method="GET",
|
|
353
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
354
|
+
json={
|
|
355
|
+
"Metadata": {
|
|
356
|
+
"externalCredentialParameters": [
|
|
357
|
+
{
|
|
358
|
+
"parameterType": "NamedPrincipal",
|
|
359
|
+
"parameterName": "MyPrincipal",
|
|
360
|
+
"parameterValue": None,
|
|
361
|
+
}
|
|
362
|
+
],
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
status=200,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Mock update external credential
|
|
369
|
+
responses.add(
|
|
370
|
+
method="PATCH",
|
|
371
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
372
|
+
json={},
|
|
373
|
+
status=200,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Mock get credential (existing)
|
|
377
|
+
responses.add(
|
|
378
|
+
method="GET",
|
|
379
|
+
url=f"{connect_url}/named-credentials/credential",
|
|
380
|
+
json={
|
|
381
|
+
"principalType": "NamedPrincipal",
|
|
382
|
+
"principalName": "MyPrincipal",
|
|
383
|
+
"externalCredential": "testExtCred",
|
|
384
|
+
"authenticationStatus": "Configured",
|
|
385
|
+
"credentials": {
|
|
386
|
+
"clientId": {
|
|
387
|
+
"value": "client123",
|
|
388
|
+
"encrypted": False,
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
status=200,
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Mock update credential
|
|
396
|
+
responses.add(
|
|
397
|
+
method="PUT",
|
|
398
|
+
url=f"{connect_url}/named-credentials/credential",
|
|
399
|
+
json={},
|
|
400
|
+
status=200,
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
task()
|
|
404
|
+
assert len(responses.calls) == 5
|
|
405
|
+
|
|
406
|
+
@responses.activate
|
|
407
|
+
def test_update_external_credential_create_new_credential(self):
|
|
408
|
+
"""Test creating new credential when it doesn't exist"""
|
|
409
|
+
named_principal = ExternalCredential(
|
|
410
|
+
name="NewPrincipal",
|
|
411
|
+
value="test-value",
|
|
412
|
+
client_id="client123",
|
|
413
|
+
client_secret="secret456",
|
|
414
|
+
)
|
|
415
|
+
task = create_task(
|
|
416
|
+
UpdateExternalCredential,
|
|
417
|
+
{
|
|
418
|
+
"name": "testExtCred",
|
|
419
|
+
"parameters": [{"named_principal": named_principal}],
|
|
420
|
+
},
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
424
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
425
|
+
connect_url = (
|
|
426
|
+
f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}"
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
# Mock query for external credential ID
|
|
430
|
+
responses.add(
|
|
431
|
+
method="GET",
|
|
432
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
433
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
434
|
+
status=200,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
# Mock get external credential object
|
|
438
|
+
responses.add(
|
|
439
|
+
method="GET",
|
|
440
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
441
|
+
json={
|
|
442
|
+
"Metadata": {
|
|
443
|
+
"externalCredentialParameters": [],
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
status=200,
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# Mock update external credential
|
|
450
|
+
responses.add(
|
|
451
|
+
method="PATCH",
|
|
452
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
453
|
+
json={},
|
|
454
|
+
status=200,
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Mock get credential (not found)
|
|
458
|
+
responses.add(
|
|
459
|
+
method="GET",
|
|
460
|
+
url=f"{connect_url}/named-credentials/credential",
|
|
461
|
+
json={
|
|
462
|
+
"principalType": "NamedPrincipal",
|
|
463
|
+
"principalName": "MyPrincipal",
|
|
464
|
+
"externalCredential": "testExtCred",
|
|
465
|
+
"authenticationStatus": "Configured",
|
|
466
|
+
"credentials": {},
|
|
467
|
+
},
|
|
468
|
+
status=200,
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
# Mock create credential
|
|
472
|
+
responses.add(
|
|
473
|
+
method="POST",
|
|
474
|
+
url=f"{connect_url}/named-credentials/credential",
|
|
475
|
+
json={},
|
|
476
|
+
status=201,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
task()
|
|
480
|
+
assert len(responses.calls) == 5
|
|
481
|
+
|
|
482
|
+
@responses.activate
|
|
483
|
+
def test_update_external_credential_not_found(self):
|
|
484
|
+
"""Test update of non-existent external credential"""
|
|
485
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer token")
|
|
486
|
+
task = create_task(
|
|
487
|
+
UpdateExternalCredential,
|
|
488
|
+
{"name": "nonExistentCred", "parameters": [{"auth_header": auth_header}]},
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
492
|
+
|
|
493
|
+
# Mock query returning no results
|
|
494
|
+
responses.add(
|
|
495
|
+
method="GET",
|
|
496
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27nonExistentCred%27+LIMIT+1",
|
|
497
|
+
json={"size": 0, "records": []},
|
|
498
|
+
status=200,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
with pytest.raises(
|
|
502
|
+
SalesforceDXException,
|
|
503
|
+
match="External credential 'nonExistentCred' not found",
|
|
504
|
+
):
|
|
505
|
+
task()
|
|
506
|
+
|
|
507
|
+
@responses.activate
|
|
508
|
+
def test_update_external_credential_with_namespace(self):
|
|
509
|
+
"""Test update of external credential with namespace"""
|
|
510
|
+
task = create_task(
|
|
511
|
+
UpdateExternalCredential,
|
|
512
|
+
{
|
|
513
|
+
"name": "testExtCred",
|
|
514
|
+
"namespace": "myns",
|
|
515
|
+
"parameters": [{"auth_provider": "MyAuthProvider"}],
|
|
516
|
+
},
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
520
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
521
|
+
|
|
522
|
+
# Mock query for external credential ID
|
|
523
|
+
responses.add(
|
|
524
|
+
method="GET",
|
|
525
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+AND+NamespacePrefix%3D%27myns%27+LIMIT+1",
|
|
526
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
527
|
+
status=200,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
# Mock get external credential object
|
|
531
|
+
responses.add(
|
|
532
|
+
method="GET",
|
|
533
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
534
|
+
json={
|
|
535
|
+
"Metadata": {
|
|
536
|
+
"externalCredentialParameters": [
|
|
537
|
+
{
|
|
538
|
+
"parameterType": "AuthProvider",
|
|
539
|
+
"parameterValue": "OldAuthProvider",
|
|
540
|
+
"description": None,
|
|
541
|
+
"parameterName": None,
|
|
542
|
+
"sequenceNumber": None,
|
|
543
|
+
}
|
|
544
|
+
],
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
status=200,
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
# Mock update external credential
|
|
551
|
+
responses.add(
|
|
552
|
+
method="PATCH",
|
|
553
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
554
|
+
json={},
|
|
555
|
+
status=200,
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
task()
|
|
559
|
+
assert len(responses.calls) == 3
|
|
560
|
+
|
|
561
|
+
@responses.activate
|
|
562
|
+
def test_update_external_credential_add_new_parameter(self):
|
|
563
|
+
"""Test adding a new parameter to external credential"""
|
|
564
|
+
jwt_claim = ExtParameter(name="sub", value='{"sub":"user123"}')
|
|
565
|
+
task = create_task(
|
|
566
|
+
UpdateExternalCredential,
|
|
567
|
+
{
|
|
568
|
+
"name": "testExtCred",
|
|
569
|
+
"parameters": [{"jwt_body_claim": jwt_claim}],
|
|
570
|
+
},
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
574
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
575
|
+
|
|
576
|
+
# Mock query for external credential ID
|
|
577
|
+
responses.add(
|
|
578
|
+
method="GET",
|
|
579
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
580
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
581
|
+
status=200,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
# Mock get external credential object with existing parameter
|
|
585
|
+
responses.add(
|
|
586
|
+
method="GET",
|
|
587
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
588
|
+
json={
|
|
589
|
+
"Metadata": {
|
|
590
|
+
"externalCredentialParameters": [
|
|
591
|
+
{
|
|
592
|
+
"parameterType": "AuthHeader",
|
|
593
|
+
"parameterValue": "Bearer token123",
|
|
594
|
+
"description": None,
|
|
595
|
+
"parameterName": None,
|
|
596
|
+
"sequenceNumber": None,
|
|
597
|
+
}
|
|
598
|
+
],
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
status=200,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
# Mock update external credential
|
|
605
|
+
responses.add(
|
|
606
|
+
method="PATCH",
|
|
607
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
608
|
+
json={},
|
|
609
|
+
status=200,
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
task()
|
|
613
|
+
assert len(responses.calls) == 3
|
|
614
|
+
|
|
615
|
+
@responses.activate
|
|
616
|
+
def test_update_external_credential_with_transform_parameters(self):
|
|
617
|
+
"""Test update with transform parameters from environment variables"""
|
|
618
|
+
with mock.patch.dict(os.environ, {"MY_AUTH_TOKEN": "Bearer envtoken789"}):
|
|
619
|
+
auth_header = HttpHeader(name="Authorization", value="MY_AUTH_TOKEN")
|
|
620
|
+
task = create_task(
|
|
621
|
+
UpdateExternalCredential,
|
|
622
|
+
{
|
|
623
|
+
"name": "testExtCred",
|
|
624
|
+
"transform_parameters": [{"auth_header": auth_header}],
|
|
625
|
+
},
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
629
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
630
|
+
|
|
631
|
+
# Mock query for external credential ID
|
|
632
|
+
responses.add(
|
|
633
|
+
method="GET",
|
|
634
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
635
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
636
|
+
status=200,
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
# Mock get external credential object
|
|
640
|
+
responses.add(
|
|
641
|
+
method="GET",
|
|
642
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
643
|
+
json={
|
|
644
|
+
"Metadata": {
|
|
645
|
+
"externalCredentialParameters": [
|
|
646
|
+
{
|
|
647
|
+
"parameterType": "AuthHeader",
|
|
648
|
+
"parameterValue": "Bearer oldtoken",
|
|
649
|
+
"description": None,
|
|
650
|
+
"parameterName": None,
|
|
651
|
+
"sequenceNumber": None,
|
|
652
|
+
}
|
|
653
|
+
],
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
status=200,
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
# Mock update external credential
|
|
660
|
+
responses.add(
|
|
661
|
+
method="PATCH",
|
|
662
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
663
|
+
json={},
|
|
664
|
+
status=200,
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
task()
|
|
668
|
+
assert len(responses.calls) == 3
|
|
669
|
+
|
|
670
|
+
@responses.activate
|
|
671
|
+
def test_update_external_credential_retrieve_error(self):
|
|
672
|
+
"""Test error handling when retrieving external credential fails"""
|
|
673
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer token")
|
|
674
|
+
task = create_task(
|
|
675
|
+
UpdateExternalCredential,
|
|
676
|
+
{"name": "testExtCred", "parameters": [{"auth_header": auth_header}]},
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
680
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
681
|
+
|
|
682
|
+
# Mock query for external credential ID
|
|
683
|
+
responses.add(
|
|
684
|
+
method="GET",
|
|
685
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
686
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
687
|
+
status=200,
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
# Mock get external credential object failure
|
|
691
|
+
responses.add(
|
|
692
|
+
method="GET",
|
|
693
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
694
|
+
json={"error": "Not Found"},
|
|
695
|
+
status=404,
|
|
696
|
+
)
|
|
697
|
+
|
|
698
|
+
with pytest.raises(
|
|
699
|
+
SalesforceDXException,
|
|
700
|
+
match="Failed to retrieve external credential object for 'testExtCred'",
|
|
701
|
+
):
|
|
702
|
+
task()
|
|
703
|
+
|
|
704
|
+
@responses.activate
|
|
705
|
+
def test_update_external_credential_update_error(self):
|
|
706
|
+
"""Test error handling when updating external credential fails"""
|
|
707
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer token")
|
|
708
|
+
task = create_task(
|
|
709
|
+
UpdateExternalCredential,
|
|
710
|
+
{"name": "testExtCred", "parameters": [{"auth_header": auth_header}]},
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
714
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
715
|
+
|
|
716
|
+
# Mock query for external credential ID
|
|
717
|
+
responses.add(
|
|
718
|
+
method="GET",
|
|
719
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
720
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
721
|
+
status=200,
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
# Mock get external credential object
|
|
725
|
+
responses.add(
|
|
726
|
+
method="GET",
|
|
727
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
728
|
+
json={
|
|
729
|
+
"Metadata": {
|
|
730
|
+
"externalCredentialParameters": [
|
|
731
|
+
{
|
|
732
|
+
"parameterType": "AuthHeader",
|
|
733
|
+
"parameterValue": "Bearer oldtoken",
|
|
734
|
+
"description": None,
|
|
735
|
+
"parameterName": None,
|
|
736
|
+
"sequenceNumber": None,
|
|
737
|
+
}
|
|
738
|
+
],
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
status=200,
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
# Mock update external credential failure
|
|
745
|
+
responses.add(
|
|
746
|
+
method="PATCH",
|
|
747
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
748
|
+
json={"error": "Update failed"},
|
|
749
|
+
status=400,
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
with pytest.raises(
|
|
753
|
+
SalesforceDXException,
|
|
754
|
+
match="Failed to update external credential object",
|
|
755
|
+
):
|
|
756
|
+
task()
|
|
757
|
+
|
|
758
|
+
@responses.activate
|
|
759
|
+
def test_update_external_credential_no_existing_parameters(self):
|
|
760
|
+
"""Test update when external credential has no existing parameters"""
|
|
761
|
+
task = create_task(
|
|
762
|
+
UpdateExternalCredential,
|
|
763
|
+
{
|
|
764
|
+
"name": "testExtCred",
|
|
765
|
+
"parameters": [{"auth_provider": "NewAuthProvider"}],
|
|
766
|
+
},
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
770
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
771
|
+
|
|
772
|
+
# Mock query for external credential ID
|
|
773
|
+
responses.add(
|
|
774
|
+
method="GET",
|
|
775
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
776
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
777
|
+
status=200,
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
# Mock get external credential object with no parameters
|
|
781
|
+
responses.add(
|
|
782
|
+
method="GET",
|
|
783
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
784
|
+
json={"Metadata": {"externalCredentialParameters": []}},
|
|
785
|
+
status=200,
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
# Mock update external credential
|
|
789
|
+
responses.add(
|
|
790
|
+
method="PATCH",
|
|
791
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
792
|
+
json={},
|
|
793
|
+
status=200,
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
task()
|
|
797
|
+
assert len(responses.calls) == 3
|
|
798
|
+
|
|
799
|
+
@responses.activate
|
|
800
|
+
def test_update_external_credential_with_multiple_parameters(self):
|
|
801
|
+
"""Test update with multiple parameters"""
|
|
802
|
+
auth_header = HttpHeader(name="Authorization", value="Bearer token123")
|
|
803
|
+
jwt_claim = ExtParameter(name="sub", value='{"sub":"user"}')
|
|
804
|
+
task = create_task(
|
|
805
|
+
UpdateExternalCredential,
|
|
806
|
+
{
|
|
807
|
+
"name": "testExtCred",
|
|
808
|
+
"parameters": [
|
|
809
|
+
{"auth_header": auth_header},
|
|
810
|
+
{"auth_provider": "MyAuthProvider"},
|
|
811
|
+
{"jwt_body_claim": jwt_claim},
|
|
812
|
+
],
|
|
813
|
+
},
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
817
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
818
|
+
|
|
819
|
+
# Mock query for external credential ID
|
|
820
|
+
responses.add(
|
|
821
|
+
method="GET",
|
|
822
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
823
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
824
|
+
status=200,
|
|
825
|
+
)
|
|
826
|
+
|
|
827
|
+
# Mock get external credential object
|
|
828
|
+
responses.add(
|
|
829
|
+
method="GET",
|
|
830
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
831
|
+
json={
|
|
832
|
+
"Metadata": {
|
|
833
|
+
"externalCredentialParameters": [
|
|
834
|
+
{
|
|
835
|
+
"parameterType": "AuthHeader",
|
|
836
|
+
"parameterValue": "Bearer oldtoken",
|
|
837
|
+
"description": None,
|
|
838
|
+
"parameterName": None,
|
|
839
|
+
"sequenceNumber": None,
|
|
840
|
+
}
|
|
841
|
+
],
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
status=200,
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
# Mock update external credential
|
|
848
|
+
responses.add(
|
|
849
|
+
method="PATCH",
|
|
850
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
851
|
+
json={},
|
|
852
|
+
status=200,
|
|
853
|
+
)
|
|
854
|
+
|
|
855
|
+
task()
|
|
856
|
+
assert len(responses.calls) == 3
|
|
857
|
+
|
|
858
|
+
@responses.activate
|
|
859
|
+
def test_update_external_credential_with_sequence_number(self):
|
|
860
|
+
"""Test update with sequence number"""
|
|
861
|
+
auth_header = HttpHeader(
|
|
862
|
+
name="MyHeader", value="Bearer token123", sequence_number=5
|
|
863
|
+
)
|
|
864
|
+
task = create_task(
|
|
865
|
+
UpdateExternalCredential,
|
|
866
|
+
{
|
|
867
|
+
"name": "testExtCred",
|
|
868
|
+
"parameters": [{"auth_header": auth_header}],
|
|
869
|
+
},
|
|
870
|
+
)
|
|
871
|
+
|
|
872
|
+
ext_cred_id = "0XE1234567890ABC"
|
|
873
|
+
tooling_url = f"https://test.salesforce.com/services/data/v{CURRENT_SF_API_VERSION}/tooling"
|
|
874
|
+
|
|
875
|
+
# Mock query for external credential ID
|
|
876
|
+
responses.add(
|
|
877
|
+
method="GET",
|
|
878
|
+
url=f"{tooling_url}/query/?q=SELECT+Id+FROM+ExternalCredential+WHERE+DeveloperName%3D%27testExtCred%27+LIMIT+1",
|
|
879
|
+
json={"size": 1, "records": [{"Id": ext_cred_id}]},
|
|
880
|
+
status=200,
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
# Mock get external credential object
|
|
884
|
+
responses.add(
|
|
885
|
+
method="GET",
|
|
886
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
887
|
+
json={
|
|
888
|
+
"Metadata": {
|
|
889
|
+
"externalCredentialParameters": [
|
|
890
|
+
{
|
|
891
|
+
"parameterType": "AuthHeader",
|
|
892
|
+
"parameterValue": "Bearer oldtoken",
|
|
893
|
+
"description": None,
|
|
894
|
+
"parameterName": None,
|
|
895
|
+
"sequenceNumber": None,
|
|
896
|
+
}
|
|
897
|
+
],
|
|
898
|
+
}
|
|
899
|
+
},
|
|
900
|
+
status=200,
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
# Mock update external credential
|
|
904
|
+
responses.add(
|
|
905
|
+
method="PATCH",
|
|
906
|
+
url=f"{tooling_url}/sobjects/ExternalCredential/{ext_cred_id}",
|
|
907
|
+
json={},
|
|
908
|
+
status=200,
|
|
909
|
+
)
|
|
910
|
+
|
|
911
|
+
task()
|
|
912
|
+
assert len(responses.calls) == 3
|