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,220 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from Browser import SupportedBrowsers
|
|
5
|
+
from Browser.utils.data_types import KeyAction, PageLoadStates
|
|
6
|
+
from robot.utils import timestr_to_secs
|
|
7
|
+
|
|
8
|
+
from cumulusci.robotframework.base_library import BaseLibrary
|
|
9
|
+
from cumulusci.robotframework.faker_mixin import FakerMixin
|
|
10
|
+
from cumulusci.robotframework.utils import (
|
|
11
|
+
WAIT_FOR_AURA_SCRIPT,
|
|
12
|
+
capture_screenshot_on_error,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SalesforcePlaywright(FakerMixin, BaseLibrary):
|
|
17
|
+
ROBOT_LIBRARY_SCOPE = "Suite"
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
super().__init__()
|
|
21
|
+
self._browser = None
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def browser(self):
|
|
25
|
+
if self._browser is None:
|
|
26
|
+
self._browser = self.builtin.get_library_instance("Browser")
|
|
27
|
+
return self._browser
|
|
28
|
+
|
|
29
|
+
def get_current_record_id(self):
|
|
30
|
+
"""Parses the current url to get the object id of the current record.
|
|
31
|
+
This expects the url to contain an id that matches [a-zA-Z0-9]{15,18}
|
|
32
|
+
"""
|
|
33
|
+
OID_REGEX = r"^(%2F)?([a-zA-Z0-9]{15,18})$"
|
|
34
|
+
url = self.browser.evaluate_javascript(None, "window.location.href")
|
|
35
|
+
for part in url.split("/"):
|
|
36
|
+
oid_match = re.match(OID_REGEX, part)
|
|
37
|
+
if oid_match is not None:
|
|
38
|
+
return oid_match[2]
|
|
39
|
+
raise AssertionError(f"Could not parse record id from url: {url}")
|
|
40
|
+
|
|
41
|
+
def go_to_record_home(self, obj_id):
|
|
42
|
+
"""Navigates to the Home view of a Salesforce Object
|
|
43
|
+
|
|
44
|
+
After navigating, this will wait until the slds-page-header_record-home
|
|
45
|
+
div can be found on the page.
|
|
46
|
+
"""
|
|
47
|
+
url = self.cumulusci.org.lightning_base_url
|
|
48
|
+
url = f"{url}/lightning/r/{obj_id}/view"
|
|
49
|
+
self.browser.go_to(url)
|
|
50
|
+
self.wait_until_loading_is_complete("div.slds-page-header_record-home")
|
|
51
|
+
|
|
52
|
+
def delete_records_and_close_browser(self):
|
|
53
|
+
"""This will close all open browser windows and then delete
|
|
54
|
+
all records that were created with the Salesforce API during
|
|
55
|
+
this testing session.
|
|
56
|
+
"""
|
|
57
|
+
self.browser.close_browser("ALL")
|
|
58
|
+
self.salesforce_api.delete_session_records()
|
|
59
|
+
|
|
60
|
+
def open_test_browser(
|
|
61
|
+
self, size=None, useralias=None, wait=True, record_video=None
|
|
62
|
+
):
|
|
63
|
+
"""Open a new Playwright browser, context, and page to the default org.
|
|
64
|
+
|
|
65
|
+
The return value is a tuple of the browser id, context id, and page details
|
|
66
|
+
returned by the Playwright keywords New Browser, New Context, and New Page.
|
|
67
|
+
|
|
68
|
+
This provides the most common environment for testing. For more control,
|
|
69
|
+
you can create your own browser environment with the Browser library
|
|
70
|
+
keywords `Create Browser`, `Create Context`, and `Create Page`.
|
|
71
|
+
|
|
72
|
+
To record a video of the session, set `record_video` to True. The video
|
|
73
|
+
(*.webm) will be viewable in the log.html file at the point where this
|
|
74
|
+
keyword is logged.
|
|
75
|
+
|
|
76
|
+
This keyword automatically calls the browser keyword `Wait until network is idle`.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
wait = self.builtin.convert_to_boolean(wait)
|
|
80
|
+
default_size = self.builtin.get_variable_value(
|
|
81
|
+
"${DEFAULT BROWSER SIZE}", "1280x1024"
|
|
82
|
+
)
|
|
83
|
+
size = size or default_size
|
|
84
|
+
|
|
85
|
+
browser = self.builtin.get_variable_value("${BROWSER}", "chrome")
|
|
86
|
+
headless = browser.startswith("headless")
|
|
87
|
+
browser_type = browser[8:] if headless else browser
|
|
88
|
+
browser_type = "chromium" if browser_type == "chrome" else browser_type
|
|
89
|
+
browser_enum = getattr(SupportedBrowsers, browser_type, None)
|
|
90
|
+
|
|
91
|
+
# Note: we can't just pass alias=useralias in the case of useralias being None.
|
|
92
|
+
# That value gets passed to a salesforce query which barfs if the value
|
|
93
|
+
# is None.
|
|
94
|
+
login_url = (
|
|
95
|
+
self.cumulusci.login_url(alias=useralias)
|
|
96
|
+
if useralias
|
|
97
|
+
else self.cumulusci.login_url()
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if record_video:
|
|
101
|
+
# ugh. the "dir" value must be non-empty, and will be treated as
|
|
102
|
+
# a folder name under the browser/video folder. using "../video"
|
|
103
|
+
# seems to be the only way to get the videos to go directly in
|
|
104
|
+
# the video folder. Also, using "." doesn't work :-/
|
|
105
|
+
record_video = {"dir": "../video"}
|
|
106
|
+
width, height = size.split("x", 1)
|
|
107
|
+
|
|
108
|
+
browser_id = self.browser.new_browser(browser=browser_enum, headless=headless)
|
|
109
|
+
context_id = self.browser.new_context(
|
|
110
|
+
viewport={"width": width, "height": height}, recordVideo=record_video
|
|
111
|
+
)
|
|
112
|
+
self.browser.set_browser_timeout("15 seconds")
|
|
113
|
+
page_details = self.browser.new_page(login_url)
|
|
114
|
+
|
|
115
|
+
if wait:
|
|
116
|
+
self.wait_until_salesforce_is_ready(login_url)
|
|
117
|
+
return browser_id, context_id, page_details
|
|
118
|
+
|
|
119
|
+
@capture_screenshot_on_error
|
|
120
|
+
def wait_until_loading_is_complete(self, locator=None, timeout="15 seconds"):
|
|
121
|
+
"""Wait for a lightning page to load.
|
|
122
|
+
|
|
123
|
+
By default this keyword will wait for any element with the
|
|
124
|
+
class 'slds-template__container', but a different locator can
|
|
125
|
+
be provided.
|
|
126
|
+
|
|
127
|
+
In addition to waiting for the element, it will also wait for
|
|
128
|
+
any pending aura events to finish.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
locator = (
|
|
132
|
+
"//div[contains(@class, 'slds-template__container')]/*"
|
|
133
|
+
if locator is None
|
|
134
|
+
else locator
|
|
135
|
+
)
|
|
136
|
+
self.browser.get_elements(locator)
|
|
137
|
+
|
|
138
|
+
self.browser.evaluate_javascript(None, WAIT_FOR_AURA_SCRIPT)
|
|
139
|
+
# An old knowledge article recommends waiting a second. I don't
|
|
140
|
+
# like it, but it seems to help. We should do a wait instead,
|
|
141
|
+
# but I can't figure out what to wait on.
|
|
142
|
+
time.sleep(1)
|
|
143
|
+
|
|
144
|
+
@capture_screenshot_on_error
|
|
145
|
+
def wait_until_salesforce_is_ready(
|
|
146
|
+
self, login_url, locator=None, timeout="30 seconds"
|
|
147
|
+
):
|
|
148
|
+
"""Attempt to wait until we land on a lightning page
|
|
149
|
+
|
|
150
|
+
In addition to waiting for a lightning page, this keyword will
|
|
151
|
+
also attempt to wait until there are no more pending ajax
|
|
152
|
+
requests.
|
|
153
|
+
|
|
154
|
+
The timeout parameter is taken as a rough guideline. This
|
|
155
|
+
keyword will actually wait for half of the timeout before
|
|
156
|
+
starting checks for edge cases.
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
timeout_seconds = timestr_to_secs(timeout)
|
|
161
|
+
start_time = time.time()
|
|
162
|
+
|
|
163
|
+
locator = locator or "div.slds-template__container"
|
|
164
|
+
expected_url = rf"/{self.cumulusci.org.lightning_base_url}\/lightning\/.*/"
|
|
165
|
+
|
|
166
|
+
while True:
|
|
167
|
+
try:
|
|
168
|
+
# only wait for half of the timeout before doing some additional
|
|
169
|
+
# checks. This seems to work better than one long timeout.
|
|
170
|
+
self.browser.wait_for_navigation(
|
|
171
|
+
expected_url, timeout_seconds // 2, PageLoadStates.networkidle
|
|
172
|
+
)
|
|
173
|
+
self.wait_until_loading_is_complete(locator)
|
|
174
|
+
# No errors? We're golden.
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
except Exception as exc:
|
|
178
|
+
# dang. Maybe we landed somewhere unexpected?
|
|
179
|
+
if self._check_for_classic():
|
|
180
|
+
continue
|
|
181
|
+
|
|
182
|
+
if time.time() - start_time > timeout_seconds:
|
|
183
|
+
self.browser.take_screenshot()
|
|
184
|
+
raise Exception("Timed out waiting for a lightning page") from exc
|
|
185
|
+
|
|
186
|
+
# If at first you don't succeed, ...
|
|
187
|
+
self.browser.go_to(login_url)
|
|
188
|
+
|
|
189
|
+
def _check_for_classic(self):
|
|
190
|
+
"""Switch to lightning if we land on a classic page
|
|
191
|
+
|
|
192
|
+
This seems to happen randomly, causing tests to fail
|
|
193
|
+
catastrophically. The idea is to detect such a case and
|
|
194
|
+
auto-click the "switch to lightning" link
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
try:
|
|
198
|
+
self.browser.get_element("a.switch-to-lightning")
|
|
199
|
+
self.builtin.log(
|
|
200
|
+
"It appears we are on a classic page; attempting to switch to lightning",
|
|
201
|
+
"WARN",
|
|
202
|
+
)
|
|
203
|
+
# just in case there's a modal present we'll try simulating
|
|
204
|
+
# the escape key. Then, click on the switch-to-lightning link
|
|
205
|
+
self.browser.keyboard_key(KeyAction.press, "Escape")
|
|
206
|
+
self.builtin.sleep("1 second")
|
|
207
|
+
self.browser.click("a.switch-to-lightning")
|
|
208
|
+
return True
|
|
209
|
+
|
|
210
|
+
except (AssertionError):
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
def breakpoint(self):
|
|
214
|
+
"""Serves as a breakpoint for the robot debugger
|
|
215
|
+
|
|
216
|
+
Note: this keyword is a no-op unless the ``robot_debug`` option for
|
|
217
|
+
the task has been set to ``true``. Unless the option has been
|
|
218
|
+
set, this keyword will have no effect on a running test.
|
|
219
|
+
"""
|
|
220
|
+
return None
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
*** Settings ***
|
|
2
|
+
Documentation
|
|
3
|
+
... This resource file contains no keywords, but can be used to import
|
|
4
|
+
... the most common libraries used for writing browser tests that use
|
|
5
|
+
... the robotframework Browser library, based upon Playwright.
|
|
6
|
+
...
|
|
7
|
+
... Note: when using this library, you cannot also use Salesforce.robot
|
|
8
|
+
... or Salesforce.py since those are based on Selenium rather than Playwright.
|
|
9
|
+
...
|
|
10
|
+
... Libraries imported by this resource file:
|
|
11
|
+
...
|
|
12
|
+
... - Browser
|
|
13
|
+
... - Collections
|
|
14
|
+
... - OperatingSystem
|
|
15
|
+
... - String
|
|
16
|
+
... - cumulusci.robotframework.CumulusCI
|
|
17
|
+
... - cumulusci.robotframework.SalesforcePlaywright
|
|
18
|
+
... - cumulusci.robotframework.SalesforceAPI
|
|
19
|
+
... - cumulusci.robotframework.Performance
|
|
20
|
+
...
|
|
21
|
+
... This resource file also defines the following variables, which can all be
|
|
22
|
+
... overridden on the command line with the --vars option
|
|
23
|
+
...
|
|
24
|
+
... | =Variable Name= | = Default Value = |
|
|
25
|
+
... | ${DEFAULT BROWSER SIZE} | 1280x1024 |
|
|
26
|
+
... | ${BROWSER} | chrome |
|
|
27
|
+
|
|
28
|
+
*** Variables ***
|
|
29
|
+
${DEFAULT BROWSER SIZE} 1280x1024
|
|
30
|
+
${BROWSER} chrome
|
|
31
|
+
|
|
32
|
+
*** Settings ***
|
|
33
|
+
Library Browser jsextension=${CURDIR}/javascript/cci_init.js
|
|
34
|
+
Library Collections
|
|
35
|
+
Library OperatingSystem
|
|
36
|
+
Library String
|
|
37
|
+
Library cumulusci.robotframework.CumulusCI ${ORG}
|
|
38
|
+
Library cumulusci.robotframework.SalesforcePlaywright
|
|
39
|
+
Library cumulusci.robotframework.SalesforceAPI
|
|
40
|
+
Library cumulusci.robotframework.Performance
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from robot.libraries.BuiltIn import BuiltIn
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BaseLibrary:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self._builtin = None
|
|
7
|
+
self._cumulusci = None
|
|
8
|
+
self._salesforce_api = None
|
|
9
|
+
self._salesforce = None
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def salesforce(self):
|
|
13
|
+
if getattr(self, "_salesforce", None) is None:
|
|
14
|
+
self._salesforce = self.builtin.get_library_instance(
|
|
15
|
+
"cumulusci.robotframework.Salesforce"
|
|
16
|
+
)
|
|
17
|
+
return self._salesforce
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def salesforce_api(self):
|
|
21
|
+
if getattr(self, "_salesforce_api", None) is None:
|
|
22
|
+
self._salesforce_api = self.builtin.get_library_instance(
|
|
23
|
+
"cumulusci.robotframework.SalesforceAPI"
|
|
24
|
+
)
|
|
25
|
+
return self._salesforce_api
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def builtin(self):
|
|
29
|
+
if getattr(self, "_builtin", None) is None:
|
|
30
|
+
self._builtin = BuiltIn()
|
|
31
|
+
return self._builtin
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def cumulusci(self):
|
|
35
|
+
if getattr(self, "_cumulusci", None) is None:
|
|
36
|
+
self._cumulusci = self.builtin.get_library_instance(
|
|
37
|
+
"cumulusci.robotframework.CumulusCI"
|
|
38
|
+
)
|
|
39
|
+
return self._cumulusci
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import faker
|
|
2
|
+
from robot.libraries.BuiltIn import RobotNotRunningError
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FakerMixin:
|
|
6
|
+
"""Mixin class which provides support for the faker library"""
|
|
7
|
+
|
|
8
|
+
def __init__(self):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self._faker = faker.Faker("en_US")
|
|
11
|
+
try:
|
|
12
|
+
self.builtin.set_global_variable("${faker}", self._faker)
|
|
13
|
+
except RobotNotRunningError:
|
|
14
|
+
# this only happens during unit tests, and we don't care.
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def set_faker_locale(self, locale):
|
|
18
|
+
"""Set the locale for fake data
|
|
19
|
+
|
|
20
|
+
This sets the locale for all calls to the ``Faker`` keyword
|
|
21
|
+
and ``${faker}`` variable. The default is en_US
|
|
22
|
+
|
|
23
|
+
For a list of supported locales see
|
|
24
|
+
[https://faker.readthedocs.io/en/master/locales.html|Localized Providers]
|
|
25
|
+
in the Faker documentation.
|
|
26
|
+
|
|
27
|
+
Example
|
|
28
|
+
|
|
29
|
+
| Set Faker Locale fr_FR
|
|
30
|
+
| ${french_address}= Faker address
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
self._faker = faker.Faker(locale)
|
|
35
|
+
except AttributeError:
|
|
36
|
+
raise Exception(f"Unknown locale for fake data: '{locale}'")
|
|
37
|
+
|
|
38
|
+
def get_fake_data(self, fake, *args, **kwargs):
|
|
39
|
+
"""Return fake data
|
|
40
|
+
|
|
41
|
+
This uses the [https://faker.readthedocs.io/en/master/|Faker]
|
|
42
|
+
library to provide fake data in a variety of formats (names,
|
|
43
|
+
addresses, credit card numbers, dates, phone numbers, etc) and
|
|
44
|
+
locales (en_US, fr_FR, etc).
|
|
45
|
+
|
|
46
|
+
The _fake_ argument is the name of a faker property such as
|
|
47
|
+
``first_name``, ``address``, ``lorem``, etc. Additional
|
|
48
|
+
arguments depend on type of data requested. For a
|
|
49
|
+
comprehensive list of the types of fake data that can be
|
|
50
|
+
generated see
|
|
51
|
+
[https://faker.readthedocs.io/en/master/providers.html|Faker
|
|
52
|
+
providers] in the Faker documentation.
|
|
53
|
+
|
|
54
|
+
The return value is typically a string, though in some cases
|
|
55
|
+
some other type of object will be returned. For example, the
|
|
56
|
+
``date_between`` fake returns a
|
|
57
|
+
[https://docs.python.org/3/library/datetime.html#date-objects|datetime.date
|
|
58
|
+
object]. Each time a piece of fake data is requested it will
|
|
59
|
+
be regenerated, so that multiple calls will usually return
|
|
60
|
+
different data.
|
|
61
|
+
|
|
62
|
+
This keyword can also be called using robot's extended variable
|
|
63
|
+
syntax using the variable ``${faker}``. In such a case, the
|
|
64
|
+
data being asked for is a method call and arguments must be
|
|
65
|
+
enclosed in parentheses and be quoted. Arguments should not be
|
|
66
|
+
quoted when using the keyword.
|
|
67
|
+
|
|
68
|
+
To generate fake data for a locale other than en_US, use
|
|
69
|
+
the keyword ``Set Faker Locale`` prior to calling this keyword.
|
|
70
|
+
|
|
71
|
+
Examples
|
|
72
|
+
|
|
73
|
+
| # Generate a fake first name
|
|
74
|
+
| ${first_name}= Get fake data first_name
|
|
75
|
+
|
|
76
|
+
| # Generate a fake date in the default format
|
|
77
|
+
| ${date}= Get fake data date
|
|
78
|
+
|
|
79
|
+
| # Generate a fake date with an explicit format
|
|
80
|
+
| ${date}= Get fake data date pattern=%Y-%m-%d
|
|
81
|
+
|
|
82
|
+
| # Generate a fake date using extended variable syntax
|
|
83
|
+
| Input text //input ${faker.date(pattern='%Y-%m-%d')}
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
return self._faker.format(fake, *args, **kwargs)
|
|
88
|
+
except AttributeError:
|
|
89
|
+
raise Exception(f"Unknown fake data request: '{fake}'")
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
from robot.libraries.BuiltIn import BuiltIn
|
|
4
|
+
from selenium.common.exceptions import TimeoutException
|
|
5
|
+
|
|
6
|
+
from cumulusci.utils.classutils import get_all_subclasses
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
FIXME: Something that still needs to be resolved is what to do about
|
|
10
|
+
name clashes. What if a project imports two different libraries and
|
|
11
|
+
each library implements a handler for the same tag and/or a handler
|
|
12
|
+
for which a built-in handler already exists. How do we decide what
|
|
13
|
+
takes precedence. Is this even something we have to worry about?
|
|
14
|
+
|
|
15
|
+
So, the idea is to find an element, then do something like
|
|
16
|
+
BaseFormHandler.get_handler(element, locator).set("foo")
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_form_handler(element, locator):
|
|
22
|
+
"""Return an instance of handler for the given element
|
|
23
|
+
|
|
24
|
+
This will search all subclasses of BaseFormHandler, looking
|
|
25
|
+
for a class that supports the tag_name of the given element
|
|
26
|
+
"""
|
|
27
|
+
tag = element.tag_name
|
|
28
|
+
for subclass in get_all_subclasses(BaseFormHandler):
|
|
29
|
+
if tag in subclass.tags:
|
|
30
|
+
# first one wins, but is that the right algorithm? Do
|
|
31
|
+
# we want to give precedence to external handlers
|
|
32
|
+
# over our built-in ones?
|
|
33
|
+
return subclass(element, locator)
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BaseFormHandler(abc.ABC):
|
|
38
|
+
"""Base class for all form handlers
|
|
39
|
+
|
|
40
|
+
The goal is to have each handler implement the methods 'get',
|
|
41
|
+
'set', 'focus', and 'clear'. However, at present we're only using
|
|
42
|
+
'set' externally. 'focus' is the one method that will probably
|
|
43
|
+
have the same implementation for every handler so it's defined in
|
|
44
|
+
the base class. The others are abstract methods which each handler
|
|
45
|
+
should define.
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, element, locator):
|
|
50
|
+
# concrete element to be handled
|
|
51
|
+
self.element = element
|
|
52
|
+
|
|
53
|
+
# the locator used to get the element, which we use for error
|
|
54
|
+
# handling.
|
|
55
|
+
self.locator = locator
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def selenium(self):
|
|
59
|
+
return BuiltIn().get_library_instance("SeleniumLibrary")
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def input_element(self):
|
|
63
|
+
"""Returns the first <input> or <textarea> element inside the element"""
|
|
64
|
+
elements = self.element.find_elements_by_xpath(
|
|
65
|
+
".//*[self::input or self::textarea]"
|
|
66
|
+
)
|
|
67
|
+
return elements[0] if elements else None
|
|
68
|
+
|
|
69
|
+
@abc.abstractmethod
|
|
70
|
+
def set(self, value):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@abc.abstractmethod
|
|
74
|
+
def get(self):
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
@abc.abstractmethod
|
|
78
|
+
def clear(self):
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
def focus(self):
|
|
82
|
+
"""Set focus to the element
|
|
83
|
+
|
|
84
|
+
In addition to merely setting the focus via selenium, we click
|
|
85
|
+
on the element in case there are functions tied to that event.
|
|
86
|
+
"""
|
|
87
|
+
self.selenium.set_focus_to_element(self.element)
|
|
88
|
+
self.element.click()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class HTMLInputHandler(BaseFormHandler):
|
|
92
|
+
"""An input handler for non-lightning input and textarea form fields
|
|
93
|
+
|
|
94
|
+
This is the fallback handler for when we can't find a lightning component.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
tags = ["input", "textarea"]
|
|
98
|
+
|
|
99
|
+
def set(self, value):
|
|
100
|
+
if self.element.get_attribute("type") == "checkbox":
|
|
101
|
+
value = value.lower()
|
|
102
|
+
checked = self.element.is_selected()
|
|
103
|
+
if (checked and value != "checked") or (not checked and value == "checked"):
|
|
104
|
+
self.element.click()
|
|
105
|
+
|
|
106
|
+
elif self.element.get_attribute("type") == "radio":
|
|
107
|
+
if value.strip().lower() != "selected":
|
|
108
|
+
raise Exception("value must be 'selected'")
|
|
109
|
+
self.element.send_keys(" ")
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
self.clear()
|
|
113
|
+
self.element.send_keys(value)
|
|
114
|
+
|
|
115
|
+
def get(self, value):
|
|
116
|
+
# not currently being used
|
|
117
|
+
pass # pragma: no cover
|
|
118
|
+
|
|
119
|
+
def clear(self):
|
|
120
|
+
# Salesforce.py has a crazy amount of code for clearing
|
|
121
|
+
# a field; for now these handlers seem to be working without it.
|
|
122
|
+
self.selenium.driver.execute_script("arguments[0].value = '';", self.element)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class LightningComboboxHandler(BaseFormHandler):
|
|
126
|
+
"""An input handler for comboboxes"""
|
|
127
|
+
|
|
128
|
+
tags = ["lightning-combobox"]
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def input_element(self):
|
|
132
|
+
"""Returns the base form element (input or button) that the combobox is based on"""
|
|
133
|
+
elements = self.element.find_elements_by_xpath(
|
|
134
|
+
".//*[contains(@class, 'slds-combobox__input')]"
|
|
135
|
+
)
|
|
136
|
+
return elements[0] if elements else None
|
|
137
|
+
|
|
138
|
+
def set(self, value):
|
|
139
|
+
value_locator = f'//lightning-base-combobox-item[.="{value}"]'
|
|
140
|
+
wait = 5
|
|
141
|
+
try:
|
|
142
|
+
# at this point, self.input_element is None
|
|
143
|
+
self.input_element.click()
|
|
144
|
+
self.selenium.wait_until_element_is_visible(value_locator, wait)
|
|
145
|
+
self.selenium.click_element(value_locator)
|
|
146
|
+
except Exception:
|
|
147
|
+
raise TimeoutException(
|
|
148
|
+
f"Dropdown value '{value}' for '{self.locator}' not found after {wait} seconds"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
def get(self, value):
|
|
152
|
+
# not currently being used
|
|
153
|
+
pass # pragma: no cover
|
|
154
|
+
|
|
155
|
+
def clear(self):
|
|
156
|
+
# not currently being used
|
|
157
|
+
pass # pragma: no cover
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class LightningInputHandler(BaseFormHandler):
|
|
161
|
+
"""An input handler for components that can be treated as an input or textarea"""
|
|
162
|
+
|
|
163
|
+
tags = [
|
|
164
|
+
"lightning-primitive-input-checkbox",
|
|
165
|
+
"lightning-primitive-input-simple",
|
|
166
|
+
"lightning-textarea",
|
|
167
|
+
"lightning-datepicker",
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
def set(self, value):
|
|
171
|
+
self.focus()
|
|
172
|
+
if self.input_element.get_attribute("type") == "checkbox":
|
|
173
|
+
# lightning-input elements are used for checkboxes
|
|
174
|
+
# as well as free text input.
|
|
175
|
+
checked = self.element.get_attribute("checked")
|
|
176
|
+
if (checked and value != "checked") or (not checked and value == "checked"):
|
|
177
|
+
self.input_element.send_keys(" ")
|
|
178
|
+
|
|
179
|
+
elif self.input_element.get_attribute("type") == "radio":
|
|
180
|
+
if value.strip().lower() != "selected":
|
|
181
|
+
raise Exception("value must be 'selected'")
|
|
182
|
+
self.input_element.send_keys(" ")
|
|
183
|
+
|
|
184
|
+
else:
|
|
185
|
+
self.clear()
|
|
186
|
+
self.input_element.send_keys(value)
|
|
187
|
+
|
|
188
|
+
def get(self, value):
|
|
189
|
+
# not currently being used
|
|
190
|
+
pass # pragma: no cover
|
|
191
|
+
|
|
192
|
+
def clear(self):
|
|
193
|
+
# Salesforce.py has a crazy amount of code for clearing
|
|
194
|
+
# a field; for now these handlers seem to be working without it.
|
|
195
|
+
self.selenium.driver.execute_script("arguments[0].value = '';", self.element)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class LightningLookupHandler(BaseFormHandler):
|
|
199
|
+
tags = ["lightning-lookup", "lightning-grouped-combobox"]
|
|
200
|
+
|
|
201
|
+
def set(self, value):
|
|
202
|
+
wait = 10
|
|
203
|
+
# I wonder if I should/could anchor this to the element
|
|
204
|
+
# instead of searching the whole document?
|
|
205
|
+
value_locator = f'//lightning-base-combobox-formatted-text[@title="{value}"]'
|
|
206
|
+
self.element.click()
|
|
207
|
+
self.input_element.send_keys(value)
|
|
208
|
+
try:
|
|
209
|
+
self.selenium.wait_until_element_is_visible(value_locator, wait)
|
|
210
|
+
self.selenium.click_element(value_locator)
|
|
211
|
+
except Exception:
|
|
212
|
+
raise TimeoutException(
|
|
213
|
+
f"Lookup value '{value}' for '{self.locator}' not found after {wait} seconds"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def get(self, value):
|
|
217
|
+
# not currently being used
|
|
218
|
+
pass # pragma: no cover
|
|
219
|
+
|
|
220
|
+
def clear(self):
|
|
221
|
+
# this is not currently being used
|
|
222
|
+
pass # pragma: no cover
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* This is passed to the Browser library via the jsextension
|
|
2
|
+
parameter when the library is imported.
|
|
3
|
+
|
|
4
|
+
This file will import all modules in the robot/<project
|
|
5
|
+
name>/javascript folder. The code in this file is dependent on an
|
|
6
|
+
environment variable named CCI_CONTEXT, which is initialized by the
|
|
7
|
+
robot task.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
|
|
12
|
+
let cumulusci = require("cumulusci");
|
|
13
|
+
let cci_context = JSON.parse(process.env.CCI_CONTEXT);
|
|
14
|
+
cumulusci.project_config = cci_context.project_config;
|
|
15
|
+
cumulusci.org = cci_context.org;
|
|
16
|
+
|
|
17
|
+
// This is where each project should store their keywords.
|
|
18
|
+
// Maybe in the future this should be configurable, but for
|
|
19
|
+
// now it's not.
|
|
20
|
+
let javascript_dir = `${cci_context.project_config.repo_root}/robot/${cci_context.project_config.repo_name}/javascript`;
|
|
21
|
+
|
|
22
|
+
if (fs.existsSync(javascript_dir)) {
|
|
23
|
+
// Should I put this in a try/catch? If I don't, we get a slightly
|
|
24
|
+
// useful stacktrace in the log, though it's a python stacktrace
|
|
25
|
+
// rather than a javascript one.
|
|
26
|
+
exports.__esModule = true;
|
|
27
|
+
module.exports = {
|
|
28
|
+
...require(javascript_dir),
|
|
29
|
+
...require("cumulusci"),
|
|
30
|
+
};
|
|
31
|
+
} else {
|
|
32
|
+
// this will show up in playwright-log.txt, alongside log.html
|
|
33
|
+
console.info(`no javascript keyword folder found: ${javascript_dir}`);
|
|
34
|
+
}
|