cumulusci-plus 5.0.0__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.

Potentially problematic release.


This version of cumulusci-plus might be problematic. Click here for more details.

Files changed (744) hide show
  1. cumulusci/__about__.py +1 -0
  2. cumulusci/__init__.py +22 -0
  3. cumulusci/__main__.py +3 -0
  4. cumulusci/cli/__init__.py +0 -0
  5. cumulusci/cli/cci.py +244 -0
  6. cumulusci/cli/error.py +125 -0
  7. cumulusci/cli/flow.py +185 -0
  8. cumulusci/cli/logger.py +72 -0
  9. cumulusci/cli/org.py +692 -0
  10. cumulusci/cli/plan.py +181 -0
  11. cumulusci/cli/project.py +391 -0
  12. cumulusci/cli/robot.py +116 -0
  13. cumulusci/cli/runtime.py +190 -0
  14. cumulusci/cli/service.py +521 -0
  15. cumulusci/cli/task.py +295 -0
  16. cumulusci/cli/tests/__init__.py +0 -0
  17. cumulusci/cli/tests/test_cci.py +545 -0
  18. cumulusci/cli/tests/test_error.py +170 -0
  19. cumulusci/cli/tests/test_flow.py +276 -0
  20. cumulusci/cli/tests/test_logger.py +25 -0
  21. cumulusci/cli/tests/test_org.py +1438 -0
  22. cumulusci/cli/tests/test_plan.py +245 -0
  23. cumulusci/cli/tests/test_project.py +235 -0
  24. cumulusci/cli/tests/test_robot.py +177 -0
  25. cumulusci/cli/tests/test_runtime.py +197 -0
  26. cumulusci/cli/tests/test_service.py +853 -0
  27. cumulusci/cli/tests/test_task.py +266 -0
  28. cumulusci/cli/tests/test_ui.py +310 -0
  29. cumulusci/cli/tests/test_utils.py +122 -0
  30. cumulusci/cli/tests/utils.py +52 -0
  31. cumulusci/cli/ui.py +234 -0
  32. cumulusci/cli/utils.py +150 -0
  33. cumulusci/conftest.py +181 -0
  34. cumulusci/core/__init__.py +0 -0
  35. cumulusci/core/config/BaseConfig.py +5 -0
  36. cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
  37. cumulusci/core/config/OrgConfig.py +5 -0
  38. cumulusci/core/config/ScratchOrgConfig.py +5 -0
  39. cumulusci/core/config/__init__.py +125 -0
  40. cumulusci/core/config/base_config.py +111 -0
  41. cumulusci/core/config/base_task_flow_config.py +82 -0
  42. cumulusci/core/config/marketing_cloud_service_config.py +83 -0
  43. cumulusci/core/config/oauth2_service_config.py +17 -0
  44. cumulusci/core/config/org_config.py +604 -0
  45. cumulusci/core/config/project_config.py +782 -0
  46. cumulusci/core/config/scratch_org_config.py +251 -0
  47. cumulusci/core/config/sfdx_org_config.py +220 -0
  48. cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
  49. cumulusci/core/config/tests/test_config.py +1895 -0
  50. cumulusci/core/config/tests/test_config_expensive.py +839 -0
  51. cumulusci/core/config/tests/test_config_util.py +91 -0
  52. cumulusci/core/config/universal_config.py +88 -0
  53. cumulusci/core/config/util.py +18 -0
  54. cumulusci/core/datasets.py +303 -0
  55. cumulusci/core/debug.py +33 -0
  56. cumulusci/core/dependencies/__init__.py +55 -0
  57. cumulusci/core/dependencies/base.py +561 -0
  58. cumulusci/core/dependencies/dependencies.py +273 -0
  59. cumulusci/core/dependencies/github.py +177 -0
  60. cumulusci/core/dependencies/github_resolvers.py +244 -0
  61. cumulusci/core/dependencies/resolvers.py +580 -0
  62. cumulusci/core/dependencies/tests/__init__.py +0 -0
  63. cumulusci/core/dependencies/tests/conftest.py +385 -0
  64. cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
  65. cumulusci/core/dependencies/tests/test_github.py +83 -0
  66. cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
  67. cumulusci/core/dependencies/utils.py +13 -0
  68. cumulusci/core/enums.py +11 -0
  69. cumulusci/core/exceptions.py +311 -0
  70. cumulusci/core/flowrunner.py +888 -0
  71. cumulusci/core/github.py +665 -0
  72. cumulusci/core/keychain/__init__.py +24 -0
  73. cumulusci/core/keychain/base_project_keychain.py +441 -0
  74. cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
  75. cumulusci/core/keychain/environment_project_keychain.py +7 -0
  76. cumulusci/core/keychain/serialization.py +152 -0
  77. cumulusci/core/keychain/subprocess_keychain.py +24 -0
  78. cumulusci/core/keychain/tests/conftest.py +50 -0
  79. cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
  80. cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
  81. cumulusci/core/metadeploy/__init__.py +0 -0
  82. cumulusci/core/metadeploy/api.py +88 -0
  83. cumulusci/core/metadeploy/plans.py +25 -0
  84. cumulusci/core/metadeploy/tests/test_api.py +276 -0
  85. cumulusci/core/runtime.py +115 -0
  86. cumulusci/core/sfdx.py +162 -0
  87. cumulusci/core/source/__init__.py +16 -0
  88. cumulusci/core/source/github.py +50 -0
  89. cumulusci/core/source/local_folder.py +35 -0
  90. cumulusci/core/source_transforms/__init__.py +0 -0
  91. cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
  92. cumulusci/core/source_transforms/transforms.py +532 -0
  93. cumulusci/core/tasks.py +404 -0
  94. cumulusci/core/template_utils.py +59 -0
  95. cumulusci/core/tests/__init__.py +0 -0
  96. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
  97. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
  98. cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
  99. cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
  100. cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
  101. cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
  102. cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
  103. cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
  104. cumulusci/core/tests/test_datasets_e2e.py +386 -0
  105. cumulusci/core/tests/test_exceptions.py +11 -0
  106. cumulusci/core/tests/test_flowrunner.py +836 -0
  107. cumulusci/core/tests/test_github.py +942 -0
  108. cumulusci/core/tests/test_sfdx.py +138 -0
  109. cumulusci/core/tests/test_source.py +678 -0
  110. cumulusci/core/tests/test_tasks.py +262 -0
  111. cumulusci/core/tests/test_utils.py +141 -0
  112. cumulusci/core/tests/test_utils_merge_config.py +276 -0
  113. cumulusci/core/tests/test_versions.py +76 -0
  114. cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
  115. cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
  116. cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
  117. cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
  118. cumulusci/core/tests/utils.py +116 -0
  119. cumulusci/core/tests/yaml/global.yaml +0 -0
  120. cumulusci/core/utils.py +402 -0
  121. cumulusci/core/versions.py +149 -0
  122. cumulusci/cumulusci.yml +1621 -0
  123. cumulusci/files/admin_profile.xml +20 -0
  124. cumulusci/files/delete_excludes.txt +424 -0
  125. cumulusci/files/templates/project/README.md +12 -0
  126. cumulusci/files/templates/project/cumulusci.yml +63 -0
  127. cumulusci/files/templates/project/dot-gitignore +60 -0
  128. cumulusci/files/templates/project/mapping.yml +45 -0
  129. cumulusci/files/templates/project/scratch_def.json +25 -0
  130. cumulusci/oauth/__init__.py +0 -0
  131. cumulusci/oauth/client.py +400 -0
  132. cumulusci/oauth/exceptions.py +9 -0
  133. cumulusci/oauth/salesforce.py +95 -0
  134. cumulusci/oauth/tests/__init__.py +0 -0
  135. cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
  136. cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
  137. cumulusci/oauth/tests/test_client.py +308 -0
  138. cumulusci/oauth/tests/test_salesforce.py +46 -0
  139. cumulusci/plugins/__init__.py +3 -0
  140. cumulusci/plugins/plugin_base.py +93 -0
  141. cumulusci/plugins/plugin_loader.py +59 -0
  142. cumulusci/robotframework/CumulusCI.py +340 -0
  143. cumulusci/robotframework/CumulusCI.robot +7 -0
  144. cumulusci/robotframework/Performance.py +165 -0
  145. cumulusci/robotframework/Salesforce.py +936 -0
  146. cumulusci/robotframework/Salesforce.robot +192 -0
  147. cumulusci/robotframework/SalesforceAPI.py +416 -0
  148. cumulusci/robotframework/SalesforcePlaywright.py +220 -0
  149. cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
  150. cumulusci/robotframework/__init__.py +2 -0
  151. cumulusci/robotframework/base_library.py +39 -0
  152. cumulusci/robotframework/faker_mixin.py +89 -0
  153. cumulusci/robotframework/form_handlers.py +222 -0
  154. cumulusci/robotframework/javascript/cci_init.js +34 -0
  155. cumulusci/robotframework/javascript/cumulusci.js +4 -0
  156. cumulusci/robotframework/locator_manager.py +197 -0
  157. cumulusci/robotframework/locators_56.py +88 -0
  158. cumulusci/robotframework/locators_57.py +5 -0
  159. cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
  160. cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
  161. cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
  162. cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
  163. cumulusci/robotframework/pageobjects/__init__.py +12 -0
  164. cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
  165. cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
  166. cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
  167. cumulusci/robotframework/tests/FooTestPage.py +8 -0
  168. cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
  169. cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
  170. cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
  171. cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
  172. cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
  173. cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
  174. cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
  175. cumulusci/robotframework/tests/salesforce/api.robot +178 -0
  176. cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
  177. cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
  178. cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
  179. cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
  180. cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
  181. cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
  182. cumulusci/robotframework/tests/salesforce/labels.html +33 -0
  183. cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
  184. cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
  185. cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
  186. cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
  187. cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
  188. cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
  189. cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
  190. cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
  191. cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
  192. cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
  193. cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
  194. cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
  195. cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
  196. cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
  197. cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
  198. cumulusci/robotframework/tests/test_locator_manager.py +158 -0
  199. cumulusci/robotframework/tests/test_pageobjects.py +291 -0
  200. cumulusci/robotframework/tests/test_performance.py +38 -0
  201. cumulusci/robotframework/tests/test_salesforce.py +79 -0
  202. cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
  203. cumulusci/robotframework/tests/test_template_util.py +53 -0
  204. cumulusci/robotframework/tests/test_utils.py +106 -0
  205. cumulusci/robotframework/utils.py +283 -0
  206. cumulusci/salesforce_api/__init__.py +0 -0
  207. cumulusci/salesforce_api/exceptions.py +23 -0
  208. cumulusci/salesforce_api/filterable_objects.py +96 -0
  209. cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
  210. cumulusci/salesforce_api/metadata.py +721 -0
  211. cumulusci/salesforce_api/org_schema.py +571 -0
  212. cumulusci/salesforce_api/org_schema_models.py +226 -0
  213. cumulusci/salesforce_api/package_install.py +265 -0
  214. cumulusci/salesforce_api/package_zip.py +301 -0
  215. cumulusci/salesforce_api/rest_deploy.py +148 -0
  216. cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
  217. cumulusci/salesforce_api/soap_envelopes.py +177 -0
  218. cumulusci/salesforce_api/tests/__init__.py +0 -0
  219. cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
  220. cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
  221. cumulusci/salesforce_api/tests/test_package_install.py +219 -0
  222. cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
  223. cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
  224. cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
  225. cumulusci/salesforce_api/tests/test_utils.py +124 -0
  226. cumulusci/salesforce_api/utils.py +51 -0
  227. cumulusci/schema/cumulusci.jsonschema.json +782 -0
  228. cumulusci/tasks/__init__.py +0 -0
  229. cumulusci/tasks/apex/__init__.py +0 -0
  230. cumulusci/tasks/apex/anon.py +157 -0
  231. cumulusci/tasks/apex/batch.py +180 -0
  232. cumulusci/tasks/apex/testrunner.py +835 -0
  233. cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
  234. cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
  235. cumulusci/tasks/base_source_control_task.py +17 -0
  236. cumulusci/tasks/bulkdata/__init__.py +15 -0
  237. cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
  238. cumulusci/tasks/bulkdata/dates.py +97 -0
  239. cumulusci/tasks/bulkdata/delete.py +156 -0
  240. cumulusci/tasks/bulkdata/extract.py +441 -0
  241. cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
  242. cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
  243. cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
  244. cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
  245. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
  246. cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
  247. cumulusci/tasks/bulkdata/factory_utils.py +134 -0
  248. cumulusci/tasks/bulkdata/generate.py +4 -0
  249. cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
  250. cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
  251. cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
  252. cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
  253. cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
  254. cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
  255. cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
  256. cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
  257. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
  258. cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
  259. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
  260. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
  261. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
  262. cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
  263. cumulusci/tasks/bulkdata/load.py +1196 -0
  264. cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
  265. cumulusci/tasks/bulkdata/query_transformers.py +264 -0
  266. cumulusci/tasks/bulkdata/select_utils.py +792 -0
  267. cumulusci/tasks/bulkdata/snowfakery.py +753 -0
  268. cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
  269. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
  270. cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
  271. cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
  272. cumulusci/tasks/bulkdata/step.py +1242 -0
  273. cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
  274. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
  275. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
  276. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
  277. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
  278. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
  279. cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
  280. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
  281. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
  282. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
  283. cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
  284. cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
  285. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
  286. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
  287. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
  288. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
  289. cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
  290. cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
  291. cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
  292. cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
  293. cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
  294. cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
  295. cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
  296. cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
  297. cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
  298. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
  299. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
  300. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
  301. cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
  302. cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
  303. cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
  304. cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
  305. cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
  306. cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
  307. cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
  308. cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
  309. cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
  310. cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
  311. cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
  312. cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
  313. cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
  314. cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
  315. cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
  316. cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
  317. cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
  318. cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
  319. cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
  320. cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
  321. cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
  322. cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
  323. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
  324. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
  325. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
  326. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
  327. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
  328. cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
  329. cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
  330. cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
  331. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
  332. cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
  333. cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
  334. cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
  335. cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
  336. cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
  337. cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
  338. cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
  339. cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
  340. cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
  341. cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
  342. cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
  343. cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
  344. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
  345. cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
  346. cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
  347. cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
  348. cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
  349. cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
  350. cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
  351. cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
  352. cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
  353. cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
  354. cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
  355. cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
  356. cumulusci/tasks/bulkdata/tests/utils.py +114 -0
  357. cumulusci/tasks/bulkdata/update_data.py +260 -0
  358. cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
  359. cumulusci/tasks/bulkdata/utils.py +249 -0
  360. cumulusci/tasks/command.py +178 -0
  361. cumulusci/tasks/connectedapp.py +186 -0
  362. cumulusci/tasks/create_package_version.py +778 -0
  363. cumulusci/tasks/datadictionary.py +745 -0
  364. cumulusci/tasks/dx_convert_from.py +26 -0
  365. cumulusci/tasks/github/__init__.py +17 -0
  366. cumulusci/tasks/github/base.py +16 -0
  367. cumulusci/tasks/github/commit_status.py +13 -0
  368. cumulusci/tasks/github/merge.py +11 -0
  369. cumulusci/tasks/github/publish.py +11 -0
  370. cumulusci/tasks/github/pull_request.py +11 -0
  371. cumulusci/tasks/github/release.py +11 -0
  372. cumulusci/tasks/github/release_report.py +11 -0
  373. cumulusci/tasks/github/tag.py +11 -0
  374. cumulusci/tasks/github/tests/__init__.py +0 -0
  375. cumulusci/tasks/github/tests/test_util.py +202 -0
  376. cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
  377. cumulusci/tasks/github/tests/util_github_api.py +666 -0
  378. cumulusci/tasks/github/util.py +252 -0
  379. cumulusci/tasks/marketing_cloud/__init__.py +0 -0
  380. cumulusci/tasks/marketing_cloud/api.py +188 -0
  381. cumulusci/tasks/marketing_cloud/base.py +38 -0
  382. cumulusci/tasks/marketing_cloud/deploy.py +345 -0
  383. cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
  384. cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
  385. cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
  386. cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
  387. cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
  388. cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
  389. cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
  390. cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
  391. cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
  392. cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
  393. cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
  394. cumulusci/tasks/metadata/__init__.py +0 -0
  395. cumulusci/tasks/metadata/ee_src.py +94 -0
  396. cumulusci/tasks/metadata/managed_src.py +100 -0
  397. cumulusci/tasks/metadata/metadata_map.yml +868 -0
  398. cumulusci/tasks/metadata/modify.py +99 -0
  399. cumulusci/tasks/metadata/package.py +684 -0
  400. cumulusci/tasks/metadata/tests/__init__.py +0 -0
  401. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
  402. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
  403. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
  404. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
  405. cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
  406. cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
  407. cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
  408. cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
  409. cumulusci/tasks/metadata/tests/test_modify.py +123 -0
  410. cumulusci/tasks/metadata/tests/test_package.py +476 -0
  411. cumulusci/tasks/metadata_etl/__init__.py +29 -0
  412. cumulusci/tasks/metadata_etl/base.py +436 -0
  413. cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
  414. cumulusci/tasks/metadata_etl/field_sets.py +70 -0
  415. cumulusci/tasks/metadata_etl/help_text.py +92 -0
  416. cumulusci/tasks/metadata_etl/layouts.py +550 -0
  417. cumulusci/tasks/metadata_etl/objects.py +68 -0
  418. cumulusci/tasks/metadata_etl/permissions.py +167 -0
  419. cumulusci/tasks/metadata_etl/picklists.py +221 -0
  420. cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
  421. cumulusci/tasks/metadata_etl/sharing.py +138 -0
  422. cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
  423. cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
  424. cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
  425. cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
  426. cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
  427. cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
  428. cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
  429. cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
  430. cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
  431. cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
  432. cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
  433. cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
  434. cumulusci/tasks/metadata_etl/value_sets.py +106 -0
  435. cumulusci/tasks/metadeploy.py +393 -0
  436. cumulusci/tasks/metaxml.py +88 -0
  437. cumulusci/tasks/preflight/__init__.py +0 -0
  438. cumulusci/tasks/preflight/dataset_load.py +49 -0
  439. cumulusci/tasks/preflight/licenses.py +86 -0
  440. cumulusci/tasks/preflight/packages.py +14 -0
  441. cumulusci/tasks/preflight/permsets.py +23 -0
  442. cumulusci/tasks/preflight/recordtypes.py +16 -0
  443. cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
  444. cumulusci/tasks/preflight/settings.py +77 -0
  445. cumulusci/tasks/preflight/sobjects.py +202 -0
  446. cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
  447. cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
  448. cumulusci/tasks/preflight/tests/test_packages.py +14 -0
  449. cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
  450. cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
  451. cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
  452. cumulusci/tasks/preflight/tests/test_settings.py +130 -0
  453. cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
  454. cumulusci/tasks/push/README.md +59 -0
  455. cumulusci/tasks/push/__init__.py +0 -0
  456. cumulusci/tasks/push/push_api.py +659 -0
  457. cumulusci/tasks/push/pushfails.py +136 -0
  458. cumulusci/tasks/push/tasks.py +476 -0
  459. cumulusci/tasks/push/tests/conftest.py +263 -0
  460. cumulusci/tasks/push/tests/test_push_api.py +951 -0
  461. cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
  462. cumulusci/tasks/release_notes/README.md +63 -0
  463. cumulusci/tasks/release_notes/__init__.py +0 -0
  464. cumulusci/tasks/release_notes/exceptions.py +5 -0
  465. cumulusci/tasks/release_notes/generator.py +137 -0
  466. cumulusci/tasks/release_notes/parser.py +232 -0
  467. cumulusci/tasks/release_notes/provider.py +44 -0
  468. cumulusci/tasks/release_notes/task.py +300 -0
  469. cumulusci/tasks/release_notes/tests/__init__.py +0 -0
  470. cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
  471. cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
  472. cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
  473. cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
  474. cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
  475. cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
  476. cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
  477. cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
  478. cumulusci/tasks/release_notes/tests/test_task.py +461 -0
  479. cumulusci/tasks/release_notes/tests/utils.py +153 -0
  480. cumulusci/tasks/robotframework/__init__.py +3 -0
  481. cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
  482. cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
  483. cumulusci/tasks/robotframework/debugger/model.py +87 -0
  484. cumulusci/tasks/robotframework/debugger/ui.py +259 -0
  485. cumulusci/tasks/robotframework/libdoc.py +269 -0
  486. cumulusci/tasks/robotframework/robotframework.py +392 -0
  487. cumulusci/tasks/robotframework/stylesheet.css +130 -0
  488. cumulusci/tasks/robotframework/template.html +109 -0
  489. cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
  490. cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
  491. cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
  492. cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
  493. cumulusci/tasks/robotframework/tests/performance.robot +23 -0
  494. cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
  495. cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
  496. cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
  497. cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
  498. cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
  499. cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
  500. cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
  501. cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
  502. cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
  503. cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
  504. cumulusci/tasks/salesforce/CreatePackage.py +29 -0
  505. cumulusci/tasks/salesforce/Deploy.py +240 -0
  506. cumulusci/tasks/salesforce/DeployBundles.py +88 -0
  507. cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
  508. cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
  509. cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
  510. cumulusci/tasks/salesforce/ListCommunities.py +40 -0
  511. cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
  512. cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
  513. cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
  514. cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
  515. cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
  516. cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
  517. cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
  518. cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
  519. cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
  520. cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
  521. cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
  522. cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
  523. cumulusci/tasks/salesforce/__init__.py +79 -0
  524. cumulusci/tasks/salesforce/activate_flow.py +74 -0
  525. cumulusci/tasks/salesforce/check_components.py +324 -0
  526. cumulusci/tasks/salesforce/composite.py +142 -0
  527. cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
  528. cumulusci/tasks/salesforce/custom_settings.py +134 -0
  529. cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
  530. cumulusci/tasks/salesforce/enable_prediction.py +107 -0
  531. cumulusci/tasks/salesforce/insert_record.py +40 -0
  532. cumulusci/tasks/salesforce/install_package_version.py +242 -0
  533. cumulusci/tasks/salesforce/license_preflights.py +8 -0
  534. cumulusci/tasks/salesforce/network_member_group.py +178 -0
  535. cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
  536. cumulusci/tasks/salesforce/org_settings.py +193 -0
  537. cumulusci/tasks/salesforce/package_upload.py +328 -0
  538. cumulusci/tasks/salesforce/profiles.py +74 -0
  539. cumulusci/tasks/salesforce/promote_package_version.py +376 -0
  540. cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
  541. cumulusci/tasks/salesforce/salesforce_files.py +244 -0
  542. cumulusci/tasks/salesforce/sourcetracking.py +507 -0
  543. cumulusci/tasks/salesforce/tests/__init__.py +3 -0
  544. cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
  545. cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
  546. cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
  547. cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
  548. cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
  549. cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
  550. cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
  551. cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
  552. cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
  553. cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
  554. cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
  555. cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
  556. cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
  557. cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
  558. cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
  559. cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
  560. cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
  561. cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
  562. cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
  563. cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
  564. cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
  565. cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
  566. cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
  567. cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
  568. cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
  569. cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
  570. cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
  571. cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
  572. cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
  573. cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
  574. cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
  575. cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
  576. cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
  577. cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
  578. cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
  579. cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
  580. cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
  581. cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
  582. cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
  583. cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
  584. cumulusci/tasks/salesforce/tests/util.py +79 -0
  585. cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
  586. cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
  587. cumulusci/tasks/salesforce/update_dependencies.py +290 -0
  588. cumulusci/tasks/salesforce/update_profile.py +339 -0
  589. cumulusci/tasks/salesforce/users/permsets.py +227 -0
  590. cumulusci/tasks/salesforce/users/photos.py +162 -0
  591. cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
  592. cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
  593. cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
  594. cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
  595. cumulusci/tasks/sample_data/load_sample_data.py +85 -0
  596. cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
  597. cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
  598. cumulusci/tasks/sfdx.py +83 -0
  599. cumulusci/tasks/tests/__init__.py +1 -0
  600. cumulusci/tasks/tests/conftest.py +30 -0
  601. cumulusci/tasks/tests/test_command.py +129 -0
  602. cumulusci/tasks/tests/test_connectedapp.py +236 -0
  603. cumulusci/tasks/tests/test_create_package_version.py +847 -0
  604. cumulusci/tasks/tests/test_datadictionary.py +1575 -0
  605. cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
  606. cumulusci/tasks/tests/test_metadeploy.py +624 -0
  607. cumulusci/tasks/tests/test_metaxml.py +99 -0
  608. cumulusci/tasks/tests/test_promote_package_version.py +488 -0
  609. cumulusci/tasks/tests/test_pushfails.py +96 -0
  610. cumulusci/tasks/tests/test_salesforce.py +72 -0
  611. cumulusci/tasks/tests/test_sfdx.py +105 -0
  612. cumulusci/tasks/tests/test_util.py +207 -0
  613. cumulusci/tasks/util.py +261 -0
  614. cumulusci/tasks/vcs/__init__.py +19 -0
  615. cumulusci/tasks/vcs/commit_status.py +58 -0
  616. cumulusci/tasks/vcs/create_commit_status.py +37 -0
  617. cumulusci/tasks/vcs/download_extract.py +199 -0
  618. cumulusci/tasks/vcs/merge.py +298 -0
  619. cumulusci/tasks/vcs/publish.py +207 -0
  620. cumulusci/tasks/vcs/pull_request.py +9 -0
  621. cumulusci/tasks/vcs/release.py +134 -0
  622. cumulusci/tasks/vcs/release_report.py +105 -0
  623. cumulusci/tasks/vcs/tag.py +31 -0
  624. cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
  625. cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
  626. cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
  627. cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
  628. cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
  629. cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
  630. cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
  631. cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
  632. cumulusci/tasks/vlocity/exceptions.py +2 -0
  633. cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
  634. cumulusci/tasks/vlocity/vlocity.py +342 -0
  635. cumulusci/tests/__init__.py +1 -0
  636. cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
  637. cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
  638. cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
  639. cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
  640. cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
  641. cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
  642. cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
  643. cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
  644. cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
  645. cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
  646. cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
  647. cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
  648. cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
  649. cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
  650. cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
  651. cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
  652. cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
  653. cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
  654. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
  655. cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
  656. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
  657. cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
  658. cumulusci/tests/test_entry_points.py +20 -0
  659. cumulusci/tests/test_integration_infrastructure.py +131 -0
  660. cumulusci/tests/test_main.py +9 -0
  661. cumulusci/tests/test_schema.py +32 -0
  662. cumulusci/tests/test_utils.py +657 -0
  663. cumulusci/tests/test_vcr_serializer.py +134 -0
  664. cumulusci/tests/uncompressed_cassette.yaml +83 -0
  665. cumulusci/tests/util.py +344 -0
  666. cumulusci/utils/__init__.py +731 -0
  667. cumulusci/utils/classutils.py +9 -0
  668. cumulusci/utils/collections.py +32 -0
  669. cumulusci/utils/deprecation.py +11 -0
  670. cumulusci/utils/encryption.py +31 -0
  671. cumulusci/utils/fileutils.py +295 -0
  672. cumulusci/utils/git.py +142 -0
  673. cumulusci/utils/http/multi_request.py +214 -0
  674. cumulusci/utils/http/requests_utils.py +103 -0
  675. cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
  676. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
  677. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
  678. cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
  679. cumulusci/utils/http/tests/test_multi_request.py +255 -0
  680. cumulusci/utils/iterators.py +21 -0
  681. cumulusci/utils/logging.py +128 -0
  682. cumulusci/utils/metaprogramming.py +10 -0
  683. cumulusci/utils/options.py +138 -0
  684. cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
  685. cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
  686. cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
  687. cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
  688. cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
  689. cumulusci/utils/salesforce/count_sobjects.py +46 -0
  690. cumulusci/utils/salesforce/soql.py +17 -0
  691. cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
  692. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
  693. cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
  694. cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
  695. cumulusci/utils/salesforce/tests/test_soql.py +30 -0
  696. cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
  697. cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
  698. cumulusci/utils/tests/test_fileutils.py +284 -0
  699. cumulusci/utils/tests/test_git.py +85 -0
  700. cumulusci/utils/tests/test_logging.py +70 -0
  701. cumulusci/utils/tests/test_option_parsing.py +188 -0
  702. cumulusci/utils/tests/test_org_schema.py +691 -0
  703. cumulusci/utils/tests/test_org_schema_models.py +79 -0
  704. cumulusci/utils/tests/test_waiting.py +25 -0
  705. cumulusci/utils/version_strings.py +391 -0
  706. cumulusci/utils/waiting.py +42 -0
  707. cumulusci/utils/xml/__init__.py +91 -0
  708. cumulusci/utils/xml/metadata_tree.py +299 -0
  709. cumulusci/utils/xml/robot_xml.py +114 -0
  710. cumulusci/utils/xml/salesforce_encoding.py +100 -0
  711. cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
  712. cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
  713. cumulusci/utils/yaml/cumulusci_yml.py +401 -0
  714. cumulusci/utils/yaml/model_parser.py +156 -0
  715. cumulusci/utils/yaml/safer_loader.py +74 -0
  716. cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
  717. cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
  718. cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
  719. cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
  720. cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
  721. cumulusci/utils/ziputils.py +61 -0
  722. cumulusci/vcs/base.py +143 -0
  723. cumulusci/vcs/bootstrap.py +272 -0
  724. cumulusci/vcs/github/__init__.py +24 -0
  725. cumulusci/vcs/github/adapter.py +689 -0
  726. cumulusci/vcs/github/release_notes/generator.py +219 -0
  727. cumulusci/vcs/github/release_notes/parser.py +151 -0
  728. cumulusci/vcs/github/release_notes/provider.py +143 -0
  729. cumulusci/vcs/github/service.py +569 -0
  730. cumulusci/vcs/github/tests/test_adapter.py +138 -0
  731. cumulusci/vcs/github/tests/test_service.py +408 -0
  732. cumulusci/vcs/models.py +586 -0
  733. cumulusci/vcs/tests/conftest.py +41 -0
  734. cumulusci/vcs/tests/dummy_service.py +241 -0
  735. cumulusci/vcs/tests/test_vcs_base.py +687 -0
  736. cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
  737. cumulusci/vcs/utils/__init__.py +31 -0
  738. cumulusci/vcs/vcs_source.py +287 -0
  739. cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
  740. cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
  741. cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
  742. cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
  743. cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
  744. cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
@@ -0,0 +1,867 @@
1
+ import http.client
2
+ import urllib.parse
3
+ from unittest import mock
4
+
5
+ import pytest
6
+ import responses
7
+
8
+ from cumulusci.core.exceptions import GithubApiNotFoundError
9
+ from cumulusci.core.github import get_github_api
10
+ from cumulusci.tasks.github.tests.util_github_api import GithubApiTestMixin
11
+ from cumulusci.tasks.release_notes.parser import (
12
+ BaseChangeNotesParser,
13
+ ChangeNotesLinesParser,
14
+ InstallLinkParser,
15
+ )
16
+ from cumulusci.tasks.release_notes.tests.utils import MockUtil
17
+ from cumulusci.vcs.github.release_notes.generator import GithubReleaseNotesGenerator
18
+ from cumulusci.vcs.github.release_notes.parser import (
19
+ GithubIssuesParser,
20
+ GithubLinesParser,
21
+ IssuesParser,
22
+ )
23
+
24
+ PARSER_CONFIG = [
25
+ {
26
+ "class_path": "cumulusci.vcs.github.release_notes.parser.GithubLinesParser",
27
+ "title": "Critical Changes",
28
+ },
29
+ {
30
+ "class_path": "cumulusci.vcs.github.release_notes.parser.GithubLinesParser",
31
+ "title": "Changes",
32
+ },
33
+ {
34
+ "class_path": "cumulusci.vcs.github.release_notes.parser.GithubIssuesParser",
35
+ "title": "Issues Closed",
36
+ },
37
+ ]
38
+
39
+
40
+ class TestBaseChangeNotesParser:
41
+ def test_parse(self):
42
+ parser = BaseChangeNotesParser("Title")
43
+ with pytest.raises(NotImplementedError):
44
+ parser.parse()
45
+
46
+ def test_render(self):
47
+ parser = BaseChangeNotesParser("Title")
48
+ with pytest.raises(NotImplementedError):
49
+ parser.render()
50
+
51
+
52
+ class TestChangeNotesLinesParser:
53
+ def setup_method(self):
54
+ self.title = "Title"
55
+
56
+ def test_parse_no_start_line(self):
57
+ change_note = "foo\r\nbar\r\n"
58
+ parser = ChangeNotesLinesParser(None, self.title)
59
+ line_added = parser.parse(change_note)
60
+ assert parser.content == []
61
+ assert not line_added
62
+
63
+ def test_parse_start_line_no_content(self):
64
+ change_note = "# {}\r\n\r\n".format(self.title)
65
+ parser = ChangeNotesLinesParser(None, self.title)
66
+ line_added = parser.parse(change_note)
67
+ assert parser.content == []
68
+ assert not line_added
69
+
70
+ def test_parse_start_line_no_end_line(self):
71
+ change_note = "# {}\r\nfoo\r\nbar".format(self.title)
72
+ parser = ChangeNotesLinesParser(None, self.title)
73
+ line_added = parser.parse(change_note)
74
+ assert parser.content == ["foo", "bar"]
75
+ assert line_added is True
76
+
77
+ def test_parse_start_line_end_at_header(self):
78
+ change_note = "# {}\r\nfoo\r\n# Another Header\r\nbar".format(self.title)
79
+ parser = ChangeNotesLinesParser(None, self.title)
80
+ line_added = parser.parse(change_note)
81
+ assert parser.content == ["foo"]
82
+ assert line_added
83
+
84
+ def test_parse_start_line_no_content_no_end_line(self):
85
+ change_note = "# {}".format(self.title)
86
+ parser = ChangeNotesLinesParser(None, self.title)
87
+ line_added = parser.parse(change_note)
88
+ assert parser.content == []
89
+ assert not line_added
90
+
91
+ def test_parse_multiple_start_lines_without_end_lines(self):
92
+ change_note = "# {0}\r\nfoo\r\n# {0}\r\nbar\r\n".format(self.title)
93
+ parser = ChangeNotesLinesParser(None, self.title)
94
+ line_added = parser.parse(change_note)
95
+ assert parser.content == ["foo", "bar"]
96
+ assert line_added
97
+
98
+ def test_parse_multiple_start_lines_with_end_lines(self):
99
+ change_note = "# {0}\r\nfoo\r\n\r\n# {0}\r\nbar\r\n\r\nincluded\r\n\r\n# not included".format(
100
+ self.title
101
+ )
102
+ parser = ChangeNotesLinesParser(None, self.title)
103
+ line_added = parser.parse(change_note)
104
+ assert parser.content == ["foo", "bar", "included"]
105
+ assert line_added
106
+
107
+ def test_parse_multi_level_indent(self):
108
+ change_note = "# {0}\r\nfoo \r\n bar \r\n baz \r\n".format(
109
+ self.title
110
+ )
111
+ parser = ChangeNotesLinesParser(None, self.title)
112
+ line_added = parser.parse(change_note)
113
+ assert parser.content == ["foo", " bar", " baz"]
114
+ assert line_added
115
+
116
+ def test_parse_subheading(self):
117
+ change_note = "# {0}\r\n## Subheading\r\nfoo".format(self.title)
118
+ parser = ChangeNotesLinesParser(None, self.title)
119
+ line_added = parser.parse(change_note)
120
+ assert [] == parser.content
121
+ assert {"Subheading": ["foo"]} == parser.h2
122
+ assert line_added
123
+
124
+ def test_parse_subheading_from_another_section(self):
125
+ change_note = "## Subheading\r\n# {0}\r\nfoo".format(self.title)
126
+ parser = ChangeNotesLinesParser(None, self.title)
127
+ line_added = parser.parse(change_note)
128
+ assert ["foo"] == parser.content
129
+ assert {} == parser.h2
130
+ assert line_added
131
+
132
+ def test_render_no_content(self):
133
+ parser = ChangeNotesLinesParser(None, self.title)
134
+ assert parser.render() == ""
135
+
136
+ def test_render_one_content(self):
137
+ parser = ChangeNotesLinesParser(None, self.title)
138
+ content = ["foo"]
139
+ parser.content = content
140
+ assert parser.render() == "# {}\r\n\r\n{}".format(self.title, content[0])
141
+
142
+ def test_render_multiple_content(self):
143
+ parser = ChangeNotesLinesParser(None, self.title)
144
+ content = ["foo", "bar"]
145
+ parser.content = content
146
+ assert parser.render() == "# {}\r\n\r\n{}".format(
147
+ self.title, "\r\n".join(content)
148
+ )
149
+
150
+ def test_render_subheadings(self):
151
+ parser = ChangeNotesLinesParser(None, self.title)
152
+ parser.h2 = {"Subheading": ["foo"]}
153
+ assert parser.render() == "# {}\r\n\r\n\r\n## Subheading\r\n\r\nfoo".format(
154
+ self.title
155
+ )
156
+
157
+
158
+ class TestGithubLinesParser:
159
+ def setup_method(self):
160
+ self.title = "Title"
161
+
162
+ def test_parse(self):
163
+ generator = mock.Mock(link_pr=True)
164
+ parser = GithubLinesParser(generator, self.title)
165
+ pr = mock.Mock(
166
+ number=1, html_url="http://pr", body="# {}\r\n\r\nfoo".format(self.title)
167
+ )
168
+ parser.parse(pr)
169
+ assert 1 == parser.pr_number
170
+ assert parser.pr_url == "http://pr"
171
+ assert ["foo [[PR1](http://pr)]"] == parser.content
172
+
173
+ def test_parse_empty_pull_request_body(self):
174
+ generator = mock.Mock(link_pr=True)
175
+ parser = GithubLinesParser(generator, self.title)
176
+ pr = mock.Mock(number=1, html_url="http://pr", body=None)
177
+ line_added = parser.parse(pr)
178
+ assert not line_added
179
+
180
+
181
+ class TestIssuesParser:
182
+ def setup_method(self):
183
+ self.title = "Issues"
184
+
185
+ def test_issue_numbers(self):
186
+ change_note = "# {}\r\nfix #2\r\nfix #3\r\nfix #5\r\n".format(self.title)
187
+ parser = IssuesParser(None, self.title)
188
+ parser.parse(change_note)
189
+ assert parser.content == [2, 3, 5]
190
+
191
+ def test_issue_numbers_with_links(self):
192
+ change_note = "# {}\r\nfix [#2](https://issue)\r\nfix [#3](http://issue)\r\nfix #5\r\n".format(
193
+ self.title
194
+ )
195
+ parser = IssuesParser(None, self.title)
196
+ parser.parse(change_note)
197
+ assert parser.content == [2, 3, 5]
198
+
199
+ def test_issue_numbers_and_other_numbers(self):
200
+ change_note = "# {}\r\nfixes #2 but not # 3 or 5".format(self.title)
201
+ parser = IssuesParser(None, self.title)
202
+ parser.parse(change_note)
203
+ assert parser.content == [2]
204
+
205
+ def test_multiple_issue_numbers_per_line(self):
206
+ change_note = "# {}\r\nfix #2 also does fix #3 and fix #5\r\n".format(
207
+ self.title
208
+ )
209
+ parser = IssuesParser(None, self.title)
210
+ parser.parse(change_note)
211
+ assert parser.content == [2, 3, 5]
212
+
213
+ def test_render(self):
214
+ parser = IssuesParser(None, self.title)
215
+ parser.content = ["1: foo"]
216
+ assert parser.render() == "# Issues\r\n\r\n#1: foo"
217
+
218
+
219
+ class TestGithubIssuesParser(GithubApiTestMixin):
220
+ def setup_method(self):
221
+ self.init_github()
222
+ self.gh = get_github_api("TestUser", "TestPass")
223
+ self.title = "Issues"
224
+ # Set up the mock release_tag lookup response
225
+ self.issue_number_valid = 123
226
+ self.issue_number_invalid = 456
227
+ self.pr_number = 789
228
+ self.pr_url = "https://github.com/{}/{}/pulls/{}".format(
229
+ "TestOwner", "TestRepo", self.pr_number
230
+ )
231
+ self.mock_util = MockUtil("TestOwner", "TestRepo")
232
+
233
+ @responses.activate
234
+ def test_issue_numbers(self):
235
+ self.mock_util.mock_get_repo()
236
+ change_note = "# {}\r\nFixes #2, Closed #3 and Resolve #5".format(self.title)
237
+ self.mock_util.mock_pull_request(self.pr_number, body=change_note)
238
+ generator = self._create_generator()
239
+ repo = generator.get_repo()
240
+ pull_request = repo.pull_request(self.pr_number)
241
+ parser = GithubIssuesParser(generator, self.title)
242
+ parser.parse(pull_request)
243
+ pr_url = "https://github.com/TestOwner/TestRepo/pulls/{}".format(self.pr_number)
244
+ expected_content = self._create_expected_content([2, 3, 5], pr_url)
245
+ assert parser.content == expected_content
246
+
247
+ @responses.activate
248
+ def test_issue_numbers_and_other_numbers(self):
249
+ self.mock_util.mock_get_repo()
250
+ change_note = "# {}\r\nFixes #2 but not #5".format(self.title)
251
+ self.mock_util.mock_pull_request(self.pr_number, body=change_note)
252
+ generator = self._create_generator()
253
+ repo = generator.get_repo()
254
+ pull_request = repo.pull_request(self.pr_number)
255
+ parser = GithubIssuesParser(generator, self.title)
256
+ parser.parse(pull_request)
257
+ pr_url = "https://github.com/TestOwner/TestRepo/pulls/{}".format(self.pr_number)
258
+ expected_content = self._create_expected_content([2], pr_url)
259
+ assert parser.content == expected_content
260
+
261
+ @responses.activate
262
+ def test_no_issue_numbers(self):
263
+ pr_number = 1
264
+ self.mock_util.mock_get_repo()
265
+ change_note = "# {}\r\n#2 and #3 are fixed by this change".format(self.title)
266
+ self.mock_util.mock_pull_request(pr_number, body=change_note)
267
+ generator = self._create_generator()
268
+ repo = generator.get_repo()
269
+ pull_request = repo.pull_request(pr_number)
270
+ parser = GithubIssuesParser(generator, self.title)
271
+ parser.parse(pull_request)
272
+ assert parser.content == []
273
+
274
+ @responses.activate
275
+ def test_render_issue_number_valid(self):
276
+ api_url = "{}/issues/{}".format(self.repo_api_url, self.issue_number_valid)
277
+ expected_response = self._get_expected_issue(self.issue_number_valid)
278
+ self.mock_util.mock_get_repo()
279
+ responses.add(method=responses.GET, url=api_url, json=expected_response)
280
+ generator = self._create_generator()
281
+ generator.link_pr = True
282
+ parser = GithubIssuesParser(generator, self.title)
283
+ parser.content = [
284
+ {
285
+ "issue_number": self.issue_number_valid,
286
+ "pr_number": self.pr_number,
287
+ "pr_url": self.pr_url,
288
+ }
289
+ ]
290
+ expected_render = self._create_expected_render(
291
+ self.issue_number_valid, expected_response["title"], True
292
+ )
293
+ assert parser.render() == expected_render
294
+
295
+ @responses.activate
296
+ def test_render_issue_number_invalid(self):
297
+ api_url = "{}/issues/{}".format(self.repo_api_url, self.issue_number_invalid)
298
+ expected_response = self._get_expected_not_found()
299
+ self.mock_util.mock_get_repo()
300
+ responses.add(
301
+ method=responses.GET,
302
+ url=api_url,
303
+ json=expected_response,
304
+ status=http.client.NOT_FOUND,
305
+ )
306
+ generator = self._create_generator()
307
+ parser = GithubIssuesParser(generator, self.title)
308
+ parser.content = [
309
+ {
310
+ "issue_number": self.issue_number_invalid,
311
+ "pr_number": self.pr_number,
312
+ "pr_url": self.pr_url,
313
+ }
314
+ ]
315
+ with pytest.raises(GithubApiNotFoundError):
316
+ parser.render()
317
+
318
+ def test_init__issues_enabled(self):
319
+ generator = mock.Mock(has_issues=True)
320
+ result = GithubIssuesParser(generator, self.title)
321
+ assert isinstance(result, GithubIssuesParser)
322
+ assert result.title == self.title
323
+
324
+ def test_init__issues_disabled(self):
325
+ generator = mock.Mock(has_issues=False)
326
+ result = GithubIssuesParser(generator, self.title)
327
+ assert isinstance(result, GithubLinesParser)
328
+ assert result.title == self.title
329
+
330
+ def _create_expected_content(self, issue_numbers, pr_url):
331
+ y = []
332
+ for n in issue_numbers:
333
+ y.append({"issue_number": n, "pr_number": self.pr_number, "pr_url": pr_url})
334
+ return y
335
+
336
+ def _create_expected_render(self, issue_number, issue_title, link_pr):
337
+ render = "# {}\r\n\r\n#{}: {}".format(self.title, issue_number, issue_title)
338
+ if link_pr:
339
+ render += " [[PR{}]({})]".format(self.pr_number, self.pr_url)
340
+ return render
341
+
342
+ def _create_generator(self):
343
+ generator = GithubReleaseNotesGenerator(
344
+ self.gh, self.github_info.copy(), PARSER_CONFIG, "release/1.1"
345
+ )
346
+ return generator
347
+
348
+
349
+ class TestCommentingGithubIssuesParser(GithubApiTestMixin):
350
+ def setup_method(self):
351
+ self.init_github()
352
+ self.gh = get_github_api("TestUser", "TestPass")
353
+ self.mock_util = MockUtil("TestOwner", "TestRepo")
354
+ self.title = "Issues"
355
+ self.issue_number_without_comments = 1
356
+ self.issue_number_with_beta_comment = 2
357
+ self.issue_number_without_beta_comment = 3
358
+ self.issue_number_with_prod_comment = 4
359
+ self.issue_number_without_prod_comment = 5
360
+ self.pr_number = 6
361
+ self.pr_url = "https://github.com/TestOwner/TestRepo/pulls/{}".format(
362
+ self.pr_number
363
+ )
364
+ self.tag_prod = "release/1.2"
365
+ self.tag_beta = "beta/1.2-Beta_3"
366
+ self.tag_not_prod_or_beta = "foo"
367
+ self.version_number_prod = "1.1"
368
+ self.version_number_beta = "1.2 (Beta 3)"
369
+
370
+ def _create_generator(self, tag):
371
+ generator = GithubReleaseNotesGenerator(
372
+ self.gh, self.github_info.copy(), PARSER_CONFIG, tag, publish=True
373
+ )
374
+ return generator
375
+
376
+ @responses.activate
377
+ def test_render_issue_without_comments(self):
378
+ issue_number = self.issue_number_without_comments
379
+ tag = self.tag_not_prod_or_beta
380
+ self.mock_util.mock_get_repo()
381
+ self.mock_util.mock_post_comment(issue_number)
382
+
383
+ # Mock the issue
384
+ api_url = "{}/issues/{}".format(self.repo_api_url, issue_number)
385
+ expected_issue = self._get_expected_issue(issue_number)
386
+ responses.add(method=responses.GET, url=api_url, json=expected_issue)
387
+
388
+ # Mock the comments list
389
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
390
+ responses.add(
391
+ method=responses.GET, url=api_url, json=[], content_type="application/json"
392
+ )
393
+
394
+ generator = self._create_generator(tag)
395
+ parser = GithubIssuesParser(generator, self.title)
396
+ parser.content = [
397
+ {
398
+ "issue_number": issue_number,
399
+ "pr_number": self.pr_number,
400
+ "pr_url": self.pr_url,
401
+ }
402
+ ]
403
+ expected_render = self._create_expected_render(
404
+ issue_number, expected_issue["title"], False
405
+ )
406
+ render = parser.render()
407
+ assert render == expected_render
408
+ assert len(responses.calls._calls) == 2
409
+
410
+ @responses.activate
411
+ def test_render_issue_with_beta_comment(self):
412
+ issue_number = self.issue_number_with_beta_comment
413
+ tag = self.tag_beta
414
+ self.mock_util.mock_get_repo()
415
+ self.mock_util.mock_post_comment(issue_number)
416
+
417
+ # Mock the issue
418
+ api_url = "{}/issues/{}".format(self.repo_api_url, issue_number)
419
+ expected_issue = self._get_expected_issue(issue_number)
420
+ responses.add(method=responses.GET, url=api_url, json=expected_issue)
421
+
422
+ # Mock the comments list
423
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
424
+ expected_comment_1 = self._get_expected_issue_comment(
425
+ GithubIssuesParser.ISSUE_COMMENT["beta"]
426
+ )
427
+ expected_comments = [expected_comment_1]
428
+ responses.add(method=responses.GET, url=api_url, json=expected_comments)
429
+
430
+ generator = self._create_generator(tag)
431
+ parser = GithubIssuesParser(generator, self.title)
432
+ parser.content = [
433
+ {
434
+ "issue_number": issue_number,
435
+ "pr_number": self.pr_number,
436
+ "pr_url": self.pr_url,
437
+ }
438
+ ]
439
+ expected_render = self._create_expected_render(
440
+ issue_number, expected_issue["title"], False
441
+ )
442
+ render = parser.render()
443
+ assert render == expected_render
444
+ assert len(responses.calls._calls) == 3
445
+
446
+ @responses.activate
447
+ def test_render_issue_without_beta_comment(self):
448
+ issue_number = self.issue_number_without_beta_comment
449
+ tag = self.tag_beta
450
+ self.mock_util.mock_get_repo()
451
+ # Mock the issue
452
+ api_url = "{}/issues/{}".format(self.repo_api_url, issue_number)
453
+ expected_issue = self._get_expected_issue(issue_number)
454
+ responses.add(method=responses.GET, url=api_url, json=expected_issue)
455
+
456
+ # Mock the comments list
457
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
458
+ expected_comment_1 = self._get_expected_issue_comment("Some other comment")
459
+ responses.add(
460
+ method=responses.GET, url=api_url, json=[], content_type="application/json"
461
+ )
462
+
463
+ # Mock the comment post response
464
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
465
+ expected_comment_1 = self._get_expected_issue_comment(
466
+ "{} {}".format(
467
+ GithubIssuesParser.ISSUE_COMMENT["beta"], self.version_number_beta
468
+ )
469
+ )
470
+ responses.add(method=responses.POST, url=api_url, json=expected_comment_1)
471
+
472
+ generator = self._create_generator(tag)
473
+ parser = GithubIssuesParser(generator, self.title)
474
+ parser.content = [
475
+ {
476
+ "issue_number": issue_number,
477
+ "pr_number": self.pr_number,
478
+ "pr_url": self.pr_url,
479
+ }
480
+ ]
481
+ expected_render = self._create_expected_render(
482
+ issue_number, expected_issue["title"], False
483
+ )
484
+ assert parser.render() == expected_render
485
+ assert len(responses.calls._calls) == 4
486
+
487
+ @responses.activate
488
+ def test_render_issue_with_prod_comment(self):
489
+ issue_number = self.issue_number_with_prod_comment
490
+ tag = self.tag_prod
491
+
492
+ self.mock_util.mock_get_repo()
493
+
494
+ # Mock the issue
495
+ api_url = "{}/issues/{}".format(self.repo_api_url, issue_number)
496
+ expected_issue = self._get_expected_issue(issue_number)
497
+ responses.add(method=responses.GET, url=api_url, json=expected_issue)
498
+
499
+ # Mock the comments list
500
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
501
+ expected_comment_1 = self._get_expected_issue_comment(
502
+ GithubIssuesParser.ISSUE_COMMENT["prod"]
503
+ )
504
+ expected_comments = [expected_comment_1]
505
+ responses.add(method=responses.GET, url=api_url, json=expected_comments)
506
+
507
+ generator = self._create_generator(tag)
508
+ parser = GithubIssuesParser(generator, self.title)
509
+ parser.content = [
510
+ {
511
+ "issue_number": issue_number,
512
+ "pr_number": self.pr_number,
513
+ "pr_url": self.pr_url,
514
+ }
515
+ ]
516
+ expected_render = self._create_expected_render(
517
+ issue_number, expected_issue["title"], False
518
+ )
519
+ assert parser.render() == expected_render
520
+ assert len(responses.calls._calls) == 3
521
+
522
+ @responses.activate
523
+ def test_render_issue_without_prod_comment(self):
524
+ issue_number = self.issue_number_without_prod_comment
525
+ tag = self.tag_prod
526
+ self.mock_util.mock_get_repo()
527
+ # Mock the issue
528
+ api_url = "{}/issues/{}".format(self.repo_api_url, issue_number)
529
+ expected_issue = self._get_expected_issue(issue_number)
530
+ responses.add(method=responses.GET, url=api_url, json=expected_issue)
531
+
532
+ # Mock the comments list
533
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
534
+ expected_comment_1 = self._get_expected_issue_comment("Some other comment")
535
+ responses.add(
536
+ method=responses.GET, url=api_url, json=[], content_type="application/json"
537
+ )
538
+
539
+ # Mock the comment post response
540
+ api_url = "{}/issues/{}/comments".format(self.repo_api_url, issue_number)
541
+ expected_comment_1 = self._get_expected_issue_comment(
542
+ "{} {}".format(
543
+ GithubIssuesParser.ISSUE_COMMENT["prod"], self.version_number_prod
544
+ )
545
+ )
546
+ responses.add(method=responses.POST, url=api_url, json=expected_comment_1)
547
+
548
+ generator = self._create_generator(tag)
549
+ parser = GithubIssuesParser(generator, self.title)
550
+ parser.content = [
551
+ {
552
+ "issue_number": issue_number,
553
+ "pr_number": self.pr_number,
554
+ "pr_url": self.pr_url,
555
+ }
556
+ ]
557
+ expected_render = self._create_expected_render(
558
+ issue_number, expected_issue["title"], False
559
+ )
560
+ render = parser.render()
561
+ assert render == expected_render
562
+ assert len(responses.calls._calls) == 4
563
+
564
+ def _create_expected_render(self, issue_number, issue_title, link_pr):
565
+ render = "# {}\r\n\r\n#{}: {}".format(self.title, issue_number, issue_title)
566
+ if link_pr:
567
+ render += " [[PR{}]({})]".format(self.pr_number, self.pr_url)
568
+ return render
569
+
570
+
571
+ class TestInstallLinkParser:
572
+ def test_no_package_version(self):
573
+ generator = mock.Mock(
574
+ link_pr=True,
575
+ version_id=None,
576
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
577
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
578
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI)
579
+ )
580
+ parser = InstallLinkParser(generator, "Title")
581
+ parser.parse("abc")
582
+ assert parser.render() == ""
583
+
584
+ def test_package_with_version_id_no_dates_no_trial(self):
585
+ generator = mock.Mock(
586
+ link_pr=True,
587
+ version_id="04t0000asdf",
588
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
589
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
590
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
591
+ )
592
+ parser = InstallLinkParser(generator, "Title")
593
+ parser.parse("abc")
594
+ version_id = urllib.parse.quote_plus(generator.version_id)
595
+ assert (
596
+ f"""# Title\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}"""
597
+ == parser.render()
598
+ )
599
+
600
+ def test_package_version_id_both_dates_no_trial(self):
601
+ generator = mock.Mock(
602
+ link_pr=True,
603
+ version_id="04t0000asdf",
604
+ sandbox_date="2020-10-10",
605
+ production_date="2020-10-11",
606
+ trial_info=False,
607
+ ) # need to set explicitly due to mock, will default to False when using CLI
608
+
609
+ parser = InstallLinkParser(generator, "Title")
610
+ parser.parse("abc")
611
+ version_id = urllib.parse.quote_plus(generator.version_id)
612
+ assert (
613
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\nProduction orgs: {generator.production_date}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}"""
614
+ == parser.render()
615
+ )
616
+
617
+ def test_package_version_id_sandbox_date_no_trial(self):
618
+ generator = mock.Mock(
619
+ link_pr=True,
620
+ version_id="04t0000asdf",
621
+ sandbox_date="2020-10-10",
622
+ production_date=None, # need to set explicitly due to mock, will default to False when using CLI
623
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
624
+ )
625
+ parser = InstallLinkParser(generator, "Title")
626
+ parser.parse("abc")
627
+ version_id = urllib.parse.quote_plus(generator.version_id)
628
+ assert (
629
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}"""
630
+ == parser.render()
631
+ )
632
+
633
+ def test_package_version_id_production_date_no_trial(self):
634
+ generator = mock.Mock(
635
+ link_pr=True,
636
+ version_id="04t0000asdf",
637
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
638
+ production_date="2020-10-10",
639
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
640
+ )
641
+ parser = InstallLinkParser(generator, "Title")
642
+ parser.parse("abc")
643
+ version_id = urllib.parse.quote_plus(generator.version_id)
644
+ assert (
645
+ f"""# Title\r\n\r\n## Push Schedule\r\nProduction orgs: {generator.production_date}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}"""
646
+ == parser.render()
647
+ )
648
+
649
+ def test_package_with_version_id_no_dates_trial(self):
650
+ generator = mock.Mock(
651
+ link_pr=True,
652
+ version_id="04t0000asdf",
653
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
654
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
655
+ trial_info="`TBD`",
656
+ )
657
+ parser = InstallLinkParser(generator, "Title")
658
+ parser.parse("abc")
659
+ version_id = urllib.parse.quote_plus(generator.version_id)
660
+ assert (
661
+ f"""# Title\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
662
+ == parser.render()
663
+ )
664
+
665
+ def test_package_version_id_both_dates_with_trial(self):
666
+ generator = mock.Mock(
667
+ link_pr=True,
668
+ version_id="04t0000asdf",
669
+ sandbox_date="2020-10-10",
670
+ production_date="2020-10-11",
671
+ trial_info="`TBD`",
672
+ )
673
+ parser = InstallLinkParser(generator, "Title")
674
+ parser.parse("abc")
675
+ version_id = urllib.parse.quote_plus(generator.version_id)
676
+ assert (
677
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\nProduction orgs: {generator.production_date}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
678
+ == parser.render()
679
+ )
680
+
681
+ def test_package_version_id_sandbox_date_with_trial(self):
682
+ generator = mock.Mock(
683
+ link_pr=True,
684
+ version_id="04t0000asdf",
685
+ sandbox_date="2020-10-10",
686
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
687
+ trial_info="`TBD`",
688
+ )
689
+ parser = InstallLinkParser(generator, "Title")
690
+ parser.parse("abc")
691
+ version_id = urllib.parse.quote_plus(generator.version_id)
692
+ assert (
693
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
694
+ == parser.render()
695
+ )
696
+
697
+ def test_package_version_id_production_date_with_trial(self):
698
+ generator = mock.Mock(
699
+ link_pr=True,
700
+ version_id="04t0000asdf",
701
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
702
+ production_date="2020-10-10",
703
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
704
+ )
705
+ parser = InstallLinkParser(generator, "Title")
706
+ parser.parse("abc")
707
+ version_id = urllib.parse.quote_plus(generator.version_id)
708
+ assert f"""# Title\r\n\r\n## Push Schedule\r\nProduction orgs: {generator.production_date}\r\n\r\n\r\nProduction & Developer Edition Orgs:\r\nhttps://login.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\nSandbox & Scratch Orgs:\r\nhttps://test.salesforce.com/packaging/installPackage.apexp?p0={version_id}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
709
+
710
+ def test_package_no_version_id_sandbox_date_no_trial(self):
711
+ generator = mock.Mock(
712
+ link_pr=True,
713
+ version_id="",
714
+ sandbox_date="2020-10-10", # need to set explicitly due to mock, will default to None when using CLI
715
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
716
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
717
+ )
718
+ parser = InstallLinkParser(generator, "Title")
719
+ parser.parse("abc")
720
+ assert (
721
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}"""
722
+ == parser.render()
723
+ )
724
+
725
+ def test_package_no_version_id_production_date_no_trial(self):
726
+ generator = mock.Mock(
727
+ link_pr=True,
728
+ version_id="",
729
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
730
+ production_date="2020-10-10",
731
+ trial_info=False, # need to set explicitly due to mock, will default to False when using CLI
732
+ )
733
+ parser = InstallLinkParser(generator, "Title")
734
+ parser.parse("abc")
735
+ assert (
736
+ f"""# Title\r\n\r\n## Push Schedule\r\nProduction orgs: {generator.production_date}"""
737
+ == parser.render()
738
+ )
739
+
740
+ def test_package_no_version_id_both_dates_no_trial(self):
741
+ generator = mock.Mock(
742
+ link_pr=True,
743
+ version_id="",
744
+ sandbox_date="2020-10-10",
745
+ production_date="2020-10-11",
746
+ trial_info=False,
747
+ )
748
+ parser = InstallLinkParser(generator, "Title")
749
+ parser.parse("abc")
750
+ assert (
751
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\nProduction orgs: {generator.production_date}"""
752
+ == parser.render()
753
+ )
754
+
755
+ def test_package_no_version_id_sandbox_date_trial(self):
756
+ generator = mock.Mock(
757
+ link_pr=True,
758
+ version_id="",
759
+ sandbox_date="2020-10-10", # need to set explicitly due to mock, will default to None when using CLI
760
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
761
+ trial_info="`TBD`", # need to set explicitly due to mock, will default to False when using CLI
762
+ )
763
+ parser = InstallLinkParser(generator, "Title")
764
+ parser.parse("abc")
765
+ assert (
766
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
767
+ == parser.render()
768
+ )
769
+
770
+ def test_package_no_version_id_production_date_trial(self):
771
+ generator = mock.Mock(
772
+ link_pr=True,
773
+ version_id="",
774
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
775
+ production_date="2020-10-10",
776
+ trial_info="`TBD`", # need to set explicitly due to mock, will default to False when using CLI
777
+ )
778
+ parser = InstallLinkParser(generator, "Title")
779
+ parser.parse("abc")
780
+ assert (
781
+ f"""# Title\r\n\r\n## Push Schedule\r\nProduction orgs: {generator.production_date}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
782
+ == parser.render()
783
+ )
784
+
785
+ def test_package_no_version_id_both_dates_trial(self):
786
+ generator = mock.Mock(
787
+ link_pr=True,
788
+ version_id="",
789
+ sandbox_date="2020-10-10",
790
+ production_date="2020-10-11",
791
+ trial_info="`TBD`",
792
+ )
793
+ parser = InstallLinkParser(generator, "Title")
794
+ parser.parse("abc")
795
+ assert (
796
+ f"""# Title\r\n\r\n## Push Schedule\r\nSandbox orgs: {generator.sandbox_date}\r\nProduction orgs: {generator.production_date}\r\n\r\n## Trialforce Template ID\r\n`TBD`"""
797
+ == parser.render()
798
+ )
799
+
800
+ def test_package_no_version_no_dates_trial(self):
801
+ generator = mock.Mock(
802
+ link_pr=True,
803
+ version_id="",
804
+ sandbox_date=None, # need to set explicitly due to mock, will default to None when using CLI
805
+ production_date=None, # need to set explicitly due to mock, will default to None when using CLI
806
+ trial_info="`TBD`",
807
+ )
808
+ parser = InstallLinkParser(generator, "Title")
809
+ parser.parse("abc")
810
+ assert (
811
+ """# Title\r\n\r\n## Trialforce Template ID\r\n`TBD`""" == parser.render()
812
+ )
813
+
814
+ def test_package_version(self):
815
+ generator = mock.Mock(link_pr=True)
816
+ generator.version_id = "foo bar"
817
+ parser = InstallLinkParser(generator, "Title")
818
+ parser.parse("abc")
819
+ output = parser.render()
820
+ assert (
821
+ "https://login.salesforce.com/packaging/installPackage.apexp?p0=foo+bar"
822
+ in output
823
+ )
824
+ assert (
825
+ "https://test.salesforce.com/packaging/installPackage.apexp?p0=foo+bar"
826
+ in output
827
+ )
828
+
829
+
830
+ class TestMigrationParser(GithubApiTestMixin):
831
+ def setup_method(self):
832
+ self.init_github()
833
+ self.gh = get_github_api("TestUser", "TestPass")
834
+ self.title = "Issues"
835
+ # Set up the mock release_tag lookup response
836
+ self.issue_number_valid = 123
837
+ self.issue_number_invalid = 456
838
+ self.pr_number = 789
839
+ self.pr_url = "https://github.com/{}/{}/pulls/{}".format(
840
+ "TestOwner", "TestRepo", self.pr_number
841
+ )
842
+ self.mock_util = MockUtil("TestOwner", "TestRepo")
843
+
844
+ @responses.activate
845
+ def test_migration(self):
846
+ from cumulusci.tasks.release_notes.parser import (
847
+ GithubIssuesParser,
848
+ GithubLinesParser,
849
+ )
850
+ from cumulusci.utils.deprecation import ClassMovedWarning
851
+
852
+ generator = mock.Mock(has_issues=True)
853
+
854
+ with pytest.warns(
855
+ ClassMovedWarning, match="cumulusci.vcs.github.release_notes.parser"
856
+ ):
857
+ GithubIssuesParser(generator, "")
858
+
859
+ with pytest.warns(
860
+ ClassMovedWarning, match="cumulusci.vcs.github.release_notes.parser"
861
+ ):
862
+ GithubLinesParser(generator, "")
863
+
864
+ assert GithubLinesParser.__module__ == "cumulusci.tasks.release_notes.parser"
865
+ assert GithubLinesParser.__name__ == "GithubLinesParser"
866
+ assert GithubIssuesParser.__module__ == "cumulusci.tasks.release_notes.parser"
867
+ assert GithubIssuesParser.__name__ == "GithubIssuesParser"