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.
- cumulusci/__about__.py +1 -0
- cumulusci/__init__.py +22 -0
- cumulusci/__main__.py +3 -0
- cumulusci/cli/__init__.py +0 -0
- cumulusci/cli/cci.py +244 -0
- cumulusci/cli/error.py +125 -0
- cumulusci/cli/flow.py +185 -0
- cumulusci/cli/logger.py +72 -0
- cumulusci/cli/org.py +692 -0
- cumulusci/cli/plan.py +181 -0
- cumulusci/cli/project.py +391 -0
- cumulusci/cli/robot.py +116 -0
- cumulusci/cli/runtime.py +190 -0
- cumulusci/cli/service.py +521 -0
- cumulusci/cli/task.py +295 -0
- cumulusci/cli/tests/__init__.py +0 -0
- cumulusci/cli/tests/test_cci.py +545 -0
- cumulusci/cli/tests/test_error.py +170 -0
- cumulusci/cli/tests/test_flow.py +276 -0
- cumulusci/cli/tests/test_logger.py +25 -0
- cumulusci/cli/tests/test_org.py +1438 -0
- cumulusci/cli/tests/test_plan.py +245 -0
- cumulusci/cli/tests/test_project.py +235 -0
- cumulusci/cli/tests/test_robot.py +177 -0
- cumulusci/cli/tests/test_runtime.py +197 -0
- cumulusci/cli/tests/test_service.py +853 -0
- cumulusci/cli/tests/test_task.py +266 -0
- cumulusci/cli/tests/test_ui.py +310 -0
- cumulusci/cli/tests/test_utils.py +122 -0
- cumulusci/cli/tests/utils.py +52 -0
- cumulusci/cli/ui.py +234 -0
- cumulusci/cli/utils.py +150 -0
- cumulusci/conftest.py +181 -0
- cumulusci/core/__init__.py +0 -0
- cumulusci/core/config/BaseConfig.py +5 -0
- cumulusci/core/config/BaseTaskFlowConfig.py +5 -0
- cumulusci/core/config/OrgConfig.py +5 -0
- cumulusci/core/config/ScratchOrgConfig.py +5 -0
- cumulusci/core/config/__init__.py +125 -0
- cumulusci/core/config/base_config.py +111 -0
- cumulusci/core/config/base_task_flow_config.py +82 -0
- cumulusci/core/config/marketing_cloud_service_config.py +83 -0
- cumulusci/core/config/oauth2_service_config.py +17 -0
- cumulusci/core/config/org_config.py +604 -0
- cumulusci/core/config/project_config.py +782 -0
- cumulusci/core/config/scratch_org_config.py +251 -0
- cumulusci/core/config/sfdx_org_config.py +220 -0
- cumulusci/core/config/tests/_test_config_backwards_compatibility.py +33 -0
- cumulusci/core/config/tests/test_config.py +1895 -0
- cumulusci/core/config/tests/test_config_expensive.py +839 -0
- cumulusci/core/config/tests/test_config_util.py +91 -0
- cumulusci/core/config/universal_config.py +88 -0
- cumulusci/core/config/util.py +18 -0
- cumulusci/core/datasets.py +303 -0
- cumulusci/core/debug.py +33 -0
- cumulusci/core/dependencies/__init__.py +55 -0
- cumulusci/core/dependencies/base.py +561 -0
- cumulusci/core/dependencies/dependencies.py +273 -0
- cumulusci/core/dependencies/github.py +177 -0
- cumulusci/core/dependencies/github_resolvers.py +244 -0
- cumulusci/core/dependencies/resolvers.py +580 -0
- cumulusci/core/dependencies/tests/__init__.py +0 -0
- cumulusci/core/dependencies/tests/conftest.py +385 -0
- cumulusci/core/dependencies/tests/test_dependencies.py +950 -0
- cumulusci/core/dependencies/tests/test_github.py +83 -0
- cumulusci/core/dependencies/tests/test_resolvers.py +1027 -0
- cumulusci/core/dependencies/utils.py +13 -0
- cumulusci/core/enums.py +11 -0
- cumulusci/core/exceptions.py +311 -0
- cumulusci/core/flowrunner.py +888 -0
- cumulusci/core/github.py +665 -0
- cumulusci/core/keychain/__init__.py +24 -0
- cumulusci/core/keychain/base_project_keychain.py +441 -0
- cumulusci/core/keychain/encrypted_file_project_keychain.py +945 -0
- cumulusci/core/keychain/environment_project_keychain.py +7 -0
- cumulusci/core/keychain/serialization.py +152 -0
- cumulusci/core/keychain/subprocess_keychain.py +24 -0
- cumulusci/core/keychain/tests/conftest.py +50 -0
- cumulusci/core/keychain/tests/test_base_project_keychain.py +299 -0
- cumulusci/core/keychain/tests/test_encrypted_file_project_keychain.py +1228 -0
- cumulusci/core/metadeploy/__init__.py +0 -0
- cumulusci/core/metadeploy/api.py +88 -0
- cumulusci/core/metadeploy/plans.py +25 -0
- cumulusci/core/metadeploy/tests/test_api.py +276 -0
- cumulusci/core/runtime.py +115 -0
- cumulusci/core/sfdx.py +162 -0
- cumulusci/core/source/__init__.py +16 -0
- cumulusci/core/source/github.py +50 -0
- cumulusci/core/source/local_folder.py +35 -0
- cumulusci/core/source_transforms/__init__.py +0 -0
- cumulusci/core/source_transforms/tests/test_transforms.py +1091 -0
- cumulusci/core/source_transforms/transforms.py +532 -0
- cumulusci/core/tasks.py +404 -0
- cumulusci/core/template_utils.py +59 -0
- cumulusci/core/tests/__init__.py +0 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_e2e.yaml +215 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_extract_standard_objects.yaml +199 -0
- cumulusci/core/tests/cassettes/TestDatasetsE2E.test_datasets_read_explicit_extract_declaration.yaml +3 -0
- cumulusci/core/tests/fake_remote_repo/cumulusci.yml +32 -0
- cumulusci/core/tests/fake_remote_repo/tasks/directory/example_2.py +6 -0
- cumulusci/core/tests/fake_remote_repo/tasks/example.py +43 -0
- cumulusci/core/tests/fake_remote_repo_2/cumulusci.yml +11 -0
- cumulusci/core/tests/fake_remote_repo_2/tasks/example_3.py +6 -0
- cumulusci/core/tests/test_datasets_e2e.py +386 -0
- cumulusci/core/tests/test_exceptions.py +11 -0
- cumulusci/core/tests/test_flowrunner.py +836 -0
- cumulusci/core/tests/test_github.py +942 -0
- cumulusci/core/tests/test_sfdx.py +138 -0
- cumulusci/core/tests/test_source.py +678 -0
- cumulusci/core/tests/test_tasks.py +262 -0
- cumulusci/core/tests/test_utils.py +141 -0
- cumulusci/core/tests/test_utils_merge_config.py +276 -0
- cumulusci/core/tests/test_versions.py +76 -0
- cumulusci/core/tests/untrusted_repo_child/cumulusci.yml +7 -0
- cumulusci/core/tests/untrusted_repo_child/tasks/untrusted_child.py +6 -0
- cumulusci/core/tests/untrusted_repo_parent/cumulusci.yml +26 -0
- cumulusci/core/tests/untrusted_repo_parent/tasks/untrusted_parent.py +6 -0
- cumulusci/core/tests/utils.py +116 -0
- cumulusci/core/tests/yaml/global.yaml +0 -0
- cumulusci/core/utils.py +402 -0
- cumulusci/core/versions.py +149 -0
- cumulusci/cumulusci.yml +1621 -0
- cumulusci/files/admin_profile.xml +20 -0
- cumulusci/files/delete_excludes.txt +424 -0
- cumulusci/files/templates/project/README.md +12 -0
- cumulusci/files/templates/project/cumulusci.yml +63 -0
- cumulusci/files/templates/project/dot-gitignore +60 -0
- cumulusci/files/templates/project/mapping.yml +45 -0
- cumulusci/files/templates/project/scratch_def.json +25 -0
- cumulusci/oauth/__init__.py +0 -0
- cumulusci/oauth/client.py +400 -0
- cumulusci/oauth/exceptions.py +9 -0
- cumulusci/oauth/salesforce.py +95 -0
- cumulusci/oauth/tests/__init__.py +0 -0
- cumulusci/oauth/tests/cassettes/test_get_device_code.yaml +22 -0
- cumulusci/oauth/tests/cassettes/test_get_device_oauth_token.yaml +74 -0
- cumulusci/oauth/tests/test_client.py +308 -0
- cumulusci/oauth/tests/test_salesforce.py +46 -0
- cumulusci/plugins/__init__.py +3 -0
- cumulusci/plugins/plugin_base.py +93 -0
- cumulusci/plugins/plugin_loader.py +59 -0
- cumulusci/robotframework/CumulusCI.py +340 -0
- cumulusci/robotframework/CumulusCI.robot +7 -0
- cumulusci/robotframework/Performance.py +165 -0
- cumulusci/robotframework/Salesforce.py +936 -0
- cumulusci/robotframework/Salesforce.robot +192 -0
- cumulusci/robotframework/SalesforceAPI.py +416 -0
- cumulusci/robotframework/SalesforcePlaywright.py +220 -0
- cumulusci/robotframework/SalesforcePlaywright.robot +40 -0
- cumulusci/robotframework/__init__.py +2 -0
- cumulusci/robotframework/base_library.py +39 -0
- cumulusci/robotframework/faker_mixin.py +89 -0
- cumulusci/robotframework/form_handlers.py +222 -0
- cumulusci/robotframework/javascript/cci_init.js +34 -0
- cumulusci/robotframework/javascript/cumulusci.js +4 -0
- cumulusci/robotframework/locator_manager.py +197 -0
- cumulusci/robotframework/locators_56.py +88 -0
- cumulusci/robotframework/locators_57.py +5 -0
- cumulusci/robotframework/pageobjects/BasePageObjects.py +433 -0
- cumulusci/robotframework/pageobjects/ObjectManagerPageObject.py +246 -0
- cumulusci/robotframework/pageobjects/PageObjectLibrary.py +45 -0
- cumulusci/robotframework/pageobjects/PageObjects.py +351 -0
- cumulusci/robotframework/pageobjects/__init__.py +12 -0
- cumulusci/robotframework/pageobjects/baseobjects.py +120 -0
- cumulusci/robotframework/perftests/short/collection_perf.robot +105 -0
- cumulusci/robotframework/tests/CustomObjectTestPage.py +10 -0
- cumulusci/robotframework/tests/FooTestPage.py +8 -0
- cumulusci/robotframework/tests/cumulusci/base.robot +40 -0
- cumulusci/robotframework/tests/cumulusci/bulkdata.robot +38 -0
- cumulusci/robotframework/tests/cumulusci/communities.robot +57 -0
- cumulusci/robotframework/tests/cumulusci/datagen.robot +84 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryA.py +24 -0
- cumulusci/robotframework/tests/salesforce/TestLibraryB.py +20 -0
- cumulusci/robotframework/tests/salesforce/TestListener.py +93 -0
- cumulusci/robotframework/tests/salesforce/api.robot +178 -0
- cumulusci/robotframework/tests/salesforce/browsers.robot +143 -0
- cumulusci/robotframework/tests/salesforce/classic.robot +51 -0
- cumulusci/robotframework/tests/salesforce/create_contact.robot +59 -0
- cumulusci/robotframework/tests/salesforce/faker.robot +68 -0
- cumulusci/robotframework/tests/salesforce/forms.robot +172 -0
- cumulusci/robotframework/tests/salesforce/label_locator.robot +244 -0
- cumulusci/robotframework/tests/salesforce/labels.html +33 -0
- cumulusci/robotframework/tests/salesforce/locators.robot +149 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/base_pageobjects.robot +100 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/example_page_object.py +25 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/listing_page.robot +115 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/objectmanager.robot +74 -0
- cumulusci/robotframework/tests/salesforce/pageobjects/pageobjects.robot +171 -0
- cumulusci/robotframework/tests/salesforce/performance.robot +109 -0
- cumulusci/robotframework/tests/salesforce/playwright/javascript_keywords.robot +33 -0
- cumulusci/robotframework/tests/salesforce/playwright/open_test_browser.robot +48 -0
- cumulusci/robotframework/tests/salesforce/playwright/playwright.robot +24 -0
- cumulusci/robotframework/tests/salesforce/playwright/ui.robot +32 -0
- cumulusci/robotframework/tests/salesforce/populate.robot +89 -0
- cumulusci/robotframework/tests/salesforce/test_testlistener.py +37 -0
- cumulusci/robotframework/tests/salesforce/ui.robot +361 -0
- cumulusci/robotframework/tests/test_cumulusci_library.py +304 -0
- cumulusci/robotframework/tests/test_locator_manager.py +158 -0
- cumulusci/robotframework/tests/test_pageobjects.py +291 -0
- cumulusci/robotframework/tests/test_performance.py +38 -0
- cumulusci/robotframework/tests/test_salesforce.py +79 -0
- cumulusci/robotframework/tests/test_salesforce_locators.py +73 -0
- cumulusci/robotframework/tests/test_template_util.py +53 -0
- cumulusci/robotframework/tests/test_utils.py +106 -0
- cumulusci/robotframework/utils.py +283 -0
- cumulusci/salesforce_api/__init__.py +0 -0
- cumulusci/salesforce_api/exceptions.py +23 -0
- cumulusci/salesforce_api/filterable_objects.py +96 -0
- cumulusci/salesforce_api/mc_soap_envelopes.py +89 -0
- cumulusci/salesforce_api/metadata.py +721 -0
- cumulusci/salesforce_api/org_schema.py +571 -0
- cumulusci/salesforce_api/org_schema_models.py +226 -0
- cumulusci/salesforce_api/package_install.py +265 -0
- cumulusci/salesforce_api/package_zip.py +301 -0
- cumulusci/salesforce_api/rest_deploy.py +148 -0
- cumulusci/salesforce_api/retrieve_profile_api.py +301 -0
- cumulusci/salesforce_api/soap_envelopes.py +177 -0
- cumulusci/salesforce_api/tests/__init__.py +0 -0
- cumulusci/salesforce_api/tests/metadata_test_strings.py +24 -0
- cumulusci/salesforce_api/tests/test_metadata.py +1015 -0
- cumulusci/salesforce_api/tests/test_package_install.py +219 -0
- cumulusci/salesforce_api/tests/test_package_zip.py +380 -0
- cumulusci/salesforce_api/tests/test_rest_deploy.py +264 -0
- cumulusci/salesforce_api/tests/test_retrieve_profile_api.py +337 -0
- cumulusci/salesforce_api/tests/test_utils.py +124 -0
- cumulusci/salesforce_api/utils.py +51 -0
- cumulusci/schema/cumulusci.jsonschema.json +782 -0
- cumulusci/tasks/__init__.py +0 -0
- cumulusci/tasks/apex/__init__.py +0 -0
- cumulusci/tasks/apex/anon.py +157 -0
- cumulusci/tasks/apex/batch.py +180 -0
- cumulusci/tasks/apex/testrunner.py +835 -0
- cumulusci/tasks/apex/tests/cassettes/ManualEditTestApexIntegrationTests.test_run_tests__integration_test.yaml +703 -0
- cumulusci/tasks/apex/tests/test_apex_tasks.py +1558 -0
- cumulusci/tasks/base_source_control_task.py +17 -0
- cumulusci/tasks/bulkdata/__init__.py +15 -0
- cumulusci/tasks/bulkdata/base_generate_data_task.py +96 -0
- cumulusci/tasks/bulkdata/dates.py +97 -0
- cumulusci/tasks/bulkdata/delete.py +156 -0
- cumulusci/tasks/bulkdata/extract.py +441 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/calculate_dependencies.py +117 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/extract_yml.py +123 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/hardcoded_default_declarations.py +49 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/synthesize_extract_declarations.py +283 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_extract_yml.py +142 -0
- cumulusci/tasks/bulkdata/extract_dataset_utils/tests/test_synthesize_extract_declarations.py +575 -0
- cumulusci/tasks/bulkdata/factory_utils.py +134 -0
- cumulusci/tasks/bulkdata/generate.py +4 -0
- cumulusci/tasks/bulkdata/generate_and_load_data.py +232 -0
- cumulusci/tasks/bulkdata/generate_and_load_data_from_yaml.py +19 -0
- cumulusci/tasks/bulkdata/generate_from_yaml.py +183 -0
- cumulusci/tasks/bulkdata/generate_mapping.py +434 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/dependency_map.py +169 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/extract_mapping_file_generator.py +45 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/generate_mapping_from_declarations.py +121 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/load_mapping_file_generator.py +127 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_generator_post_processes.py +53 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/mapping_transforms.py +139 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_extract_mapping_from_declarations.py +135 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_generate_load_mapping_from_declarations.py +330 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_generator_post_processes.py +60 -0
- cumulusci/tasks/bulkdata/generate_mapping_utils/tests/test_mapping_transforms.py +188 -0
- cumulusci/tasks/bulkdata/load.py +1196 -0
- cumulusci/tasks/bulkdata/mapping_parser.py +811 -0
- cumulusci/tasks/bulkdata/query_transformers.py +264 -0
- cumulusci/tasks/bulkdata/select_utils.py +792 -0
- cumulusci/tasks/bulkdata/snowfakery.py +753 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/queue_manager.py +478 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_run_until.py +141 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/snowfakery_working_directory.py +53 -0
- cumulusci/tasks/bulkdata/snowfakery_utils/subtask_configurator.py +64 -0
- cumulusci/tasks/bulkdata/step.py +1242 -0
- cumulusci/tasks/bulkdata/tests/__init__.py +0 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_random_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_annoy_strategy.yaml +123 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy.yaml +313 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_select_and_insert_strategy_bulk.yaml +550 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_similarity_strategy.yaml +175 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSelect.test_select_standard_strategy.yaml +147 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__multiple_needed.yaml +69 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__none_needed.yaml +22 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_run_until_records_in_org__one_needed.yaml +24 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestSnowfakery.test_snowfakery_query_salesforce.yaml +25 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpdatesIntegrationTests.test_updates_task.yaml +80 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_simple_upsert__rest.yaml +270 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert__rest.yaml +267 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field__rest.yaml +369 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_external_id_field_rest__duplicate_error.yaml +204 -0
- cumulusci/tasks/bulkdata/tests/cassettes/TestUpsert.test_upsert_complex_fields__bulk.yaml +675 -0
- cumulusci/tasks/bulkdata/tests/dummy_data_factory.py +36 -0
- cumulusci/tasks/bulkdata/tests/integration_test_utils.py +49 -0
- cumulusci/tasks/bulkdata/tests/mapping-oid.yml +87 -0
- cumulusci/tasks/bulkdata/tests/mapping_after.yml +38 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly.yml +34 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_incomplete.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_poly_wrong.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_strategy.yml +20 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_number.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__invalid_strategy.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_invalid_threshold__non_float.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_missing_priority_fields.yml +22 -0
- cumulusci/tasks/bulkdata/tests/mapping_select_no_priority_fields.yml +18 -0
- cumulusci/tasks/bulkdata/tests/mapping_simple.yml +27 -0
- cumulusci/tasks/bulkdata/tests/mapping_v1.yml +28 -0
- cumulusci/tasks/bulkdata/tests/mapping_v2.yml +21 -0
- cumulusci/tasks/bulkdata/tests/mapping_v3.yml +32 -0
- cumulusci/tasks/bulkdata/tests/mapping_vanilla_sf.yml +69 -0
- cumulusci/tasks/bulkdata/tests/mock_data_factory_without_mapping.py +12 -0
- cumulusci/tasks/bulkdata/tests/person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/person_accounts_minimal.yml +15 -0
- cumulusci/tasks/bulkdata/tests/recordtypes.yml +8 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_2.yml +6 -0
- cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml +8 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child/child2.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/child.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/gen_npsp_standard_objects.recipe.yml +89 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/include_parent.yml +3 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/npsp_standard_objects_macros.yml +34 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/options.recipe.yml +6 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/query_snowfakery.recipe.yml +16 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/sf_standard_object_macros.yml +83 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.load.yml +2 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery.recipe.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_2.load.yml +5 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels.recipe.yml +12 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/simple_snowfakery_channels_2.load.yml +13 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/unique_values.recipe.yml +4 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert.recipe.yml +23 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_2.recipe.yml +29 -0
- cumulusci/tasks/bulkdata/tests/snowfakery/upsert_before.yml +10 -0
- cumulusci/tasks/bulkdata/tests/test_base_generate_data_tasks.py +61 -0
- cumulusci/tasks/bulkdata/tests/test_dates.py +99 -0
- cumulusci/tasks/bulkdata/tests/test_delete.py +404 -0
- cumulusci/tasks/bulkdata/tests/test_extract.py +1311 -0
- cumulusci/tasks/bulkdata/tests/test_factory_utils.py +55 -0
- cumulusci/tasks/bulkdata/tests/test_generate_and_load.py +252 -0
- cumulusci/tasks/bulkdata/tests/test_generate_from_snowfakery_task.py +343 -0
- cumulusci/tasks/bulkdata/tests/test_generatemapping.py +1039 -0
- cumulusci/tasks/bulkdata/tests/test_load.py +3175 -0
- cumulusci/tasks/bulkdata/tests/test_mapping_parser.py +1658 -0
- cumulusci/tasks/bulkdata/tests/test_query_db__joins_self_lookups.yml +12 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups.yml +26 -0
- cumulusci/tasks/bulkdata/tests/test_query_db_joins_lookups_select.yml +48 -0
- cumulusci/tasks/bulkdata/tests/test_select.py +171 -0
- cumulusci/tasks/bulkdata/tests/test_select_utils.py +1057 -0
- cumulusci/tasks/bulkdata/tests/test_snowfakery.py +1153 -0
- cumulusci/tasks/bulkdata/tests/test_step.py +3957 -0
- cumulusci/tasks/bulkdata/tests/test_updates.py +513 -0
- cumulusci/tasks/bulkdata/tests/test_upsert.py +1015 -0
- cumulusci/tasks/bulkdata/tests/test_utils.py +158 -0
- cumulusci/tasks/bulkdata/tests/testdata.db +0 -0
- cumulusci/tasks/bulkdata/tests/update_describe.py +50 -0
- cumulusci/tasks/bulkdata/tests/update_person_accounts.yml +23 -0
- cumulusci/tasks/bulkdata/tests/utils.py +114 -0
- cumulusci/tasks/bulkdata/update_data.py +260 -0
- cumulusci/tasks/bulkdata/upsert_utils.py +130 -0
- cumulusci/tasks/bulkdata/utils.py +249 -0
- cumulusci/tasks/command.py +178 -0
- cumulusci/tasks/connectedapp.py +186 -0
- cumulusci/tasks/create_package_version.py +778 -0
- cumulusci/tasks/datadictionary.py +745 -0
- cumulusci/tasks/dx_convert_from.py +26 -0
- cumulusci/tasks/github/__init__.py +17 -0
- cumulusci/tasks/github/base.py +16 -0
- cumulusci/tasks/github/commit_status.py +13 -0
- cumulusci/tasks/github/merge.py +11 -0
- cumulusci/tasks/github/publish.py +11 -0
- cumulusci/tasks/github/pull_request.py +11 -0
- cumulusci/tasks/github/release.py +11 -0
- cumulusci/tasks/github/release_report.py +11 -0
- cumulusci/tasks/github/tag.py +11 -0
- cumulusci/tasks/github/tests/__init__.py +0 -0
- cumulusci/tasks/github/tests/test_util.py +202 -0
- cumulusci/tasks/github/tests/test_vcs_migration.py +44 -0
- cumulusci/tasks/github/tests/util_github_api.py +666 -0
- cumulusci/tasks/github/util.py +252 -0
- cumulusci/tasks/marketing_cloud/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/api.py +188 -0
- cumulusci/tasks/marketing_cloud/base.py +38 -0
- cumulusci/tasks/marketing_cloud/deploy.py +345 -0
- cumulusci/tasks/marketing_cloud/get_user_info.py +40 -0
- cumulusci/tasks/marketing_cloud/mc_constants.py +1 -0
- cumulusci/tasks/marketing_cloud/tests/__init__.py +0 -0
- cumulusci/tasks/marketing_cloud/tests/conftest.py +46 -0
- cumulusci/tasks/marketing_cloud/tests/expected-payload.json +110 -0
- cumulusci/tasks/marketing_cloud/tests/test_api.py +97 -0
- cumulusci/tasks/marketing_cloud/tests/test_api_soap_envelopes.py +145 -0
- cumulusci/tasks/marketing_cloud/tests/test_base.py +14 -0
- cumulusci/tasks/marketing_cloud/tests/test_deploy.py +400 -0
- cumulusci/tasks/marketing_cloud/tests/test_get_user_info.py +141 -0
- cumulusci/tasks/marketing_cloud/tests/validation-response.json +39 -0
- cumulusci/tasks/metadata/__init__.py +0 -0
- cumulusci/tasks/metadata/ee_src.py +94 -0
- cumulusci/tasks/metadata/managed_src.py +100 -0
- cumulusci/tasks/metadata/metadata_map.yml +868 -0
- cumulusci/tasks/metadata/modify.py +99 -0
- cumulusci/tasks/metadata/package.py +684 -0
- cumulusci/tasks/metadata/tests/__init__.py +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/.hidden/.keep +0 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/destructiveChanges.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package.xml +9 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/package_install_uninstall.xml +11 -0
- cumulusci/tasks/metadata/tests/package_metadata/namespaced_report_folder/reports/namespace__TestFolder/TestReport.report +3 -0
- cumulusci/tasks/metadata/tests/sample_package.xml +9 -0
- cumulusci/tasks/metadata/tests/test_ee_src.py +112 -0
- cumulusci/tasks/metadata/tests/test_managed_src.py +111 -0
- cumulusci/tasks/metadata/tests/test_modify.py +123 -0
- cumulusci/tasks/metadata/tests/test_package.py +476 -0
- cumulusci/tasks/metadata_etl/__init__.py +29 -0
- cumulusci/tasks/metadata_etl/base.py +436 -0
- cumulusci/tasks/metadata_etl/duplicate_rules.py +24 -0
- cumulusci/tasks/metadata_etl/field_sets.py +70 -0
- cumulusci/tasks/metadata_etl/help_text.py +92 -0
- cumulusci/tasks/metadata_etl/layouts.py +550 -0
- cumulusci/tasks/metadata_etl/objects.py +68 -0
- cumulusci/tasks/metadata_etl/permissions.py +167 -0
- cumulusci/tasks/metadata_etl/picklists.py +221 -0
- cumulusci/tasks/metadata_etl/remote_site_settings.py +99 -0
- cumulusci/tasks/metadata_etl/sharing.py +138 -0
- cumulusci/tasks/metadata_etl/tests/test_base.py +512 -0
- cumulusci/tasks/metadata_etl/tests/test_duplicate_rules.py +22 -0
- cumulusci/tasks/metadata_etl/tests/test_field_sets.py +156 -0
- cumulusci/tasks/metadata_etl/tests/test_help_text.py +387 -0
- cumulusci/tasks/metadata_etl/tests/test_ip_ranges.py +85 -0
- cumulusci/tasks/metadata_etl/tests/test_layouts.py +858 -0
- cumulusci/tasks/metadata_etl/tests/test_objects.py +236 -0
- cumulusci/tasks/metadata_etl/tests/test_permissions.py +223 -0
- cumulusci/tasks/metadata_etl/tests/test_picklists.py +547 -0
- cumulusci/tasks/metadata_etl/tests/test_remote_site_settings.py +46 -0
- cumulusci/tasks/metadata_etl/tests/test_sharing.py +333 -0
- cumulusci/tasks/metadata_etl/tests/test_value_sets.py +298 -0
- cumulusci/tasks/metadata_etl/value_sets.py +106 -0
- cumulusci/tasks/metadeploy.py +393 -0
- cumulusci/tasks/metaxml.py +88 -0
- cumulusci/tasks/preflight/__init__.py +0 -0
- cumulusci/tasks/preflight/dataset_load.py +49 -0
- cumulusci/tasks/preflight/licenses.py +86 -0
- cumulusci/tasks/preflight/packages.py +14 -0
- cumulusci/tasks/preflight/permsets.py +23 -0
- cumulusci/tasks/preflight/recordtypes.py +16 -0
- cumulusci/tasks/preflight/retrieve_tasks.py +30 -0
- cumulusci/tasks/preflight/settings.py +77 -0
- cumulusci/tasks/preflight/sobjects.py +202 -0
- cumulusci/tasks/preflight/tests/test_dataset_load.py +85 -0
- cumulusci/tasks/preflight/tests/test_licenses.py +174 -0
- cumulusci/tasks/preflight/tests/test_packages.py +14 -0
- cumulusci/tasks/preflight/tests/test_permset_preflights.py +51 -0
- cumulusci/tasks/preflight/tests/test_recordtypes.py +30 -0
- cumulusci/tasks/preflight/tests/test_retrieve_tasks.py +62 -0
- cumulusci/tasks/preflight/tests/test_settings.py +130 -0
- cumulusci/tasks/preflight/tests/test_sobjects.py +231 -0
- cumulusci/tasks/push/README.md +59 -0
- cumulusci/tasks/push/__init__.py +0 -0
- cumulusci/tasks/push/push_api.py +659 -0
- cumulusci/tasks/push/pushfails.py +136 -0
- cumulusci/tasks/push/tasks.py +476 -0
- cumulusci/tasks/push/tests/conftest.py +263 -0
- cumulusci/tasks/push/tests/test_push_api.py +951 -0
- cumulusci/tasks/push/tests/test_push_tasks.py +659 -0
- cumulusci/tasks/release_notes/README.md +63 -0
- cumulusci/tasks/release_notes/__init__.py +0 -0
- cumulusci/tasks/release_notes/exceptions.py +5 -0
- cumulusci/tasks/release_notes/generator.py +137 -0
- cumulusci/tasks/release_notes/parser.py +232 -0
- cumulusci/tasks/release_notes/provider.py +44 -0
- cumulusci/tasks/release_notes/task.py +300 -0
- cumulusci/tasks/release_notes/tests/__init__.py +0 -0
- cumulusci/tasks/release_notes/tests/change_notes/full/example1.md +17 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/2.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/multi/3.txt +1 -0
- cumulusci/tasks/release_notes/tests/change_notes/single/1.txt +1 -0
- cumulusci/tasks/release_notes/tests/test_generator.py +582 -0
- cumulusci/tasks/release_notes/tests/test_parser.py +867 -0
- cumulusci/tasks/release_notes/tests/test_provider.py +512 -0
- cumulusci/tasks/release_notes/tests/test_task.py +461 -0
- cumulusci/tasks/release_notes/tests/utils.py +153 -0
- cumulusci/tasks/robotframework/__init__.py +3 -0
- cumulusci/tasks/robotframework/debugger/DebugListener.py +100 -0
- cumulusci/tasks/robotframework/debugger/__init__.py +10 -0
- cumulusci/tasks/robotframework/debugger/model.py +87 -0
- cumulusci/tasks/robotframework/debugger/ui.py +259 -0
- cumulusci/tasks/robotframework/libdoc.py +269 -0
- cumulusci/tasks/robotframework/robotframework.py +392 -0
- cumulusci/tasks/robotframework/stylesheet.css +130 -0
- cumulusci/tasks/robotframework/template.html +109 -0
- cumulusci/tasks/robotframework/tests/TestLibrary.py +18 -0
- cumulusci/tasks/robotframework/tests/TestPageObjects.py +31 -0
- cumulusci/tasks/robotframework/tests/TestResource.robot +8 -0
- cumulusci/tasks/robotframework/tests/failing_tests.robot +16 -0
- cumulusci/tasks/robotframework/tests/performance.robot +23 -0
- cumulusci/tasks/robotframework/tests/test_browser_proxies.py +137 -0
- cumulusci/tasks/robotframework/tests/test_debugger.py +360 -0
- cumulusci/tasks/robotframework/tests/test_robot_parallel.py +141 -0
- cumulusci/tasks/robotframework/tests/test_robotframework.py +860 -0
- cumulusci/tasks/salesforce/BaseRetrieveMetadata.py +58 -0
- cumulusci/tasks/salesforce/BaseSalesforceApiTask.py +45 -0
- cumulusci/tasks/salesforce/BaseSalesforceMetadataApiTask.py +18 -0
- cumulusci/tasks/salesforce/BaseSalesforceTask.py +4 -0
- cumulusci/tasks/salesforce/BaseUninstallMetadata.py +41 -0
- cumulusci/tasks/salesforce/CreateCommunity.py +124 -0
- cumulusci/tasks/salesforce/CreatePackage.py +29 -0
- cumulusci/tasks/salesforce/Deploy.py +240 -0
- cumulusci/tasks/salesforce/DeployBundles.py +88 -0
- cumulusci/tasks/salesforce/DescribeMetadataTypes.py +26 -0
- cumulusci/tasks/salesforce/EnsureRecordTypes.py +202 -0
- cumulusci/tasks/salesforce/GetInstalledPackages.py +8 -0
- cumulusci/tasks/salesforce/ListCommunities.py +40 -0
- cumulusci/tasks/salesforce/ListCommunityTemplates.py +19 -0
- cumulusci/tasks/salesforce/PublishCommunity.py +62 -0
- cumulusci/tasks/salesforce/RetrievePackaged.py +41 -0
- cumulusci/tasks/salesforce/RetrieveReportsAndDashboards.py +82 -0
- cumulusci/tasks/salesforce/RetrieveUnpackaged.py +36 -0
- cumulusci/tasks/salesforce/SOQLQuery.py +39 -0
- cumulusci/tasks/salesforce/UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/UninstallLocalBundles.py +28 -0
- cumulusci/tasks/salesforce/UninstallLocalNamespacedBundles.py +58 -0
- cumulusci/tasks/salesforce/UninstallPackage.py +32 -0
- cumulusci/tasks/salesforce/UninstallPackaged.py +56 -0
- cumulusci/tasks/salesforce/UpdateAdminProfile.py +8 -0
- cumulusci/tasks/salesforce/__init__.py +79 -0
- cumulusci/tasks/salesforce/activate_flow.py +74 -0
- cumulusci/tasks/salesforce/check_components.py +324 -0
- cumulusci/tasks/salesforce/composite.py +142 -0
- cumulusci/tasks/salesforce/create_permission_sets.py +35 -0
- cumulusci/tasks/salesforce/custom_settings.py +134 -0
- cumulusci/tasks/salesforce/custom_settings_wait.py +132 -0
- cumulusci/tasks/salesforce/enable_prediction.py +107 -0
- cumulusci/tasks/salesforce/insert_record.py +40 -0
- cumulusci/tasks/salesforce/install_package_version.py +242 -0
- cumulusci/tasks/salesforce/license_preflights.py +8 -0
- cumulusci/tasks/salesforce/network_member_group.py +178 -0
- cumulusci/tasks/salesforce/nonsourcetracking.py +228 -0
- cumulusci/tasks/salesforce/org_settings.py +193 -0
- cumulusci/tasks/salesforce/package_upload.py +328 -0
- cumulusci/tasks/salesforce/profiles.py +74 -0
- cumulusci/tasks/salesforce/promote_package_version.py +376 -0
- cumulusci/tasks/salesforce/retrieve_profile.py +195 -0
- cumulusci/tasks/salesforce/salesforce_files.py +244 -0
- cumulusci/tasks/salesforce/sourcetracking.py +507 -0
- cumulusci/tasks/salesforce/tests/__init__.py +3 -0
- cumulusci/tasks/salesforce/tests/test_CreateCommunity.py +278 -0
- cumulusci/tasks/salesforce/tests/test_CreatePackage.py +22 -0
- cumulusci/tasks/salesforce/tests/test_Deploy.py +470 -0
- cumulusci/tasks/salesforce/tests/test_DeployBundles.py +76 -0
- cumulusci/tasks/salesforce/tests/test_EnsureRecordTypes.py +345 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunities.py +84 -0
- cumulusci/tasks/salesforce/tests/test_ListCommunityTemplates.py +49 -0
- cumulusci/tasks/salesforce/tests/test_PackageUpload.py +547 -0
- cumulusci/tasks/salesforce/tests/test_ProfileGrantAllAccess.py +699 -0
- cumulusci/tasks/salesforce/tests/test_PublishCommunity.py +181 -0
- cumulusci/tasks/salesforce/tests/test_RetrievePackaged.py +24 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveReportsAndDashboards.py +56 -0
- cumulusci/tasks/salesforce/tests/test_RetrieveUnpackaged.py +21 -0
- cumulusci/tasks/salesforce/tests/test_SOQLQuery.py +30 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocal.py +15 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalBundles.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallLocalNamespacedBundles.py +22 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackage.py +19 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackaged.py +66 -0
- cumulusci/tasks/salesforce/tests/test_UninstallPackagedIncremental.py +127 -0
- cumulusci/tasks/salesforce/tests/test_activate_flow.py +132 -0
- cumulusci/tasks/salesforce/tests/test_base_tasks.py +110 -0
- cumulusci/tasks/salesforce/tests/test_check_components.py +445 -0
- cumulusci/tasks/salesforce/tests/test_composite.py +250 -0
- cumulusci/tasks/salesforce/tests/test_create_permission_sets.py +41 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings.py +227 -0
- cumulusci/tasks/salesforce/tests/test_custom_settings_wait.py +174 -0
- cumulusci/tasks/salesforce/tests/test_describemetadatatypes.py +18 -0
- cumulusci/tasks/salesforce/tests/test_enable_prediction.py +240 -0
- cumulusci/tasks/salesforce/tests/test_insert_record.py +110 -0
- cumulusci/tasks/salesforce/tests/test_install_package_version.py +464 -0
- cumulusci/tasks/salesforce/tests/test_network_member_group.py +444 -0
- cumulusci/tasks/salesforce/tests/test_nonsourcetracking.py +235 -0
- cumulusci/tasks/salesforce/tests/test_org_settings.py +407 -0
- cumulusci/tasks/salesforce/tests/test_profiles.py +202 -0
- cumulusci/tasks/salesforce/tests/test_retrieve_profile.py +287 -0
- cumulusci/tasks/salesforce/tests/test_salesforce_files.py +228 -0
- cumulusci/tasks/salesforce/tests/test_sourcetracking.py +350 -0
- cumulusci/tasks/salesforce/tests/test_trigger_handlers.py +300 -0
- cumulusci/tasks/salesforce/tests/test_update_dependencies.py +509 -0
- cumulusci/tasks/salesforce/tests/util.py +79 -0
- cumulusci/tasks/salesforce/trigger_handlers.py +119 -0
- cumulusci/tasks/salesforce/uninstall_packaged_incremental.py +136 -0
- cumulusci/tasks/salesforce/update_dependencies.py +290 -0
- cumulusci/tasks/salesforce/update_profile.py +339 -0
- cumulusci/tasks/salesforce/users/permsets.py +227 -0
- cumulusci/tasks/salesforce/users/photos.py +162 -0
- cumulusci/tasks/salesforce/users/tests/photo.mock.txt +1 -0
- cumulusci/tasks/salesforce/users/tests/test_permsets.py +950 -0
- cumulusci/tasks/salesforce/users/tests/test_photos.py +373 -0
- cumulusci/tasks/sample_data/capture_sample_data.py +77 -0
- cumulusci/tasks/sample_data/load_sample_data.py +85 -0
- cumulusci/tasks/sample_data/test_capture_sample_data.py +117 -0
- cumulusci/tasks/sample_data/test_load_sample_data.py +121 -0
- cumulusci/tasks/sfdx.py +83 -0
- cumulusci/tasks/tests/__init__.py +1 -0
- cumulusci/tasks/tests/conftest.py +30 -0
- cumulusci/tasks/tests/test_command.py +129 -0
- cumulusci/tasks/tests/test_connectedapp.py +236 -0
- cumulusci/tasks/tests/test_create_package_version.py +847 -0
- cumulusci/tasks/tests/test_datadictionary.py +1575 -0
- cumulusci/tasks/tests/test_dx_convert_from.py +60 -0
- cumulusci/tasks/tests/test_metadeploy.py +624 -0
- cumulusci/tasks/tests/test_metaxml.py +99 -0
- cumulusci/tasks/tests/test_promote_package_version.py +488 -0
- cumulusci/tasks/tests/test_pushfails.py +96 -0
- cumulusci/tasks/tests/test_salesforce.py +72 -0
- cumulusci/tasks/tests/test_sfdx.py +105 -0
- cumulusci/tasks/tests/test_util.py +207 -0
- cumulusci/tasks/util.py +261 -0
- cumulusci/tasks/vcs/__init__.py +19 -0
- cumulusci/tasks/vcs/commit_status.py +58 -0
- cumulusci/tasks/vcs/create_commit_status.py +37 -0
- cumulusci/tasks/vcs/download_extract.py +199 -0
- cumulusci/tasks/vcs/merge.py +298 -0
- cumulusci/tasks/vcs/publish.py +207 -0
- cumulusci/tasks/vcs/pull_request.py +9 -0
- cumulusci/tasks/vcs/release.py +134 -0
- cumulusci/tasks/vcs/release_report.py +105 -0
- cumulusci/tasks/vcs/tag.py +31 -0
- cumulusci/tasks/vcs/tests/github/test_commit_status.py +196 -0
- cumulusci/tasks/vcs/tests/github/test_download_extract.py +896 -0
- cumulusci/tasks/vcs/tests/github/test_merge.py +1118 -0
- cumulusci/tasks/vcs/tests/github/test_publish.py +823 -0
- cumulusci/tasks/vcs/tests/github/test_pull_request.py +29 -0
- cumulusci/tasks/vcs/tests/github/test_release.py +390 -0
- cumulusci/tasks/vcs/tests/github/test_release_report.py +109 -0
- cumulusci/tasks/vcs/tests/github/test_tag.py +90 -0
- cumulusci/tasks/vlocity/exceptions.py +2 -0
- cumulusci/tasks/vlocity/tests/test_vlocity.py +283 -0
- cumulusci/tasks/vlocity/vlocity.py +342 -0
- cumulusci/tests/__init__.py +1 -0
- cumulusci/tests/cassettes/GET_sobjects_Account_PersonAccount_describe.yaml +18 -0
- cumulusci/tests/cassettes/TestIntegrationInfrastructure.test_integration_tests.yaml +19 -0
- cumulusci/tests/pytest_plugins/pytest_sf_orgconnect.py +307 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr.py +275 -0
- cumulusci/tests/pytest_plugins/pytest_sf_vcr_serializer.py +160 -0
- cumulusci/tests/pytest_plugins/pytest_typeguard.py +5 -0
- cumulusci/tests/pytest_plugins/test_vcr_string_compressor.py +49 -0
- cumulusci/tests/pytest_plugins/vcr_string_compressor.py +97 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Account_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Case_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Contact_describe.yaml +4838 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Custom__c_describe.yaml +242 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Event_describe.yaml +19 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Global_describe.yaml +1338 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Lead_describe.yaml +18 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_OpportunityContactRole_describe.yaml +34 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Opportunity_describe.yaml +1261 -0
- cumulusci/tests/shared_cassettes/GET_sobjects_Organization.yaml +49 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfoList_xml.tpl +15 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/batchInfo_xml.tpl +13 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_insert_xml.tpl +24 -0
- cumulusci/tests/shared_cassettes/vcr_string_templates/jobInfo_upsert_xml.tpl +25 -0
- cumulusci/tests/test_entry_points.py +20 -0
- cumulusci/tests/test_integration_infrastructure.py +131 -0
- cumulusci/tests/test_main.py +9 -0
- cumulusci/tests/test_schema.py +32 -0
- cumulusci/tests/test_utils.py +657 -0
- cumulusci/tests/test_vcr_serializer.py +134 -0
- cumulusci/tests/uncompressed_cassette.yaml +83 -0
- cumulusci/tests/util.py +344 -0
- cumulusci/utils/__init__.py +731 -0
- cumulusci/utils/classutils.py +9 -0
- cumulusci/utils/collections.py +32 -0
- cumulusci/utils/deprecation.py +11 -0
- cumulusci/utils/encryption.py +31 -0
- cumulusci/utils/fileutils.py +295 -0
- cumulusci/utils/git.py +142 -0
- cumulusci/utils/http/multi_request.py +214 -0
- cumulusci/utils/http/requests_utils.py +103 -0
- cumulusci/utils/http/tests/cassettes/ManualEditTestCompositeParallelSalesforce.test_http_headers.yaml +32 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_composite_parallel_salesforce.yaml +65 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_errors.yaml +24 -0
- cumulusci/utils/http/tests/cassettes/TestCompositeParallelSalesforce.test_reference_ids.yaml +49 -0
- cumulusci/utils/http/tests/test_multi_request.py +255 -0
- cumulusci/utils/iterators.py +21 -0
- cumulusci/utils/logging.py +128 -0
- cumulusci/utils/metaprogramming.py +10 -0
- cumulusci/utils/options.py +138 -0
- cumulusci/utils/parallel/queries_in_parallel/run_queries_in_parallel.py +29 -0
- cumulusci/utils/parallel/queries_in_parallel/tests/test_run_queries_in_parallel.py +50 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker.py +238 -0
- cumulusci/utils/parallel/task_worker_queues/parallel_worker_queue.py +243 -0
- cumulusci/utils/parallel/task_worker_queues/tests/test_parallel_worker.py +353 -0
- cumulusci/utils/salesforce/count_sobjects.py +46 -0
- cumulusci/utils/salesforce/soql.py +17 -0
- cumulusci/utils/salesforce/tests/cassettes/ManualEdit_TestCountSObjects.test_count_sobjects__network_errors.yaml +23 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects__errors.yaml +33 -0
- cumulusci/utils/salesforce/tests/cassettes/TestCountSObjects.test_count_sobjects_simple.yaml +29 -0
- cumulusci/utils/salesforce/tests/test_count_sobjects.py +29 -0
- cumulusci/utils/salesforce/tests/test_soql.py +30 -0
- cumulusci/utils/tests/cassettes/ManualEditTestDescribeOrg.test_minimal_schema.yaml +36 -0
- cumulusci/utils/tests/cassettes/ManualEdit_test_describe_to_sql.yaml +191 -0
- cumulusci/utils/tests/test_fileutils.py +284 -0
- cumulusci/utils/tests/test_git.py +85 -0
- cumulusci/utils/tests/test_logging.py +70 -0
- cumulusci/utils/tests/test_option_parsing.py +188 -0
- cumulusci/utils/tests/test_org_schema.py +691 -0
- cumulusci/utils/tests/test_org_schema_models.py +79 -0
- cumulusci/utils/tests/test_waiting.py +25 -0
- cumulusci/utils/version_strings.py +391 -0
- cumulusci/utils/waiting.py +42 -0
- cumulusci/utils/xml/__init__.py +91 -0
- cumulusci/utils/xml/metadata_tree.py +299 -0
- cumulusci/utils/xml/robot_xml.py +114 -0
- cumulusci/utils/xml/salesforce_encoding.py +100 -0
- cumulusci/utils/xml/test/test_metadata_tree.py +251 -0
- cumulusci/utils/xml/test/test_salesforce_encoding.py +173 -0
- cumulusci/utils/yaml/cumulusci_yml.py +401 -0
- cumulusci/utils/yaml/model_parser.py +156 -0
- cumulusci/utils/yaml/safer_loader.py +74 -0
- cumulusci/utils/yaml/tests/bad_cci.yml +5 -0
- cumulusci/utils/yaml/tests/cassettes/TestCumulusciYml.test_validate_url__with_errors.yaml +20 -0
- cumulusci/utils/yaml/tests/test_cumulusci_yml.py +286 -0
- cumulusci/utils/yaml/tests/test_model_parser.py +175 -0
- cumulusci/utils/yaml/tests/test_safer_loader.py +88 -0
- cumulusci/utils/ziputils.py +61 -0
- cumulusci/vcs/base.py +143 -0
- cumulusci/vcs/bootstrap.py +272 -0
- cumulusci/vcs/github/__init__.py +24 -0
- cumulusci/vcs/github/adapter.py +689 -0
- cumulusci/vcs/github/release_notes/generator.py +219 -0
- cumulusci/vcs/github/release_notes/parser.py +151 -0
- cumulusci/vcs/github/release_notes/provider.py +143 -0
- cumulusci/vcs/github/service.py +569 -0
- cumulusci/vcs/github/tests/test_adapter.py +138 -0
- cumulusci/vcs/github/tests/test_service.py +408 -0
- cumulusci/vcs/models.py +586 -0
- cumulusci/vcs/tests/conftest.py +41 -0
- cumulusci/vcs/tests/dummy_service.py +241 -0
- cumulusci/vcs/tests/test_vcs_base.py +687 -0
- cumulusci/vcs/tests/test_vcs_bootstrap.py +727 -0
- cumulusci/vcs/utils/__init__.py +31 -0
- cumulusci/vcs/vcs_source.py +287 -0
- cumulusci_plus-5.0.0.dist-info/METADATA +145 -0
- cumulusci_plus-5.0.0.dist-info/RECORD +744 -0
- cumulusci_plus-5.0.0.dist-info/WHEEL +4 -0
- cumulusci_plus-5.0.0.dist-info/entry_points.txt +3 -0
- cumulusci_plus-5.0.0.dist-info/licenses/AUTHORS.rst +41 -0
- cumulusci_plus-5.0.0.dist-info/licenses/LICENSE +30 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
*** Settings ***
|
|
2
|
+
|
|
3
|
+
Documentation
|
|
4
|
+
... This resource file imports the Salesforce and CumulusCI
|
|
5
|
+
... keyword libraries, along with several other commonly used
|
|
6
|
+
... libraries (Collections, OperatingSystem, String, XML). In
|
|
7
|
+
... addition, it defines several other keywords.
|
|
8
|
+
...
|
|
9
|
+
... This resource file also defines several global variables,
|
|
10
|
+
... including ``${BROWSER}``, ``${ORG}``, and ``${DEFAULT_BROWSER_SIZE}``
|
|
11
|
+
...
|
|
12
|
+
... This resource file should be included in every test suite,
|
|
13
|
+
... like in the following example (note: there should be two
|
|
14
|
+
... or more spaces after ``Resource``):
|
|
15
|
+
...
|
|
16
|
+
... | ``*** Settings ***``
|
|
17
|
+
... | ``Resource cumulusci/robotframework/Salesforce.robot``
|
|
18
|
+
|
|
19
|
+
Library Collections
|
|
20
|
+
Library OperatingSystem
|
|
21
|
+
Library String
|
|
22
|
+
Library XML
|
|
23
|
+
Library SeleniumLibrary implicit_wait=${IMPLICIT_WAIT} timeout=${TIMEOUT}
|
|
24
|
+
Library cumulusci.robotframework.SalesforceAPI
|
|
25
|
+
Library cumulusci.robotframework.CumulusCI ${ORG}
|
|
26
|
+
Library cumulusci.robotframework.Salesforce debug=${DEBUG}
|
|
27
|
+
Library cumulusci.robotframework.Performance
|
|
28
|
+
|
|
29
|
+
*** Variables ***
|
|
30
|
+
${BROWSER} chrome
|
|
31
|
+
${SELENIUM_SPEED} 0
|
|
32
|
+
${DEBUG} ${false}
|
|
33
|
+
${CHROME_BINARY} ${empty}
|
|
34
|
+
${ORG} ${empty}
|
|
35
|
+
${IMPLICIT_WAIT} 7.0
|
|
36
|
+
${INITIAL_TIMEOUT} 180.0
|
|
37
|
+
${TIMEOUT} 30.0
|
|
38
|
+
${LOCATION STRATEGIES INITIALIZED} ${False}
|
|
39
|
+
${DEFAULT BROWSER SIZE} 1280x1024
|
|
40
|
+
|
|
41
|
+
*** Keywords ***
|
|
42
|
+
|
|
43
|
+
Delete Records and Close Browser
|
|
44
|
+
[Documentation]
|
|
45
|
+
... This will close all open browser windows and then delete
|
|
46
|
+
... all records that were created with the Salesforce API during
|
|
47
|
+
... this testing session.
|
|
48
|
+
Close All Browsers
|
|
49
|
+
Delete Session Records
|
|
50
|
+
|
|
51
|
+
Locate Element By Text
|
|
52
|
+
[Documentation]
|
|
53
|
+
... This is registered as a custom locator strategy named ``text``.
|
|
54
|
+
... It is shorthand for the locator ``//*[text()=...]``
|
|
55
|
+
...
|
|
56
|
+
... Example:
|
|
57
|
+
...
|
|
58
|
+
... | Wait until page contains element text:Mobile Publisher
|
|
59
|
+
|
|
60
|
+
[Arguments] ${browser} ${locator} ${tag} ${constraints}
|
|
61
|
+
${element}= Get WebElement //*[text()='${locator}']
|
|
62
|
+
[Return] ${element}
|
|
63
|
+
|
|
64
|
+
Locate Element By Title
|
|
65
|
+
[Documentation]
|
|
66
|
+
... This is registered as a custom locator strategy named ``title``.
|
|
67
|
+
... It is shorthand for the locator ``//*[@title=...]``
|
|
68
|
+
...
|
|
69
|
+
... Example:
|
|
70
|
+
...
|
|
71
|
+
... | Wait until page contains element title:Object Manager
|
|
72
|
+
|
|
73
|
+
[Arguments] ${browser} ${locator} ${tag} ${constraints}
|
|
74
|
+
${element}= Get WebElement //*[@title='${locator}']
|
|
75
|
+
[Return] ${element}
|
|
76
|
+
|
|
77
|
+
Open Test Browser
|
|
78
|
+
[Documentation]
|
|
79
|
+
... Opens a test browser to the org.
|
|
80
|
+
...
|
|
81
|
+
... The variable ${BROWSER} determines which browser should
|
|
82
|
+
... open. The following four browsers are explicitly supported:
|
|
83
|
+
... chrome, firefox, headlesschrome, and headlessfirefox. Any
|
|
84
|
+
... other value will be passed directly to the SeleniumLibrary
|
|
85
|
+
... 'Open Browser' keyword.
|
|
86
|
+
...
|
|
87
|
+
... Once the browser has been opened, it will be set to the given
|
|
88
|
+
... size (default=${DEFAULT BROWSER SIZE})
|
|
89
|
+
...
|
|
90
|
+
... If you open multiple browsers you can use the optional
|
|
91
|
+
... argument `alias` to give each browser a name. This name can
|
|
92
|
+
... be used when calling the `Switch Browser` keyword from
|
|
93
|
+
... SeleniumLibrary
|
|
94
|
+
...
|
|
95
|
+
... The optional argument 'useralias' may be used to specify a
|
|
96
|
+
... specific user by their alias; if not specified then the org's
|
|
97
|
+
... default user will be used.
|
|
98
|
+
...
|
|
99
|
+
... The keyword `Log Browser Capabilities` will automatically be called.
|
|
100
|
+
... The keyword will also call `Wait Until Salesforce is Ready` unless
|
|
101
|
+
... the `wait` parameter is set to False.
|
|
102
|
+
|
|
103
|
+
[Arguments] ${size}=${DEFAULT BROWSER SIZE} ${alias}=${NONE} ${wait}=True ${useralias}=${NONE}
|
|
104
|
+
${login_url}= Run keyword if $useralias Login URL alias=${useralias}
|
|
105
|
+
... ELSE Login URL
|
|
106
|
+
|
|
107
|
+
Run Keyword If '${BROWSER}' == 'chrome' Open Test Browser Chrome ${login_url} alias=${alias}
|
|
108
|
+
... ELSE IF '${BROWSER}' == 'firefox' Open Test Browser Firefox ${login_url} alias=${alias}
|
|
109
|
+
... ELSE IF '${BROWSER}' == 'headlesschrome' Open Test Browser Chrome ${login_url} alias=${alias}
|
|
110
|
+
... ELSE IF '${BROWSER}' == 'headlessfirefox' Open Test Browser Headless Firefox ${login_url} alias=${alias}
|
|
111
|
+
... ELSE Open Browser ${login_url} ${BROWSER} alias=${alias}
|
|
112
|
+
${should_wait}= convert to boolean ${wait}
|
|
113
|
+
Run keyword if $should_wait Wait Until Salesforce Is Ready timeout=180
|
|
114
|
+
Set Selenium Timeout ${TIMEOUT}
|
|
115
|
+
Initialize Location Strategies
|
|
116
|
+
${width} ${height}= split string ${size} separator=x max_split=1
|
|
117
|
+
Set window size ${width} ${height}
|
|
118
|
+
Set selenium speed ${SELENIUM_SPEED}
|
|
119
|
+
Log browser capabilities
|
|
120
|
+
|
|
121
|
+
Open Test Browser Chrome
|
|
122
|
+
[Documentation] Opens a Chrome browser window and navigates to the org
|
|
123
|
+
... This keyword isn't normally called directly by a test. It is used
|
|
124
|
+
... by the `Open Test Browser` keyword.
|
|
125
|
+
|
|
126
|
+
[Arguments] ${login_url} ${alias}=${NONE}
|
|
127
|
+
${options} = Get Chrome Options
|
|
128
|
+
Create Webdriver With Retry Chrome options=${options} alias=${alias}
|
|
129
|
+
Set Selenium Implicit Wait ${IMPLICIT_WAIT}
|
|
130
|
+
Set Selenium Timeout ${TIMEOUT}
|
|
131
|
+
Go To ${login_url}
|
|
132
|
+
|
|
133
|
+
Open Test Browser Firefox
|
|
134
|
+
[Documentation] Opens a Firefox browser window and navigates to the org
|
|
135
|
+
... This keyword isn't normally called directly by a test. It is used
|
|
136
|
+
... by the `Open Test Browser` keyword.
|
|
137
|
+
...
|
|
138
|
+
... The firefox profile is set to accept all cookies.
|
|
139
|
+
|
|
140
|
+
[Arguments] ${login_url} ${alias}=${NONE}
|
|
141
|
+
Open Browser ${login_url} firefox alias=${alias}
|
|
142
|
+
# http://kb.mozillazine.org/Network.cookie.cookieBehavior
|
|
143
|
+
... ff_profile_dir=set_preference("network.cookie.cookieBehavior", 0)
|
|
144
|
+
|
|
145
|
+
Open Test Browser Headless Firefox
|
|
146
|
+
[Documentation] Opens the firefox browser in headless mode
|
|
147
|
+
... This keyword isn't normally called directly by a test. It is used
|
|
148
|
+
... by the `Open Test Browser` keyword.
|
|
149
|
+
...
|
|
150
|
+
... The firefox profile is set to accept all cookies.
|
|
151
|
+
|
|
152
|
+
[Arguments] ${login_url} ${alias}=${NONE}
|
|
153
|
+
Open Browser ${login_url} headlessfirefox alias=${alias}
|
|
154
|
+
# http://kb.mozillazine.org/Network.cookie.cookieBehavior
|
|
155
|
+
... ff_profile_dir=set_preference("network.cookie.cookieBehavior", 0)
|
|
156
|
+
|
|
157
|
+
Get Chrome Options
|
|
158
|
+
[Documentation]
|
|
159
|
+
... Returns a dictionary of chrome options, for use by the keyword `Open Test Browser`.
|
|
160
|
+
...
|
|
161
|
+
... This keyword is not intended to be used by test scripts.
|
|
162
|
+
${options} = Evaluate selenium.webdriver.ChromeOptions() modules=selenium
|
|
163
|
+
Run Keyword If '${BROWSER}' == 'headlesschrome'
|
|
164
|
+
... Chrome Set Headless ${options}
|
|
165
|
+
Run Keyword If '${CHROME_BINARY}' != '${empty}'
|
|
166
|
+
... Chrome Set Binary ${options}
|
|
167
|
+
Call Method ${options} add_argument --disable-notifications
|
|
168
|
+
[return] ${options}
|
|
169
|
+
|
|
170
|
+
Chrome Set Binary
|
|
171
|
+
[Documentation]
|
|
172
|
+
... Sets the 'options.binary_location' value in the chrome options dictionary
|
|
173
|
+
... to the value of the environment variable CHROME_BINARY, if set.
|
|
174
|
+
...
|
|
175
|
+
... This keyword is not intended to be used by test scripts
|
|
176
|
+
|
|
177
|
+
[Arguments] ${options}
|
|
178
|
+
${options.binary_location} = Set Variable ${CHROME_BINARY}
|
|
179
|
+
[return] ${options}
|
|
180
|
+
|
|
181
|
+
Chrome Set Headless
|
|
182
|
+
[Documentation]
|
|
183
|
+
... This keyword is used to set the chrome options dictionary values
|
|
184
|
+
... required to run headless chrome.
|
|
185
|
+
...
|
|
186
|
+
... This keyword is not intended to be used by test scripts
|
|
187
|
+
|
|
188
|
+
[Arguments] ${options}
|
|
189
|
+
Call Method ${options} set_headless ${true}
|
|
190
|
+
Call Method ${options} add_argument --disable-dev-shm-usage
|
|
191
|
+
Call Method ${options} add_argument --disable-background-timer-throttling
|
|
192
|
+
[return] ${options}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
from simple_salesforce.exceptions import SalesforceResourceNotFound
|
|
2
|
+
|
|
3
|
+
from cumulusci.core.template_utils import format_str
|
|
4
|
+
from cumulusci.robotframework.base_library import BaseLibrary
|
|
5
|
+
|
|
6
|
+
# https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_sobjects_collections_create.htm
|
|
7
|
+
SF_COLLECTION_INSERTION_LIMIT = 200
|
|
8
|
+
STATUS_KEY = ("status",)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SalesforceAPI(BaseLibrary):
|
|
12
|
+
"""Keywords for interacting with Salesforce API"""
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self._session_records = []
|
|
17
|
+
|
|
18
|
+
def delete_session_records(self):
|
|
19
|
+
"""Deletes records that were created while running this test case.
|
|
20
|
+
|
|
21
|
+
(Only records specifically recorded using the Store Session Record
|
|
22
|
+
keyword are deleted.)
|
|
23
|
+
"""
|
|
24
|
+
self._session_records.reverse()
|
|
25
|
+
self.builtin.log("Deleting {} records".format(len(self._session_records)))
|
|
26
|
+
for record in self._session_records[:]:
|
|
27
|
+
self.builtin.log(" Deleting {type} {id}".format(**record))
|
|
28
|
+
try:
|
|
29
|
+
self.salesforce_delete(record["type"], record["id"])
|
|
30
|
+
except SalesforceResourceNotFound:
|
|
31
|
+
self.builtin.log(" {type} {id} is already deleted".format(**record))
|
|
32
|
+
except Exception as e:
|
|
33
|
+
self.builtin.log(
|
|
34
|
+
" {type} {id} could not be deleted:".format(**record),
|
|
35
|
+
level="WARN",
|
|
36
|
+
)
|
|
37
|
+
self.builtin.log(" {}".format(e), level="WARN")
|
|
38
|
+
|
|
39
|
+
def get_latest_api_version(self):
|
|
40
|
+
"""Return the API version used by the current org"""
|
|
41
|
+
return self.cumulusci.org.latest_api_version
|
|
42
|
+
|
|
43
|
+
def get_record_type_id(self, obj_type, developer_name):
|
|
44
|
+
"""Returns the Record Type Id for a record type name"""
|
|
45
|
+
soql = "SELECT Id FROM RecordType WHERE SObjectType='{}' and DeveloperName='{}'".format(
|
|
46
|
+
obj_type, developer_name
|
|
47
|
+
)
|
|
48
|
+
res = self.cumulusci.sf.query_all(soql)
|
|
49
|
+
return res["records"][0]["Id"]
|
|
50
|
+
|
|
51
|
+
def salesforce_delete(self, obj_name, obj_id):
|
|
52
|
+
"""Deletes a Salesforce object by object name and Id.
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
|
|
56
|
+
The following example assumes that ``${contact id}`` has been
|
|
57
|
+
previously set. The example deletes the Contact with that Id.
|
|
58
|
+
|
|
59
|
+
| Salesforce Delete Contact ${contact id}
|
|
60
|
+
"""
|
|
61
|
+
self.builtin.log("Deleting {} with Id {}".format(obj_name, obj_id))
|
|
62
|
+
obj_class = getattr(self.cumulusci.sf, obj_name)
|
|
63
|
+
obj_class.delete(obj_id)
|
|
64
|
+
self.remove_session_record(obj_name, obj_id)
|
|
65
|
+
|
|
66
|
+
def salesforce_get(self, obj_name, obj_id):
|
|
67
|
+
"""Gets a Salesforce object by Id and returns the result as a dict.
|
|
68
|
+
|
|
69
|
+
Example:
|
|
70
|
+
|
|
71
|
+
The following example assumes that ``${contact id}`` has been
|
|
72
|
+
previously set. The example retrieves the Contact object with
|
|
73
|
+
that Id and then logs the Name field.
|
|
74
|
+
|
|
75
|
+
| &{contact}= Salesforce Get Contact ${contact id}
|
|
76
|
+
| log Contact name: ${contact['Name']}
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
self.builtin.log(f"Getting {obj_name} with Id {obj_id}")
|
|
80
|
+
obj_class = getattr(self.cumulusci.sf, obj_name)
|
|
81
|
+
return obj_class.get(obj_id)
|
|
82
|
+
|
|
83
|
+
def salesforce_insert(self, obj_name, **kwargs):
|
|
84
|
+
"""Creates a new Salesforce object and returns the Id.
|
|
85
|
+
|
|
86
|
+
The fields of the object may be defined with keyword arguments
|
|
87
|
+
where the keyword name is the same as the field name.
|
|
88
|
+
|
|
89
|
+
The object name and Id is passed to the *Store Session
|
|
90
|
+
Record* keyword, and will be deleted when the keyword
|
|
91
|
+
*Delete Session Records* is called.
|
|
92
|
+
|
|
93
|
+
As a best practice, either *Delete Session Records* or
|
|
94
|
+
*Delete Records and Close Browser* from Salesforce.robot
|
|
95
|
+
should be called as a suite teardown.
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
|
|
99
|
+
The following example creates a new Contact with the
|
|
100
|
+
first name of "Eleanor" and the last name of "Rigby".
|
|
101
|
+
|
|
102
|
+
| ${contact id}= Salesforce Insert Contact
|
|
103
|
+
| ... FirstName=Eleanor
|
|
104
|
+
| ... LastName=Rigby
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
self.builtin.log("Inserting {} with values {}".format(obj_name, kwargs))
|
|
108
|
+
obj_class = getattr(self.cumulusci.sf, obj_name)
|
|
109
|
+
res = obj_class.create(kwargs)
|
|
110
|
+
self.store_session_record(obj_name, res["id"])
|
|
111
|
+
return res["id"]
|
|
112
|
+
|
|
113
|
+
def _salesforce_generate_object(self, obj_name, **fields):
|
|
114
|
+
obj = {"attributes": {"type": obj_name}} # Object type to create
|
|
115
|
+
obj.update(fields)
|
|
116
|
+
return obj
|
|
117
|
+
|
|
118
|
+
def generate_test_data(self, obj_name, number_to_create, **fields):
|
|
119
|
+
"""Generate bulk test data
|
|
120
|
+
|
|
121
|
+
This returns an array of dictionaries with template-formatted
|
|
122
|
+
arguments which can be passed to the *Salesforce Collection Insert*
|
|
123
|
+
keyword.
|
|
124
|
+
|
|
125
|
+
You can use ``{{number}}`` to represent the unique index of
|
|
126
|
+
the row in the list of rows. If the entire string consists of
|
|
127
|
+
a number, Salesforce API will treat the value as a number.
|
|
128
|
+
|
|
129
|
+
Example:
|
|
130
|
+
|
|
131
|
+
The following example creates three new Contacts:
|
|
132
|
+
|
|
133
|
+
| @{objects} = Generate Test Data Contact 3
|
|
134
|
+
| ... Name=User {{number}}
|
|
135
|
+
| ... Age={{number}}
|
|
136
|
+
|
|
137
|
+
The example code will generate Contact objects with these fields:
|
|
138
|
+
|
|
139
|
+
| [{'Name': 'User 0', 'Age': '0'},
|
|
140
|
+
| {'Name': 'User 1', 'Age': '1'},
|
|
141
|
+
| {'Name': 'User 2', 'Age': '2'}]
|
|
142
|
+
|
|
143
|
+
Python Expression Syntax is allowed so computed templates like this are also allowed: ``{{1000 + number}}``
|
|
144
|
+
|
|
145
|
+
Python operators can be used, but no functions or variables are provided, so mostly you just
|
|
146
|
+
have access to mathematical and logical operators. The Python operators are described here:
|
|
147
|
+
|
|
148
|
+
https://www.digitalocean.com/community/tutorials/how-to-do-math-in-python-3-with-operators
|
|
149
|
+
|
|
150
|
+
Contact the CCI team if you have a use-case that
|
|
151
|
+
could benefit from more expression language power.
|
|
152
|
+
|
|
153
|
+
Templates can also be based on faker patterns like those described here:
|
|
154
|
+
|
|
155
|
+
https://faker.readthedocs.io/en/master/providers.html
|
|
156
|
+
|
|
157
|
+
Most examples can be pasted into templates verbatim:
|
|
158
|
+
|
|
159
|
+
| @{objects}= Generate Test Data Contact 200
|
|
160
|
+
| ... Name={{fake.first_name}} {{fake.last_name}}
|
|
161
|
+
| ... MailingStreet={{fake.street_address}}
|
|
162
|
+
| ... MailingCity=New York
|
|
163
|
+
| ... MailingState=NY
|
|
164
|
+
| ... MailingPostalCode=12345
|
|
165
|
+
| ... Email={{fake.email(domain="salesforce.com")}}
|
|
166
|
+
|
|
167
|
+
"""
|
|
168
|
+
objs = []
|
|
169
|
+
|
|
170
|
+
for i in range(int(number_to_create)):
|
|
171
|
+
formatted_fields = {
|
|
172
|
+
name: format_str(value, {"number": i}) for name, value in fields.items()
|
|
173
|
+
}
|
|
174
|
+
newobj = self._salesforce_generate_object(obj_name, **formatted_fields)
|
|
175
|
+
objs.append(newobj)
|
|
176
|
+
|
|
177
|
+
return objs
|
|
178
|
+
|
|
179
|
+
def remove_session_record(self, obj_type, obj_id):
|
|
180
|
+
"""Remove a record from the list of records that should be automatically removed."""
|
|
181
|
+
try:
|
|
182
|
+
self._session_records.remove({"type": obj_type, "id": obj_id})
|
|
183
|
+
except ValueError:
|
|
184
|
+
self.builtin.log(
|
|
185
|
+
"Did not find record {} {} in the session records list".format(
|
|
186
|
+
obj_type, obj_id
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def salesforce_collection_insert(self, objects):
|
|
191
|
+
"""Inserts records that were created with *Generate Test Data*.
|
|
192
|
+
|
|
193
|
+
_objects_ is a list of data, typically generated by the
|
|
194
|
+
*Generate Test Data* keyword.
|
|
195
|
+
|
|
196
|
+
A 200 record limit is enforced by the Salesforce APIs.
|
|
197
|
+
|
|
198
|
+
The object name and Id is passed to the *Store Session
|
|
199
|
+
Record* keyword, and will be deleted when the keyword *Delete
|
|
200
|
+
Session Records* is called.
|
|
201
|
+
|
|
202
|
+
As a best practice, either *Delete Session Records* or
|
|
203
|
+
**Delete Records and Close Browser* from Salesforce.robot
|
|
204
|
+
should be called as a suite teardown.
|
|
205
|
+
|
|
206
|
+
Example:
|
|
207
|
+
|
|
208
|
+
| @{objects}= Generate Test Data Contact 200
|
|
209
|
+
| ... FirstName=User {{number}}
|
|
210
|
+
| ... LastName={{fake.last_name}}
|
|
211
|
+
| Salesforce Collection Insert ${objects}
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
assert (
|
|
215
|
+
not obj.get("id", None) for obj in objects
|
|
216
|
+
), "Insertable objects should not have IDs"
|
|
217
|
+
assert len(objects) <= SF_COLLECTION_INSERTION_LIMIT, (
|
|
218
|
+
"Cannot insert more than %s objects with this keyword"
|
|
219
|
+
% SF_COLLECTION_INSERTION_LIMIT
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
records = self.cumulusci.sf.restful(
|
|
223
|
+
"composite/sobjects",
|
|
224
|
+
method="POST",
|
|
225
|
+
json={"allOrNone": True, "records": objects},
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
for idx, (record, obj) in enumerate(zip(records, objects)):
|
|
229
|
+
if record["errors"]:
|
|
230
|
+
raise AssertionError(
|
|
231
|
+
"Error on Object {idx}: {record} : {obj}".format(**vars())
|
|
232
|
+
)
|
|
233
|
+
self.store_session_record(obj["attributes"]["type"], record["id"])
|
|
234
|
+
obj["id"] = record["id"]
|
|
235
|
+
obj[STATUS_KEY] = record
|
|
236
|
+
|
|
237
|
+
return objects
|
|
238
|
+
|
|
239
|
+
def salesforce_collection_update(self, objects):
|
|
240
|
+
"""Updates records described as Robot/Python dictionaries.
|
|
241
|
+
|
|
242
|
+
_objects_ is a dictionary of data in the format returned
|
|
243
|
+
by the *Salesforce Collection Insert* keyword.
|
|
244
|
+
|
|
245
|
+
A 200 record limit is enforced by the Salesforce APIs.
|
|
246
|
+
|
|
247
|
+
Example:
|
|
248
|
+
|
|
249
|
+
The following example creates ten accounts and then updates
|
|
250
|
+
the Rating from "Cold" to "Hot"
|
|
251
|
+
|
|
252
|
+
| ${data}= Generate Test Data Account 10
|
|
253
|
+
| ... Name=Account #{{number}}
|
|
254
|
+
| ... Rating=Cold
|
|
255
|
+
| ${accounts}= Salesforce Collection Insert ${data}
|
|
256
|
+
|
|
|
257
|
+
| FOR ${account} IN @{accounts}
|
|
258
|
+
| Set to dictionary ${account} Rating Hot
|
|
259
|
+
| END
|
|
260
|
+
| Salesforce Collection Update ${accounts}
|
|
261
|
+
|
|
262
|
+
"""
|
|
263
|
+
for obj in objects:
|
|
264
|
+
assert obj[
|
|
265
|
+
"id"
|
|
266
|
+
], "Should be a list of objects with Ids returned by Salesforce Collection Insert"
|
|
267
|
+
if STATUS_KEY in obj:
|
|
268
|
+
del obj[STATUS_KEY]
|
|
269
|
+
|
|
270
|
+
assert len(objects) <= SF_COLLECTION_INSERTION_LIMIT, (
|
|
271
|
+
"Cannot update more than %s objects with this keyword"
|
|
272
|
+
% SF_COLLECTION_INSERTION_LIMIT
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
records = self.cumulusci.sf.restful(
|
|
276
|
+
"composite/sobjects",
|
|
277
|
+
method="PATCH",
|
|
278
|
+
json={"allOrNone": True, "records": objects},
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
for record, obj in zip(records, objects):
|
|
282
|
+
obj[STATUS_KEY] = record
|
|
283
|
+
|
|
284
|
+
for idx, (record, obj) in enumerate(zip(records, objects)):
|
|
285
|
+
if record["errors"]:
|
|
286
|
+
raise AssertionError(
|
|
287
|
+
"Error on Object {idx}: {record} : {obj}".format(**vars())
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
def salesforce_query(self, obj_name, **kwargs):
|
|
291
|
+
"""Constructs and runs a simple SOQL query and returns a list of dictionaries.
|
|
292
|
+
|
|
293
|
+
By default the results will only contain object Ids. You can
|
|
294
|
+
specify a SOQL SELECT clause via keyword arguments by passing
|
|
295
|
+
a comma-separated list of fields with the ``select`` keyword
|
|
296
|
+
argument.
|
|
297
|
+
|
|
298
|
+
You can supply keys and values to match against
|
|
299
|
+
in keyword arguments, or a full SOQL where-clause
|
|
300
|
+
in a keyword argument named ``where``. If you supply
|
|
301
|
+
both, they will be combined with a SOQL "AND".
|
|
302
|
+
|
|
303
|
+
``order_by`` and ``limit`` keyword arguments are also
|
|
304
|
+
supported as shown below.
|
|
305
|
+
|
|
306
|
+
Examples:
|
|
307
|
+
|
|
308
|
+
The following example searches for all Contacts where the
|
|
309
|
+
first name is "Eleanor". It returns the "Name" and "Id"
|
|
310
|
+
fields and logs them to the robot report:
|
|
311
|
+
|
|
312
|
+
| @{records}= Salesforce Query Contact select=Id,Name
|
|
313
|
+
| ... FirstName=Eleanor
|
|
314
|
+
| FOR ${record} IN @{records}
|
|
315
|
+
| log Name: ${record['Name']} Id: ${record['Id']}
|
|
316
|
+
| END
|
|
317
|
+
|
|
318
|
+
Or with a WHERE-clause, we can look for the last contact where
|
|
319
|
+
the first name is NOT Eleanor.
|
|
320
|
+
|
|
321
|
+
| @{records}= Salesforce Query Contact select=Id,Name
|
|
322
|
+
| ... where=FirstName!='Eleanor'
|
|
323
|
+
| ... order_by=LastName desc
|
|
324
|
+
| ... limit=1
|
|
325
|
+
"""
|
|
326
|
+
query = self._soql_query_builder(obj_name, **kwargs)
|
|
327
|
+
self.builtin.log("Running SOQL Query: {}".format(query))
|
|
328
|
+
return self.cumulusci.sf.query_all(query).get("records", [])
|
|
329
|
+
|
|
330
|
+
def _soql_query_builder(
|
|
331
|
+
self, obj_name, select=None, order_by=None, limit=None, where=None, **kwargs
|
|
332
|
+
):
|
|
333
|
+
query = "SELECT "
|
|
334
|
+
if select:
|
|
335
|
+
query += select
|
|
336
|
+
else:
|
|
337
|
+
query += "Id"
|
|
338
|
+
query += " FROM {}".format(obj_name)
|
|
339
|
+
where_clauses = []
|
|
340
|
+
if where:
|
|
341
|
+
where_clauses = [where]
|
|
342
|
+
for key, value in kwargs.items():
|
|
343
|
+
where_clauses.append("{} = '{}'".format(key, value))
|
|
344
|
+
if where_clauses:
|
|
345
|
+
query += " WHERE " + " AND ".join(where_clauses)
|
|
346
|
+
if order_by:
|
|
347
|
+
query += " ORDER BY " + order_by
|
|
348
|
+
if limit:
|
|
349
|
+
assert int(limit), "Limit should be an integer"
|
|
350
|
+
query += f" LIMIT {limit}"
|
|
351
|
+
|
|
352
|
+
return query
|
|
353
|
+
|
|
354
|
+
def salesforce_update(self, obj_name, obj_id, **kwargs):
|
|
355
|
+
"""Updates a Salesforce object by Id.
|
|
356
|
+
|
|
357
|
+
The keyword returns the result from the underlying
|
|
358
|
+
simple_salesforce ``insert`` method, which is an HTTP
|
|
359
|
+
status code. As with `Salesforce Insert`, field values
|
|
360
|
+
are specified as keyword arguments.
|
|
361
|
+
|
|
362
|
+
The following example assumes that ${contact id} has been
|
|
363
|
+
previously set, and adds a Description to the given
|
|
364
|
+
contact.
|
|
365
|
+
|
|
366
|
+
| &{contact}= Salesforce Update Contact ${contact id}
|
|
367
|
+
| ... Description=This Contact created during a test
|
|
368
|
+
| Should be equal as numbers ${result} 204
|
|
369
|
+
|
|
370
|
+
"""
|
|
371
|
+
self.builtin.log(
|
|
372
|
+
"Updating {} {} with values {}".format(obj_name, obj_id, kwargs)
|
|
373
|
+
)
|
|
374
|
+
obj_class = getattr(self.cumulusci.sf, obj_name)
|
|
375
|
+
return obj_class.update(obj_id, kwargs)
|
|
376
|
+
|
|
377
|
+
def soql_query(self, query, *args):
|
|
378
|
+
"""Runs a SOQL query and returns the result as a dictionary.
|
|
379
|
+
|
|
380
|
+
The _query_ parameter must be a properly quoted SOQL query
|
|
381
|
+
statement or statement fragment. Additional arguments will be
|
|
382
|
+
joined to the query with spaces, allowing for a query to span
|
|
383
|
+
multiple lines.
|
|
384
|
+
|
|
385
|
+
This keyword will return a dictionary. The dictionary contains
|
|
386
|
+
the keys as documented for the raw API call. The most useful
|
|
387
|
+
keys are ``records`` and ``totalSize``, which contains a list
|
|
388
|
+
of records that were matched by the query and the number of
|
|
389
|
+
records that were returned.
|
|
390
|
+
|
|
391
|
+
Example:
|
|
392
|
+
|
|
393
|
+
The following example searches for all Contacts with a first
|
|
394
|
+
name of "Eleanor" and a last name of "Rigby", and then logs
|
|
395
|
+
the Id of the first record found.
|
|
396
|
+
|
|
397
|
+
| ${result}= SOQL Query
|
|
398
|
+
| ... SELECT Name, Id
|
|
399
|
+
| ... FROM Contact
|
|
400
|
+
| ... WHERE FirstName='Eleanor' AND LastName='Rigby'
|
|
401
|
+
|
|
|
402
|
+
| ${contact}= Get from list ${result['records']} 0
|
|
403
|
+
| log Contact Id: ${contact['Id']}
|
|
404
|
+
|
|
405
|
+
"""
|
|
406
|
+
query = " ".join((query,) + args)
|
|
407
|
+
self.builtin.log("Running SOQL Query: {}".format(query))
|
|
408
|
+
return self.cumulusci.sf.query_all(query)
|
|
409
|
+
|
|
410
|
+
def store_session_record(self, obj_type, obj_id):
|
|
411
|
+
"""Stores a Salesforce record's Id for use in the *Delete Session Records* keyword.
|
|
412
|
+
|
|
413
|
+
This keyword is automatically called by *Salesforce Insert*.
|
|
414
|
+
"""
|
|
415
|
+
self.builtin.log("Storing {} {} to session records".format(obj_type, obj_id))
|
|
416
|
+
self._session_records.append({"type": obj_type, "id": obj_id})
|