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,158 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+
5
+ from cumulusci.robotframework.locator_manager import (
6
+ LOCATORS,
7
+ locate_element,
8
+ register_locators,
9
+ translate_locator,
10
+ )
11
+
12
+ mock_libs = {}
13
+
14
+
15
+ def mock_get_library_instance(name):
16
+ mock_libs[name] = mock.Mock(name=name)
17
+ return mock_libs[name]
18
+
19
+
20
+ class TestTranslateLocator:
21
+ @classmethod
22
+ def setup_class(cls):
23
+ LOCATORS.clear()
24
+ register_locators(
25
+ prefix="test",
26
+ locators={
27
+ "foo": {
28
+ "message": "{} {}",
29
+ "bar": {
30
+ "baz": "//div[@class='baz']",
31
+ "hello": "//span[text()='Hello, {}']",
32
+ },
33
+ },
34
+ "action": "//span[@name='{title}' or @title='{title}']//a[.='{link}']",
35
+ },
36
+ )
37
+
38
+ def test_named_format_fields(self):
39
+ """This tests that named format fields are given positional arguments in the correct order"""
40
+ loc = translate_locator("test", "action:User,Clear")
41
+ assert loc == "//span[@name='User' or @title='User']//a[.='Clear']"
42
+
43
+ def test_strip_whitespace_from_locator(self):
44
+ """Verify whitespace is stripped from locator key and args"""
45
+ loc = translate_locator("test", "foo . bar . baz")
46
+ assert loc == "//div[@class='baz']"
47
+
48
+ def test_nested_locators(self):
49
+ """Verify dot notation can be used to drill into nested structure"""
50
+ loc = translate_locator("test", "foo.bar.baz")
51
+ assert loc == "//div[@class='baz']"
52
+
53
+ def test_arguments(self):
54
+ """Verify arguments appear in the final locator"""
55
+ loc = translate_locator("test", "foo.bar.hello:world")
56
+ assert loc == "//span[text()='Hello, world']"
57
+
58
+ def test_multiple_arguments(self):
59
+ """Verify we support more than a single argument"""
60
+ loc = translate_locator("test", "foo.message:hello,world")
61
+ assert loc == "hello world"
62
+
63
+ def test_extra_args(self):
64
+ """Verify extra args are ignored
65
+
66
+ Maybe we should be throwing an error, but since `.format()`
67
+ doesn't throw an error, we would have to add our own argument
68
+ checking which I think is more trouble than its worth
69
+ """
70
+ loc = translate_locator("test", "foo.message:testing,one,two,three")
71
+ assert loc == "testing one"
72
+
73
+ def test_missing_args(self):
74
+ """Verify a friendly exception is thrown for missing arguments"""
75
+ expected_error = "Not enough arguments were supplied"
76
+ with pytest.raises(Exception, match=expected_error):
77
+ translate_locator("test", "foo.bar.hello")
78
+
79
+ def test_bad_locator(self):
80
+ """Verify a locator that resolves to a non-string raises an error"""
81
+ expected_error = "Expected locator to be of type string, but was <class 'dict'>"
82
+ with pytest.raises(TypeError, match=expected_error):
83
+ translate_locator("test", "foo.bar")
84
+
85
+ def test_unknown_locator(self):
86
+ """Verify that an invalid locator path throws a useful error
87
+
88
+ Not only that, but verify that what appears in the error is
89
+ the first part of the locator key that wasn't found.
90
+ """
91
+ expected_error = "locator test:foo.not not found"
92
+ with pytest.raises(Exception, match=expected_error):
93
+ translate_locator("test", "foo.not.valid")
94
+
95
+
96
+ class TestLocateElement:
97
+ @classmethod
98
+ def setup_class(cls):
99
+ LOCATORS.clear()
100
+ register_locators(
101
+ prefix="test",
102
+ locators={"foo": {"bar": {"hello": "//span[text()='Hello, {}']"}}},
103
+ )
104
+
105
+ def test_locate_element(self):
106
+ """Verify that the locate_element function translates the
107
+ locator and calls SeleniumLibrary.get_webelement with the
108
+ translated locator.
109
+
110
+ That is to say, this verifies that our registered locators
111
+ are actually usable with Selenium keywords.
112
+ """
113
+
114
+ locator = "foo.bar.hello:world"
115
+ parent = mock.Mock()
116
+ tag = ""
117
+ constraints = {}
118
+
119
+ with mock.patch(
120
+ "robot.libraries.BuiltIn.BuiltIn.get_library_instance",
121
+ side_effect=mock_get_library_instance,
122
+ ):
123
+ locate_element("test", parent, locator, tag, constraints)
124
+ mock_libs["SeleniumLibrary"].get_webelements.assert_called_with(
125
+ "//span[text()='Hello, world']"
126
+ )
127
+
128
+
129
+ class TestRegisterLocators:
130
+ def setup_method(self):
131
+ LOCATORS.clear()
132
+
133
+ def test_register_locators(self):
134
+ """Verify that register_locators updates the LOCATORS dictionary"""
135
+ register_locators("test", {"foo": "//div/foo"})
136
+
137
+ expected = {"test": {"foo": "//div/foo"}}
138
+ assert LOCATORS == expected
139
+
140
+ def test_multiple_registrations(self):
141
+ """Verify that more than one prefix can be registered"""
142
+
143
+ register_locators("test1", {"foo": "//div/foo"})
144
+ register_locators("test2", {"bar": "//div/bar"})
145
+
146
+ expected = {"test1": {"foo": "//div/foo"}, "test2": {"bar": "//div/bar"}}
147
+ assert LOCATORS == expected
148
+
149
+ def test_register_locators_merge(self):
150
+ """Verify that calling register_locators will merge the new locators
151
+ with existing locators for a given prefix, rather than
152
+ replacing them.
153
+ """
154
+ register_locators("test1", {"foo": {"one": "//div/one"}})
155
+ register_locators("test1", {"foo": {"two": "//div/two"}})
156
+
157
+ expected = {"test1": {"foo": {"one": "//div/one", "two": "//div/two"}}}
158
+ assert LOCATORS == expected
@@ -0,0 +1,291 @@
1
+ """Tests for the PageObjects class
2
+
3
+ Testing notes:
4
+
5
+ The PageObjects library uses robot's BuiltIn library. However,
6
+ instantiating that will throw an error if done outside the context of
7
+ a running robot test. To work around that, these tests mock out the
8
+ _get_context method to fool the BuiltIn library into not complaining.
9
+
10
+ These tests use two external files in the same directory as this test:
11
+ FooTestPage.py and BarTestPage.py. FooTestPage has a single keyword,
12
+ BarTestPage has two.
13
+
14
+ """
15
+
16
+ import os.path
17
+ import sys
18
+ from contextlib import contextmanager
19
+ from unittest import mock
20
+
21
+ import pytest
22
+ import robot.utils
23
+ from robot.libraries.BuiltIn import BuiltIn
24
+
25
+ from cumulusci.robotframework import PageObjects
26
+ from cumulusci.robotframework.CumulusCI import CumulusCI
27
+ from cumulusci.robotframework.pageobjects.BasePageObjects import (
28
+ DetailPage,
29
+ HomePage,
30
+ ListingPage,
31
+ )
32
+ from cumulusci.robotframework.pageobjects.PageObjectLibrary import _PageObjectLibrary
33
+ from cumulusci.utils import temporary_dir
34
+
35
+ HERE = os.path.dirname(__file__)
36
+ FOO_PATH = os.path.join(HERE, "FooTestPage.py")
37
+ CUSTOM_PATH = os.path.join(HERE, "CustomObjectTestPage.py")
38
+
39
+ # this is the importer used by the page objects, which makes it easy
40
+ # peasy to import by file path
41
+ importer = robot.utils.Importer()
42
+
43
+ # These tests don't need an org, so mocking it out will prevent some
44
+ # keywords from trying to create the org.
45
+ cci_lib = CumulusCI()
46
+ cci_lib._org = mock.Mock()
47
+
48
+
49
+ class MockGetLibraryInstance:
50
+ """Mock robot's get_library_instance method
51
+
52
+ This will return instances of the libraries used in this set of tests.
53
+ """
54
+
55
+ libs = {
56
+ "SeleniumLibrary": mock.Mock(),
57
+ "cumulusci.robotframework.CumulusCI": cci_lib,
58
+ "cumulusci.robotframework.Salesforce": mock.Mock(),
59
+ "cumulusci.robotframework.SalesforceAPI": mock.Mock(),
60
+ # Note: the fact that we're using "Contact" here is largely
61
+ # irrelevant. The important thing is that we create a page
62
+ # object for the base types of Home, Listing,and Detail
63
+ "ContactHomePage": _PageObjectLibrary(HomePage("Contact")),
64
+ "ContactListingPage": _PageObjectLibrary(ListingPage("Contact")),
65
+ "ContactDetailPage": _PageObjectLibrary(DetailPage("Contact")),
66
+ }
67
+
68
+ def __call__(self, libname):
69
+ if libname in self.libs:
70
+ return self.libs[libname]
71
+ else:
72
+ raise Exception("unknown library: {}".format(libname))
73
+
74
+
75
+ @contextmanager
76
+ def reload_PageObjects(*args):
77
+ # Reset the registry and re-import the built-in page objects
78
+ saved_registry = PageObjects.registry
79
+ PageObjects._reset()
80
+ import cumulusci.robotframework.pageobjects.BasePageObjects # noqa: F401
81
+ import cumulusci.robotframework.pageobjects.ObjectManagerPageObject # noqa: F401
82
+
83
+ yield PageObjects(*args)
84
+
85
+ PageObjects._reset()
86
+ PageObjects.registry = saved_registry
87
+
88
+
89
+ @mock.patch(
90
+ "robot.libraries.BuiltIn.BuiltIn.get_library_instance",
91
+ side_effect=MockGetLibraryInstance(),
92
+ )
93
+ # We have to mock out _get_context or the robot libraries will
94
+ # throw an exception saying it cannot access the execution context.
95
+ @mock.patch("robot.libraries.BuiltIn.BuiltIn._get_context")
96
+ class TestPageObjects:
97
+ def test_PageObject(self, get_context_mock, get_library_instance_mock):
98
+ """Smoke test to make sure the default registry is set up and keywords exist"""
99
+
100
+ with reload_PageObjects() as po:
101
+ expected_keywords = [
102
+ "current_page_should_be",
103
+ "get_page_object",
104
+ "go_to_page",
105
+ "load_page_object",
106
+ "log_page_object_keywords",
107
+ "wait_for_modal",
108
+ "wait_for_page_object",
109
+ ]
110
+ actual_keywords = po.get_keyword_names()
111
+ assert actual_keywords == expected_keywords
112
+
113
+ # fmt: off
114
+ # This is much easier to read than if black were to reformat it.
115
+ expected_registry = {
116
+ ("Detail", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.DetailPage'>",
117
+ ("Edit", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.EditModal'>",
118
+ ("Home", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.HomePage'>",
119
+ ("Listing", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.ListingPage'>",
120
+ ("New", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.NewModal'>",
121
+ ("ObjectManager", ""): "<class 'cumulusci.robotframework.pageobjects.ObjectManagerPageObject.ObjectManagerPage'>",
122
+ }
123
+ # fmt: on
124
+ actual_registry = {key: repr(value) for key, value in po.registry.items()}
125
+ assert actual_registry == expected_registry
126
+
127
+ def test_file_in_pythonpath(self, get_context_mock, get_library_instance_mock):
128
+ """Verify we can find a page object via PYTHONPATH"""
129
+ # PageObjects will throw an error if it can't find the file.
130
+ # As long as this doesn't throw an error, we're golden.
131
+ sys_path = sys.path.copy()
132
+ if HERE not in sys.path:
133
+ sys_path.append(HERE)
134
+ with mock.patch.object(sys, "path", sys_path):
135
+ PageObjects("FooTestPage.py")
136
+
137
+ def test_exception_not_found(self, get_context_mock, get_library_instance_mock):
138
+ """Verify we get an assertion of we can't find a page object file"""
139
+ with pytest.raises(
140
+ ImportError, match="Unable to find page object file 'bogus.py'"
141
+ ):
142
+ PageObjects("bogus.py")
143
+
144
+ def test_import_failed(self, get_context_mock, get_library_instance_mock):
145
+ with temporary_dir() as d:
146
+ with open("busted.py", "w") as f:
147
+ f.write("class Busted # incomplete class\n")
148
+ f.close()
149
+ with mock.patch.object(sys, "path", sys.path + [d]):
150
+ with pytest.raises(
151
+ ImportError,
152
+ match="Unable to import page object 'busted.py': .*",
153
+ ):
154
+ PageObjects("busted.py")
155
+
156
+ def test_PageObject_registry_with_custom_pageobjects(
157
+ self, get_context_mock, get_library_instance_mock
158
+ ):
159
+ """Verify that custom page objects get added to the registry"""
160
+ with reload_PageObjects(FOO_PATH, CUSTOM_PATH) as po:
161
+ # fmt: off
162
+ # This is much easier to read than if black were to reformat it.
163
+ expected_registry = {
164
+ ("Detail", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.DetailPage'>",
165
+ ("Edit", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.EditModal'>",
166
+ ("Home", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.HomePage'>",
167
+ ("Listing", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.ListingPage'>",
168
+ ("New", ""): "<class 'cumulusci.robotframework.pageobjects.BasePageObjects.NewModal'>",
169
+ ("ObjectManager", ""): "<class 'cumulusci.robotframework.pageobjects.ObjectManagerPageObject.ObjectManagerPage'>",
170
+ # the custom page object uses an alias for the object name so it will be in the registry twice
171
+ ("Listing", "CustomObject__c"): "<class 'CustomObjectTestPage.CustomObjectListingPage'>",
172
+ ("Listing", "Custom Object"): "<class 'CustomObjectTestPage.CustomObjectListingPage'>",
173
+ ("Test", "Foo__c"): "<class 'FooTestPage.FooTestPage'>",
174
+ }
175
+ # fmt: on
176
+ actual_registry = {key: repr(value) for key, value in po.registry.items()}
177
+ assert actual_registry == expected_registry
178
+
179
+ def test_namespaced_object_name(self, get_context_mock, get_library_instance_mock):
180
+ """Verify that the object name is prefixed by the namespace when there's a namespace"""
181
+ with mock.patch.object(
182
+ CumulusCI, "get_namespace_prefix", return_value="foobar__"
183
+ ):
184
+ with reload_PageObjects(FOO_PATH) as po:
185
+
186
+ FooTestPage = importer.import_class_or_module_by_path(FOO_PATH)
187
+ MockGetLibraryInstance.libs["FooTestPage"] = _PageObjectLibrary(
188
+ FooTestPage()
189
+ )
190
+
191
+ pobj = po.get_page_object("Test", "Foo__c")
192
+ assert pobj.object_name == "foobar__Foo__c"
193
+
194
+ def test_non_namespaced_object_name(
195
+ self, get_context_mock, get_library_instance_mock
196
+ ):
197
+ """Verify that the object name is not prefixed by a namespace when there is no namespace"""
198
+ with mock.patch.object(CumulusCI, "get_namespace_prefix", return_value=""):
199
+ with reload_PageObjects(FOO_PATH) as po:
200
+
201
+ FooTestPage = importer.import_class_or_module_by_path(FOO_PATH)
202
+ MockGetLibraryInstance.libs["FooTestPage"] = _PageObjectLibrary(
203
+ FooTestPage()
204
+ )
205
+
206
+ pobj = po.get_page_object("Test", "Foo__c")
207
+ assert pobj.object_name == "Foo__c"
208
+
209
+ def test_go_to_page_with_locator(self, get_context_mock, get_library_instance_mock):
210
+ """Verify 'Go to page' accepts and uses a locator argument
211
+
212
+ See W-8580487 for more details
213
+ """
214
+
215
+ with reload_PageObjects() as po:
216
+ for page_type in ("Home", "Listing", "Detail"):
217
+ # the exact locator isn't important for the test, we
218
+ # just need to make sure it is passed on to
219
+ # wait_until_loading_is_complete
220
+ locator = f"//div[@class='{page_type}']"
221
+ po.go_to_page(page_type, "Contact", locator=locator)
222
+ sflib = BuiltIn().get_library_instance(
223
+ "cumulusci.robotframework.Salesforce"
224
+ )
225
+ sflib.wait_until_loading_is_complete.assert_called_with(locator=locator)
226
+
227
+ def test_go_to_page_without_locator(
228
+ self, get_context_mock, get_library_instance_mock
229
+ ):
230
+ """Verify 'Go to page' doesn't require a locator"""
231
+
232
+ with reload_PageObjects() as po:
233
+ for page_type in ("Home", "Listing", "Detail"):
234
+ po.go_to_page(page_type, "Contact")
235
+ sflib = BuiltIn().get_library_instance(
236
+ "cumulusci.robotframework.Salesforce"
237
+ )
238
+ sflib.wait_until_loading_is_complete.assert_called_with(locator=None)
239
+
240
+
241
+ @mock.patch(
242
+ "robot.libraries.BuiltIn.BuiltIn.get_library_instance",
243
+ side_effect=MockGetLibraryInstance(),
244
+ )
245
+ class TestBasePage:
246
+ """Some low-level tests of page object classes"""
247
+
248
+ def test_no_implicit_wait(self, mock_get_library_instance):
249
+ """Verify the "implicit wait" context manager restores the value"""
250
+
251
+ selib = BuiltIn().get_library_instance("SeleniumLibrary")
252
+ selib.set_selenium_implicit_wait.return_value = 7
253
+ selib.set_selenium_implicit_wait.reset_mock()
254
+
255
+ from cumulusci.robotframework.pageobjects import BasePage
256
+
257
+ page = BasePage()
258
+ with page._no_implicit_wait():
259
+ pass
260
+
261
+ # The first call should pass in zero to turn off the
262
+ # implicit wait. We've configured the mocked function to
263
+ # return '7'. The second call should pass the return value
264
+ # of the first call
265
+ selib.set_selenium_implicit_wait.assert_has_calls(
266
+ (mock.call(0), mock.call(7)), any_order=False
267
+ )
268
+
269
+ def test_no_implicit_wait_with_exception(self, mock_get_library_instance):
270
+ """Verify the "implicit wait" context manager restores the value even if exception occurs"""
271
+
272
+ selib = BuiltIn().get_library_instance("SeleniumLibrary")
273
+ selib.set_selenium_implicit_wait.return_value = 42
274
+ selib.set_selenium_implicit_wait.reset_mock()
275
+
276
+ from cumulusci.robotframework.pageobjects import BasePage
277
+
278
+ page = BasePage()
279
+ try:
280
+ with page._no_implicit_wait():
281
+ raise Exception("Danger Will Robinson!")
282
+ except Exception:
283
+ pass
284
+
285
+ # The first call should pass in zero to turn off the
286
+ # implicit wait. We've configured the mocked function to
287
+ # return '42'. The second call should pass the return value
288
+ # of the first call
289
+ selib.set_selenium_implicit_wait.assert_has_calls(
290
+ (mock.call(0), mock.call(42)), any_order=False
291
+ )
@@ -0,0 +1,38 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+
5
+ from cumulusci.robotframework.Performance import Performance
6
+ from cumulusci.robotframework.SalesforceAPI import SalesforceAPI
7
+
8
+
9
+ class TestKeyword_elapsed_time_for_last_record:
10
+ def test_elapsed_time_for_last_record__query_empty(self):
11
+ perflib = Performance()
12
+ records = {"records": []}
13
+
14
+ with mock.patch.object(perflib, "_salesforce_api", SalesforceAPI()):
15
+ with mock.patch.object(SalesforceAPI, "cumulusci") as cumulusci:
16
+ cumulusci.sf.query_all.return_value = records
17
+ with pytest.raises(Exception) as e:
18
+ perflib.elapsed_time_for_last_record("FOO", "Bar", "Baz", "Baz")
19
+ assert "Matching record not found" in str(e.value)
20
+
21
+ def test_elapsed_time_for_last_record__query_returns_result(self):
22
+ perflib = Performance()
23
+ records = {
24
+ "records": [
25
+ {
26
+ "CreatedDate": "2020-12-29T10:00:01.000+0000",
27
+ "CompletedDate": "2020-12-29T10:00:04.000+0000",
28
+ }
29
+ ],
30
+ }
31
+
32
+ with mock.patch.object(perflib, "_salesforce_api", SalesforceAPI()):
33
+ with mock.patch.object(SalesforceAPI, "cumulusci") as cumulusci:
34
+ cumulusci.sf.query_all.return_value = records
35
+ elapsed = perflib.elapsed_time_for_last_record(
36
+ "AsyncApexJob", "CreatedDate", "CompletedDate", "CompletedDate"
37
+ )
38
+ assert elapsed == 3
@@ -0,0 +1,79 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+ from SeleniumLibrary.errors import ElementNotFound
5
+
6
+ from cumulusci.robotframework.Salesforce import Salesforce
7
+
8
+
9
+ # _init_locators has a special code block
10
+ class TestSeleniumLibrary:
11
+ def test_init_locators(self):
12
+ """Verify that locators are initialized if not passed in"""
13
+ with mock.patch.object(Salesforce, "_init_locators"):
14
+ # _init_locators should NOT be called if we pass them in
15
+ sflib = Salesforce(locators={"body": "//whatever"})
16
+ assert not sflib._init_locators.called
17
+
18
+ # _init_locators SHOULD be called if we don't pass them in
19
+ sflib = Salesforce()
20
+ sflib._init_locators.assert_called_once()
21
+
22
+
23
+ @mock.patch("robot.libraries.BuiltIn.BuiltIn._get_context")
24
+ class TestKeyword_wait_until_salesforce_is_ready:
25
+ @classmethod
26
+ def setup_class(cls):
27
+ cls.sflib = Salesforce(locators={"body": "//whatever"})
28
+
29
+ def test_successful_page_load(self, mock_robot_context):
30
+ """Verify that a succesful page load returns no errors"""
31
+ with mock.patch.object(Salesforce, "wait_for_aura", return_value=True):
32
+ self.sflib.wait_until_salesforce_is_ready(timeout="1")
33
+
34
+ self.sflib.wait_for_aura.assert_called_once()
35
+ self.sflib.selenium.get_webelement.assert_called_once_with("//whatever")
36
+
37
+ def test_reload_on_initial_failure(self, mock_robot_context):
38
+ """Verify that we attempt a reload when we don't find the lightning component"""
39
+ with mock.patch.object(Salesforce, "wait_for_aura", return_value=True):
40
+ with mock.patch.object(
41
+ Salesforce, "_check_for_classic", return_value=False
42
+ ):
43
+ with mock.patch.object(
44
+ Salesforce, "_check_for_login_failure", return_value=False
45
+ ):
46
+ with mock.patch.object(
47
+ self.sflib.selenium,
48
+ "get_webelement",
49
+ side_effect=(ElementNotFound(), True),
50
+ ):
51
+ self.sflib.wait_until_salesforce_is_ready(timeout="10")
52
+ self.sflib.selenium.go_to.assert_called_once()
53
+
54
+ def test_exception_and_screenshot_on_timeout(self, mock_robot_context):
55
+ """Verify that we throw an appropriate exception after the timeout"""
56
+ with mock.patch.object(Salesforce, "wait_for_aura", return_value=True):
57
+ self.sflib.selenium.get_webelement.side_effect = ElementNotFound()
58
+
59
+ with pytest.raises(
60
+ Exception, match="Timed out waiting for a lightning page"
61
+ ):
62
+ # The timeout needs to be longer than the duration of
63
+ # one loop iteration, but less than the retry interval
64
+ # of 5 seconds. Making it longer should still pass the
65
+ # test, it just makes the test run longer than necessary.
66
+ self.sflib.wait_until_salesforce_is_ready(timeout=0.1)
67
+
68
+ self.sflib.selenium.capture_page_screenshot.assert_called()
69
+
70
+
71
+ @mock.patch("robot.libraries.BuiltIn.BuiltIn._get_context")
72
+ class TestKeyword_breakpoint:
73
+ @classmethod
74
+ def setup_class(cls):
75
+ cls.sflib = Salesforce(locators={"body": "//whatever"})
76
+
77
+ def test_breakpoint(self, mock_robot_context):
78
+ """Verify that the keyword doesn't raise an exception"""
79
+ assert self.sflib.breakpoint() is None
@@ -0,0 +1,73 @@
1
+ from pathlib import Path
2
+ from unittest import mock
3
+
4
+ from robot.libraries.BuiltIn import RobotNotRunningError
5
+
6
+ from cumulusci.robotframework.Salesforce import Salesforce
7
+
8
+
9
+ # FIXME: we shouldn't have to tweak these tests for every
10
+ # version. The tests should be smarter.
11
+ class TestLocators:
12
+ @mock.patch(
13
+ "cumulusci.robotframework.SalesforceAPI.SalesforceAPI.get_latest_api_version"
14
+ )
15
+ def test_locators_in_robot_context(self, get_latest_api_version):
16
+ """Verify we can get locators for the current org api version"""
17
+ get_latest_api_version.return_value = 57.0
18
+
19
+ # This instantiates the robot library, mimicking a robot library import.
20
+ # We've mocked out the code that would otherwise throw an error since
21
+ # we're not running in the context of a robot test. The library should
22
+ # return the latest version of the locators.
23
+ sf = Salesforce()
24
+
25
+ expected = "cumulusci.robotframework.locators_57"
26
+ actual = sf.locators_module.__name__
27
+ message = "expected to load '{}', actually loaded '{}'".format(expected, actual)
28
+ assert expected == actual, message
29
+
30
+ @mock.patch(
31
+ "robot.libraries.BuiltIn.BuiltIn.get_library_instance",
32
+ side_effect=RobotNotRunningError(),
33
+ )
34
+ def test_locators_outside_robot_context(self, builtin_mock):
35
+ """Verify that we get the latest locators if not running in the context of a robot test"""
36
+
37
+ # This instantiates the robot library, mimicing a robot library import
38
+ # however, because we've mocked get_library_instance to throw an error,
39
+ # we expect the library to still be instantiated, but with the latest
40
+ # version of the locators.
41
+
42
+ sf = Salesforce()
43
+
44
+ locator_folder = Path("./cumulusci/robotframework")
45
+ locator_modules = sorted(locator_folder.glob("locators_[0-9][0-9].py"))
46
+ expected = f"cumulusci.robotframework.{locator_modules[-1].stem}"
47
+
48
+ actual = sf.locators_module.__name__
49
+ message = "expected to load '{}', actually loaded '{}'".format(expected, actual)
50
+ assert expected == actual, message
51
+
52
+ def test_locators_57(self):
53
+ """Verify that locators_57 is a superset of the locators_56
54
+
55
+ This test is far from perfect, but it should at least flag a
56
+ catastrophic error in how locators for a version that augments
57
+ the locators from previous versions.
58
+
59
+ Note: this test assumes that locators_56 doesn't delete any of the
60
+ keys from 54.
61
+
62
+ """
63
+ import cumulusci.robotframework.locators_56 as locators_56
64
+ import cumulusci.robotframework.locators_57 as locators_57
65
+
66
+ keys_56 = set(locators_56.lex_locators)
67
+ keys_57 = set(locators_57.lex_locators)
68
+
69
+ assert id(locators_56.lex_locators) != id(
70
+ locators_57.lex_locators
71
+ ), "locators_56.lex_locators and locators_57.lex_locators are the same object"
72
+ assert len(keys_56) > 0
73
+ assert keys_57.issubset(keys_56)