cumulusci-plus 5.0.21__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.
Files changed (121) hide show
  1. cumulusci/__about__.py +1 -1
  2. cumulusci/cli/logger.py +2 -2
  3. cumulusci/cli/service.py +20 -0
  4. cumulusci/cli/task.py +17 -0
  5. cumulusci/cli/tests/test_error.py +3 -1
  6. cumulusci/cli/tests/test_flow.py +279 -2
  7. cumulusci/cli/tests/test_service.py +15 -12
  8. cumulusci/cli/tests/test_task.py +88 -2
  9. cumulusci/cli/tests/utils.py +1 -4
  10. cumulusci/core/config/base_task_flow_config.py +26 -1
  11. cumulusci/core/config/project_config.py +2 -20
  12. cumulusci/core/config/tests/test_config_expensive.py +9 -3
  13. cumulusci/core/config/universal_config.py +3 -4
  14. cumulusci/core/dependencies/base.py +1 -1
  15. cumulusci/core/dependencies/dependencies.py +1 -1
  16. cumulusci/core/dependencies/github.py +1 -2
  17. cumulusci/core/dependencies/resolvers.py +1 -1
  18. cumulusci/core/dependencies/tests/test_dependencies.py +1 -1
  19. cumulusci/core/dependencies/tests/test_resolvers.py +1 -1
  20. cumulusci/core/flowrunner.py +90 -6
  21. cumulusci/core/github.py +1 -1
  22. cumulusci/core/sfdx.py +3 -1
  23. cumulusci/core/source_transforms/tests/test_transforms.py +1 -1
  24. cumulusci/core/source_transforms/transforms.py +1 -1
  25. cumulusci/core/tasks.py +13 -2
  26. cumulusci/core/tests/test_flowrunner.py +100 -0
  27. cumulusci/core/tests/test_tasks.py +65 -0
  28. cumulusci/core/utils.py +3 -1
  29. cumulusci/core/versions.py +1 -1
  30. cumulusci/cumulusci.yml +55 -0
  31. cumulusci/oauth/client.py +1 -1
  32. cumulusci/plugins/plugin_base.py +5 -3
  33. cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +1 -1
  34. cumulusci/salesforce_api/rest_deploy.py +1 -1
  35. cumulusci/schema/cumulusci.jsonschema.json +64 -0
  36. cumulusci/tasks/apex/anon.py +1 -1
  37. cumulusci/tasks/apex/testrunner.py +416 -142
  38. cumulusci/tasks/apex/tests/test_apex_tasks.py +917 -1
  39. cumulusci/tasks/bulkdata/extract.py +0 -1
  40. cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +1 -1
  41. cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +1 -1
  42. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +1 -1
  43. cumulusci/tasks/bulkdata/generate_and_load_data.py +136 -12
  44. cumulusci/tasks/bulkdata/mapping_parser.py +139 -44
  45. cumulusci/tasks/bulkdata/select_utils.py +1 -1
  46. cumulusci/tasks/bulkdata/snowfakery.py +100 -25
  47. cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +159 -0
  48. cumulusci/tasks/bulkdata/tests/test_load.py +0 -2
  49. cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +763 -1
  50. cumulusci/tasks/bulkdata/tests/test_select_utils.py +26 -0
  51. cumulusci/tasks/bulkdata/tests/test_snowfakery.py +133 -0
  52. cumulusci/tasks/create_package_version.py +190 -16
  53. cumulusci/tasks/datadictionary.py +1 -1
  54. cumulusci/tasks/metadata_etl/base.py +7 -3
  55. cumulusci/tasks/metadata_etl/layouts.py +1 -1
  56. cumulusci/tasks/metadata_etl/permissions.py +1 -1
  57. cumulusci/tasks/metadata_etl/remote_site_settings.py +2 -2
  58. cumulusci/tasks/push/README.md +15 -17
  59. cumulusci/tasks/release_notes/README.md +13 -13
  60. cumulusci/tasks/release_notes/generator.py +13 -8
  61. cumulusci/tasks/robotframework/tests/test_robotframework.py +6 -1
  62. cumulusci/tasks/salesforce/Deploy.py +53 -2
  63. cumulusci/tasks/salesforce/SfPackageCommands.py +363 -0
  64. cumulusci/tasks/salesforce/__init__.py +1 -0
  65. cumulusci/tasks/salesforce/assign_ps_psg.py +448 -0
  66. cumulusci/tasks/salesforce/composite.py +1 -1
  67. cumulusci/tasks/salesforce/custom_settings_wait.py +1 -1
  68. cumulusci/tasks/salesforce/enable_prediction.py +5 -1
  69. cumulusci/tasks/salesforce/getPackageVersion.py +89 -0
  70. cumulusci/tasks/salesforce/sourcetracking.py +1 -1
  71. cumulusci/tasks/salesforce/tests/test_Deploy.py +316 -1
  72. cumulusci/tasks/salesforce/tests/test_SfPackageCommands.py +554 -0
  73. cumulusci/tasks/salesforce/tests/test_assign_ps_psg.py +1055 -0
  74. cumulusci/tasks/salesforce/tests/test_getPackageVersion.py +651 -0
  75. cumulusci/tasks/salesforce/tests/test_update_dependencies.py +1 -1
  76. cumulusci/tasks/salesforce/tests/test_update_external_credential.py +912 -0
  77. cumulusci/tasks/salesforce/tests/test_update_named_credential.py +1042 -0
  78. cumulusci/tasks/salesforce/update_dependencies.py +2 -2
  79. cumulusci/tasks/salesforce/update_external_credential.py +562 -0
  80. cumulusci/tasks/salesforce/update_named_credential.py +441 -0
  81. cumulusci/tasks/salesforce/update_profile.py +17 -13
  82. cumulusci/tasks/salesforce/users/permsets.py +62 -5
  83. cumulusci/tasks/salesforce/users/tests/test_permsets.py +237 -11
  84. cumulusci/tasks/sfdmu/__init__.py +0 -0
  85. cumulusci/tasks/sfdmu/sfdmu.py +363 -0
  86. cumulusci/tasks/sfdmu/tests/__init__.py +1 -0
  87. cumulusci/tasks/sfdmu/tests/test_runner.py +212 -0
  88. cumulusci/tasks/sfdmu/tests/test_sfdmu.py +1012 -0
  89. cumulusci/tasks/tests/test_create_package_version.py +716 -1
  90. cumulusci/tasks/tests/test_util.py +42 -0
  91. cumulusci/tasks/util.py +37 -1
  92. cumulusci/tasks/utility/copyContents.py +402 -0
  93. cumulusci/tasks/utility/credentialManager.py +256 -0
  94. cumulusci/tasks/utility/directoryRecreator.py +30 -0
  95. cumulusci/tasks/utility/env_management.py +1 -1
  96. cumulusci/tasks/utility/secretsToEnv.py +135 -0
  97. cumulusci/tasks/utility/tests/test_copyContents.py +1719 -0
  98. cumulusci/tasks/utility/tests/test_credentialManager.py +564 -0
  99. cumulusci/tasks/utility/tests/test_directoryRecreator.py +439 -0
  100. cumulusci/tasks/utility/tests/test_secretsToEnv.py +1091 -0
  101. cumulusci/tests/test_integration_infrastructure.py +3 -1
  102. cumulusci/tests/test_utils.py +70 -6
  103. cumulusci/utils/__init__.py +54 -9
  104. cumulusci/utils/classutils.py +5 -2
  105. cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +31 -30
  106. cumulusci/utils/options.py +23 -1
  107. cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +1 -1
  108. cumulusci/utils/yaml/cumulusci_yml.py +7 -3
  109. cumulusci/utils/yaml/model_parser.py +2 -2
  110. cumulusci/utils/yaml/tests/test_cumulusci_yml.py +1 -1
  111. cumulusci/utils/yaml/tests/test_model_parser.py +3 -3
  112. cumulusci/vcs/base.py +23 -15
  113. cumulusci/vcs/bootstrap.py +5 -4
  114. cumulusci/vcs/utils/list_modified_files.py +189 -0
  115. cumulusci/vcs/utils/tests/test_list_modified_files.py +588 -0
  116. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/METADATA +12 -10
  117. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/RECORD +121 -96
  118. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/WHEEL +0 -0
  119. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/entry_points.txt +0 -0
  120. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/licenses/AUTHORS.rst +0 -0
  121. {cumulusci_plus-5.0.21.dist-info → cumulusci_plus-5.0.35.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,554 @@
1
+ import json
2
+ from unittest import mock
3
+
4
+ import pytest
5
+ import sarge
6
+
7
+ from cumulusci.core.exceptions import SalesforceDXException
8
+ from cumulusci.tasks.salesforce.SfPackageCommands import (
9
+ PackageCreateTask,
10
+ PackageDisplayTask,
11
+ PackageListTask,
12
+ PackageVersionCreateTask,
13
+ PackageVersionDeleteTask,
14
+ PackageVersionDisplayTask,
15
+ PackageVersionListTask,
16
+ PackageVersionReportTask,
17
+ PackageVersionUpdateTask,
18
+ SfPackageCommands,
19
+ )
20
+
21
+ from . import create_task
22
+
23
+
24
+ def create_mock_sarge_command(stdout="", stderr="", returncode=0):
25
+ """Create a mock sarge.Command that satisfies type checking"""
26
+ mock_command = mock.Mock(spec=sarge.Command)
27
+ mock_command.returncode = returncode
28
+
29
+ # Mock stdout_text
30
+ stdout_lines = stdout.split("\n") if stdout else []
31
+ mock_stdout_text = mock.Mock()
32
+ mock_stdout_text.__iter__ = mock.Mock(return_value=iter(stdout_lines))
33
+ mock_stdout_text.read = mock.Mock(return_value=stdout)
34
+ mock_command.stdout_text = mock_stdout_text
35
+
36
+ # Mock stderr_text
37
+ stderr_lines = stderr.split("\n") if stderr else []
38
+ mock_stderr_text = mock.Mock()
39
+ mock_stderr_text.__iter__ = mock.Mock(return_value=iter(stderr_lines))
40
+ mock_stderr_text.read = mock.Mock(return_value=stderr)
41
+ mock_command.stderr_text = mock_stderr_text
42
+
43
+ return mock_command
44
+
45
+
46
+ def setup_devhub_mock(mock_devhub):
47
+ """Helper function to set up devhub mock"""
48
+ mock_devhub.return_value.username = "test-devhub@example.com"
49
+
50
+
51
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
52
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
53
+ class TestSfPackageCommands:
54
+ def test_init_options_basic(self, mock_sfdx, mock_devhub):
55
+ mock_sfdx.return_value = create_mock_sarge_command()
56
+ setup_devhub_mock(mock_devhub)
57
+ task = create_task(SfPackageCommands, {})
58
+ task()
59
+ assert task.package_command == "package "
60
+ assert len(task.args) == 2
61
+ assert "--target-dev-hub" in task.args
62
+ assert "test-devhub@example.com" in task.args
63
+
64
+ def test_init_options_all_flags(self, mock_sfdx, mock_devhub):
65
+ json_response = {"status": 0, "result": {}}
66
+ mock_sfdx.return_value = create_mock_sarge_command(
67
+ stdout=json.dumps(json_response)
68
+ )
69
+ setup_devhub_mock(mock_devhub)
70
+ task = create_task(
71
+ SfPackageCommands,
72
+ {
73
+ "json_output": True,
74
+ "api_version": "50.0",
75
+ "flags_dir": "/tmp/flags",
76
+ },
77
+ )
78
+ task()
79
+ expected_args = [
80
+ "--flags-dir",
81
+ "/tmp/flags",
82
+ "--json",
83
+ "--api-version",
84
+ "50.0",
85
+ "--target-dev-hub",
86
+ "test-devhub@example.com",
87
+ ]
88
+ assert all(arg in task.args for arg in expected_args)
89
+
90
+ def test_load_json_output_success(self, mock_sfdx, mock_devhub):
91
+ json_response = {"status": 0, "result": {"packageVersionId": "04t000000000001"}}
92
+ stdout = json.dumps(json_response)
93
+ mock_command = create_mock_sarge_command(stdout=stdout)
94
+ mock_sfdx.return_value = mock_command
95
+ setup_devhub_mock(mock_devhub)
96
+
97
+ task = create_task(SfPackageCommands, {"json_output": True})
98
+ task()
99
+
100
+ assert task.return_values == json_response
101
+
102
+ def test_load_json_output_decode_error(self, mock_sfdx, mock_devhub):
103
+ mock_command = create_mock_sarge_command(stdout="invalid json")
104
+ mock_sfdx.return_value = mock_command
105
+ setup_devhub_mock(mock_devhub)
106
+
107
+ task = create_task(SfPackageCommands, {"json_output": True})
108
+
109
+ with pytest.raises(SalesforceDXException, match="Failed to parse the output"):
110
+ task()
111
+
112
+ def test_logging_stdout_and_stderr(self, mock_sfdx, mock_devhub):
113
+ mock_command = create_mock_sarge_command(
114
+ stdout="Success: Package version updated\nVersion ID: 04t000000000001",
115
+ stderr="Warning: Some non-critical issue",
116
+ )
117
+ mock_sfdx.return_value = mock_command
118
+ setup_devhub_mock(mock_devhub)
119
+
120
+ task = create_task(SfPackageCommands, {})
121
+ with mock.patch.object(task, "logger") as mock_logger:
122
+ task()
123
+
124
+ # Check that stdout lines were logged as info
125
+ mock_logger.info.assert_any_call("Success: Package version updated")
126
+ mock_logger.info.assert_any_call("Version ID: 04t000000000001")
127
+
128
+ # Check that stderr lines were logged as error
129
+ mock_logger.error.assert_called_with("Warning: Some non-critical issue")
130
+
131
+
132
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
133
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
134
+ class TestPackageVersionUpdateTask:
135
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
136
+ mock_sfdx.return_value = create_mock_sarge_command()
137
+ setup_devhub_mock(mock_devhub)
138
+ task = create_task(PackageVersionUpdateTask, {"package_id": "0Ho000000000001"})
139
+ task()
140
+ assert task.package_command == "package version update"
141
+
142
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
143
+ json_response = {"status": 0, "result": {"packageVersionId": "04t000000000001"}}
144
+ mock_sfdx.return_value = create_mock_sarge_command(
145
+ stdout=json.dumps(json_response)
146
+ )
147
+ task = create_task(
148
+ PackageVersionUpdateTask,
149
+ {
150
+ "package_id": "0Ho000000000001",
151
+ "version_name": "Updated Version",
152
+ "version_description": "Updated description",
153
+ "branch": "main",
154
+ "tag": "v1.1.0",
155
+ "installation_key": "secret-key",
156
+ "api_version": "50.0",
157
+ "flags_dir": "/tmp/flags",
158
+ "json_output": True,
159
+ },
160
+ )
161
+ task()
162
+
163
+ call_args = mock_sfdx.call_args[1]["args"]
164
+ assert mock_sfdx.call_args[1]["log_note"] == "Running package command"
165
+ assert "--package" in call_args
166
+ assert "0Ho000000000001" in call_args
167
+ assert "--version-name" in call_args
168
+ assert "Updated Version" in call_args
169
+ assert "--version-description" in call_args
170
+ assert "Updated description" in call_args
171
+ assert "--branch" in call_args
172
+ assert "main" in call_args
173
+ assert "--tag" in call_args
174
+ assert "v1.1.0" in call_args
175
+ assert "--installation-key" in call_args
176
+ assert "secret-key" in call_args
177
+ assert "--api-version" in call_args
178
+ assert "50.0" in call_args
179
+ assert "--flags-dir" in call_args
180
+ assert "/tmp/flags" in call_args
181
+ assert "--json" in call_args
182
+
183
+ def test_minimal_options(self, mock_sfdx, mock_devhub):
184
+ mock_sfdx.return_value = create_mock_sarge_command()
185
+ task = create_task(PackageVersionUpdateTask, {"package_id": "0Ho000000000001"})
186
+ task()
187
+
188
+ call_args = mock_sfdx.call_args[1]["args"]
189
+ assert "--package" in call_args
190
+ assert "0Ho000000000001" in call_args
191
+
192
+ def test_json_output_logging(self, mock_sfdx, mock_devhub):
193
+ json_response = {"status": 0, "result": {"packageVersionId": "04t000000000001"}}
194
+ stdout = json.dumps(json_response)
195
+ mock_sfdx.return_value = create_mock_sarge_command(stdout=stdout)
196
+
197
+ task = create_task(
198
+ PackageVersionUpdateTask,
199
+ {"package_id": "0Ho000000000001", "json_output": True},
200
+ )
201
+
202
+ with mock.patch.object(task, "logger") as mock_logger:
203
+ task()
204
+ mock_logger.info.assert_called_with(json_response)
205
+
206
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
207
+ from cumulusci.core.exceptions import TaskOptionsError
208
+
209
+ with pytest.raises(TaskOptionsError, match="field required"):
210
+ create_task(PackageVersionUpdateTask, {})
211
+
212
+
213
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
214
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
215
+ class TestPackageVersionCreateTask:
216
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
217
+ mock_sfdx.return_value = create_mock_sarge_command()
218
+ task = create_task(PackageVersionCreateTask, {"package_id": "0Ho000000000001"})
219
+ task()
220
+ assert task.package_command == "package version create"
221
+
222
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
223
+ json_response = {"status": 0, "result": {"packageVersionId": "04t000000000001"}}
224
+ mock_sfdx.return_value = create_mock_sarge_command(
225
+ stdout=json.dumps(json_response)
226
+ )
227
+ task = create_task(
228
+ PackageVersionCreateTask,
229
+ {
230
+ "package_id": "0Ho000000000001",
231
+ "version_name": "New Version",
232
+ "version_description": "New description",
233
+ "branch": "main",
234
+ "tag": "v1.0.0",
235
+ "installation_key": "secret-key",
236
+ "wait": 10,
237
+ "code_coverage": True,
238
+ "skip_validation": True,
239
+ "json_output": True,
240
+ },
241
+ )
242
+ task()
243
+
244
+ call_args = mock_sfdx.call_args[1]["args"]
245
+ assert "--package" in call_args
246
+ assert "0Ho000000000001" in call_args
247
+ assert "--version-name" in call_args
248
+ assert "New Version" in call_args
249
+ assert "--version-description" in call_args
250
+ assert "New description" in call_args
251
+ assert "--branch" in call_args
252
+ assert "main" in call_args
253
+ assert "--tag" in call_args
254
+ assert "v1.0.0" in call_args
255
+ assert "--installation-key" in call_args
256
+ assert "secret-key" in call_args
257
+ assert "--wait" in call_args
258
+ assert "10" in call_args
259
+ assert "--code-coverage" in call_args
260
+ assert True in call_args # Boolean flags include the value
261
+ assert "--skip-validation" in call_args
262
+ assert "--json" in call_args
263
+
264
+ def test_minimal_options(self, mock_sfdx, mock_devhub):
265
+ mock_sfdx.return_value = create_mock_sarge_command()
266
+ task = create_task(PackageVersionCreateTask, {"package_id": "0Ho000000000001"})
267
+ task()
268
+
269
+ call_args = mock_sfdx.call_args[1]["args"]
270
+ assert "--package" in call_args
271
+ assert "0Ho000000000001" in call_args
272
+
273
+
274
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
275
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
276
+ class TestPackageVersionListTask:
277
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
278
+ mock_sfdx.return_value = create_mock_sarge_command()
279
+ task = create_task(PackageVersionListTask, {})
280
+ task()
281
+ assert task.package_command == "package version list"
282
+
283
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
284
+ json_response = {"status": 0, "result": {"packageVersions": []}}
285
+ mock_sfdx.return_value = create_mock_sarge_command(
286
+ stdout=json.dumps(json_response)
287
+ )
288
+ task = create_task(
289
+ PackageVersionListTask,
290
+ {
291
+ "package_id": "0Ho000000000001",
292
+ "status": "Success",
293
+ "modified": True,
294
+ "concise": True,
295
+ "json_output": True,
296
+ },
297
+ )
298
+ task()
299
+
300
+ call_args = mock_sfdx.call_args[1]["args"]
301
+ assert "--package" in call_args
302
+ assert "0Ho000000000001" in call_args
303
+ assert "--status" in call_args
304
+ assert "Success" in call_args
305
+ assert "--modified" in call_args
306
+ assert True in call_args # Boolean flags include the value
307
+ assert "--concise" in call_args
308
+ assert "--json" in call_args
309
+
310
+ def test_minimal_options(self, mock_sfdx, mock_devhub):
311
+ mock_sfdx.return_value = create_mock_sarge_command()
312
+ task = create_task(PackageVersionListTask, {})
313
+ task()
314
+
315
+ call_args = mock_sfdx.call_args[1]["args"]
316
+ # Should only have base options, no package-specific args
317
+ assert "--package" not in call_args
318
+
319
+
320
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
321
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
322
+ class TestPackageVersionDisplayTask:
323
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
324
+ mock_sfdx.return_value = create_mock_sarge_command()
325
+ task = create_task(
326
+ PackageVersionDisplayTask, {"package_version_id": "04t000000000001"}
327
+ )
328
+ task()
329
+ assert task.package_command == "package version display"
330
+
331
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
332
+ json_response = {"status": 0, "result": {"packageVersion": {}}}
333
+ mock_sfdx.return_value = create_mock_sarge_command(
334
+ stdout=json.dumps(json_response)
335
+ )
336
+ task = create_task(
337
+ PackageVersionDisplayTask,
338
+ {
339
+ "package_version_id": "04t000000000001",
340
+ "verbose": True,
341
+ "json_output": True,
342
+ },
343
+ )
344
+ task()
345
+
346
+ call_args = mock_sfdx.call_args[1]["args"]
347
+ assert "--package-version-id" in call_args
348
+ assert "04t000000000001" in call_args
349
+ assert "--verbose" in call_args
350
+ assert True in call_args # Boolean flags include the value
351
+ assert "--json" in call_args
352
+
353
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
354
+ from cumulusci.core.exceptions import TaskOptionsError
355
+
356
+ with pytest.raises(TaskOptionsError, match="field required"):
357
+ create_task(PackageVersionDisplayTask, {})
358
+
359
+
360
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
361
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
362
+ class TestPackageVersionDeleteTask:
363
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
364
+ mock_sfdx.return_value = create_mock_sarge_command()
365
+ task = create_task(
366
+ PackageVersionDeleteTask, {"package_version_id": "04t000000000001"}
367
+ )
368
+ task()
369
+ assert task.package_command == "package version delete"
370
+
371
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
372
+ json_response = {"status": 0, "result": {}}
373
+ mock_sfdx.return_value = create_mock_sarge_command(
374
+ stdout=json.dumps(json_response)
375
+ )
376
+ task = create_task(
377
+ PackageVersionDeleteTask,
378
+ {
379
+ "package_version_id": "04t000000000001",
380
+ "no_prompt_flag": True,
381
+ "json_output": True,
382
+ },
383
+ )
384
+ task()
385
+
386
+ call_args = mock_sfdx.call_args[1]["args"]
387
+ assert "--package-version-id" in call_args
388
+ assert "04t000000000001" in call_args
389
+ assert "--no-prompt" in call_args
390
+ assert True in call_args # Boolean flags include the value
391
+ assert "--json" in call_args
392
+
393
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
394
+ from cumulusci.core.exceptions import TaskOptionsError
395
+
396
+ with pytest.raises(TaskOptionsError, match="field required"):
397
+ create_task(PackageVersionDeleteTask, {})
398
+
399
+
400
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
401
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
402
+ class TestPackageVersionReportTask:
403
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
404
+ mock_sfdx.return_value = create_mock_sarge_command()
405
+ task = create_task(
406
+ PackageVersionReportTask, {"package_version_id": "04t000000000001"}
407
+ )
408
+ task()
409
+ assert task.package_command == "package version report"
410
+
411
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
412
+ json_response = {
413
+ "status": 0,
414
+ "result": {"reportUrl": "https://example.com/report"},
415
+ }
416
+ mock_sfdx.return_value = create_mock_sarge_command(
417
+ stdout=json.dumps(json_response)
418
+ )
419
+ task = create_task(
420
+ PackageVersionReportTask,
421
+ {
422
+ "package_version_id": "04t000000000001",
423
+ "code_coverage": True,
424
+ "output_dir": "/tmp/reports",
425
+ "json_output": True,
426
+ },
427
+ )
428
+ task()
429
+
430
+ call_args = mock_sfdx.call_args[1]["args"]
431
+ assert "--package-version-id" in call_args
432
+ assert "04t000000000001" in call_args
433
+ assert "--code-coverage" in call_args
434
+ assert True in call_args # Boolean flags include the value
435
+ assert "--output-dir" in call_args
436
+ assert "/tmp/reports" in call_args
437
+ assert "--json" in call_args
438
+
439
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
440
+ from cumulusci.core.exceptions import TaskOptionsError
441
+
442
+ with pytest.raises(TaskOptionsError, match="field required"):
443
+ create_task(PackageVersionReportTask, {})
444
+
445
+
446
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
447
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
448
+ class TestPackageCreateTask:
449
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
450
+ mock_sfdx.return_value = create_mock_sarge_command()
451
+ task = create_task(PackageCreateTask, {"name": "Test Package"})
452
+ task()
453
+ assert task.package_command == "package create"
454
+
455
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
456
+ json_response = {"status": 0, "result": {"packageId": "0Ho000000000001"}}
457
+ mock_sfdx.return_value = create_mock_sarge_command(
458
+ stdout=json.dumps(json_response)
459
+ )
460
+ task = create_task(
461
+ PackageCreateTask,
462
+ {
463
+ "name": "Test Package",
464
+ "description": "Test package description",
465
+ "package_type": "Managed",
466
+ "path": "/tmp/package",
467
+ "json_output": True,
468
+ },
469
+ )
470
+ task()
471
+
472
+ call_args = mock_sfdx.call_args[1]["args"]
473
+ assert "--name" in call_args
474
+ assert "Test Package" in call_args
475
+ assert "--description" in call_args
476
+ assert "Test package description" in call_args
477
+ assert "--package-type" in call_args
478
+ assert "Managed" in call_args
479
+ assert "--path" in call_args
480
+ assert "/tmp/package" in call_args
481
+ assert "--json" in call_args
482
+
483
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
484
+ from cumulusci.core.exceptions import TaskOptionsError
485
+
486
+ with pytest.raises(TaskOptionsError, match="field required"):
487
+ create_task(PackageCreateTask, {})
488
+
489
+
490
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
491
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
492
+ class TestPackageListTask:
493
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
494
+ mock_sfdx.return_value = create_mock_sarge_command()
495
+ task = create_task(PackageListTask, {})
496
+ task()
497
+ assert task.package_command == "package list"
498
+
499
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
500
+ json_response = {"status": 0, "result": {"packages": []}}
501
+ mock_sfdx.return_value = create_mock_sarge_command(
502
+ stdout=json.dumps(json_response)
503
+ )
504
+ task = create_task(
505
+ PackageListTask,
506
+ {
507
+ "concise": True,
508
+ "json_output": True,
509
+ },
510
+ )
511
+ task()
512
+
513
+ call_args = mock_sfdx.call_args[1]["args"]
514
+ assert "--concise" in call_args
515
+ assert True in call_args # Boolean flags include the value
516
+ assert "--json" in call_args
517
+
518
+
519
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.get_devhub_config")
520
+ @mock.patch("cumulusci.tasks.salesforce.SfPackageCommands.sfdx")
521
+ class TestPackageDisplayTask:
522
+ def test_init_task_sets_command(self, mock_sfdx, mock_devhub):
523
+ mock_sfdx.return_value = create_mock_sarge_command()
524
+ task = create_task(PackageDisplayTask, {"package_id": "0Ho000000000001"})
525
+ task()
526
+ assert task.package_command == "package display"
527
+
528
+ def test_init_options_all_parameters(self, mock_sfdx, mock_devhub):
529
+ json_response = {"status": 0, "result": {"package": {}}}
530
+ mock_sfdx.return_value = create_mock_sarge_command(
531
+ stdout=json.dumps(json_response)
532
+ )
533
+ task = create_task(
534
+ PackageDisplayTask,
535
+ {
536
+ "package_id": "0Ho000000000001",
537
+ "verbose": True,
538
+ "json_output": True,
539
+ },
540
+ )
541
+ task()
542
+
543
+ call_args = mock_sfdx.call_args[1]["args"]
544
+ assert "--package-id" in call_args
545
+ assert "0Ho000000000001" in call_args
546
+ assert "--verbose" in call_args
547
+ assert True in call_args # Boolean flags include the value
548
+ assert "--json" in call_args
549
+
550
+ def test_missing_required_options(self, mock_sfdx, mock_devhub):
551
+ from cumulusci.core.exceptions import TaskOptionsError
552
+
553
+ with pytest.raises(TaskOptionsError, match="field required"):
554
+ create_task(PackageDisplayTask, {})