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,45 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class _PageObjectLibrary(object):
|
|
5
|
+
"""
|
|
6
|
+
This uses robot's hybrid library API to create a keyword library
|
|
7
|
+
from any object. All of the methods in the object will be exposed
|
|
8
|
+
as keywords, except for a method named 'get_keyword_names'
|
|
9
|
+
|
|
10
|
+
For example, the following code will create an instance of this class
|
|
11
|
+
with the _obj parameter set to the instance of SomeKeywordClass():
|
|
12
|
+
|
|
13
|
+
keywords = SomeKeywordClass()
|
|
14
|
+
BuiltIn().import_library("PageObjectLibrary", keywords)
|
|
15
|
+
|
|
16
|
+
This isn't designed to be called from test suites. It's for internal
|
|
17
|
+
use only.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
ROBOT_LIBRARY_SCOPE = "TEST SUITE"
|
|
21
|
+
|
|
22
|
+
def __init__(self, obj, libname=None):
|
|
23
|
+
self._obj = obj
|
|
24
|
+
self._libname = libname if libname is not None else obj.__class__.__name__
|
|
25
|
+
|
|
26
|
+
self._keyword_names = sorted(
|
|
27
|
+
[
|
|
28
|
+
member[0]
|
|
29
|
+
for member in inspect.getmembers(obj, inspect.isroutine)
|
|
30
|
+
if (not member[0].startswith("_")) and member[0] != "get_keyword_names"
|
|
31
|
+
]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def get_keyword_names(self):
|
|
35
|
+
return self._keyword_names
|
|
36
|
+
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
return "<{} obj={}>".format(
|
|
39
|
+
self.__class__.__name__, self._obj.__class__.__name__
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def __getattr__(self, item):
|
|
43
|
+
if hasattr(self._obj, item):
|
|
44
|
+
return getattr(self._obj, item)
|
|
45
|
+
raise AttributeError(item)
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import robot.utils
|
|
6
|
+
from robot.api import logger
|
|
7
|
+
from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError
|
|
8
|
+
|
|
9
|
+
from cumulusci.robotframework.pageobjects.baseobjects import BasePage
|
|
10
|
+
from cumulusci.robotframework.utils import capture_screenshot_on_error
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_keyword_names(obj):
|
|
14
|
+
"""Returns a list of method names for the given object
|
|
15
|
+
|
|
16
|
+
This excludes methods that begin with an underscore, and
|
|
17
|
+
also excludes the special method `get_keyword_names`.
|
|
18
|
+
"""
|
|
19
|
+
names = [
|
|
20
|
+
member[0]
|
|
21
|
+
for member in inspect.getmembers(obj, inspect.isroutine)
|
|
22
|
+
if (not member[0].startswith("_")) and member[0] != "get_keyword_names"
|
|
23
|
+
]
|
|
24
|
+
return names
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def pageobject(page_type, object_name=None):
|
|
28
|
+
"""A decorator to designate a class as a page object"""
|
|
29
|
+
BuiltIn().log("importing page object {} {}".format(page_type, object_name), "DEBUG")
|
|
30
|
+
|
|
31
|
+
def wrapper(cls):
|
|
32
|
+
key = (page_type, object_name if object_name else "")
|
|
33
|
+
PageObjects.registry[key] = cls
|
|
34
|
+
cls._page_type = page_type
|
|
35
|
+
if getattr(cls, "_object_name", None) is None:
|
|
36
|
+
cls._object_name = object_name
|
|
37
|
+
else:
|
|
38
|
+
# this page object uses an alias for the object (ie: the name
|
|
39
|
+
# and _object_name do not match). Let's add this object name
|
|
40
|
+
# into the registry so it can be called with either the alias
|
|
41
|
+
# or the actual object name
|
|
42
|
+
alias_key = (page_type, cls._object_name)
|
|
43
|
+
PageObjects.registry[alias_key] = cls
|
|
44
|
+
return cls
|
|
45
|
+
|
|
46
|
+
return wrapper
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PageObjects(object):
|
|
50
|
+
"""Keyword library for importing and using page objects
|
|
51
|
+
|
|
52
|
+
When importing, you can include one or more paths to python
|
|
53
|
+
files that define page objects. For example, if you have a set
|
|
54
|
+
of classes in robot/HEDA/resources/PageObjects.py, you can import
|
|
55
|
+
this library into a test case like this:
|
|
56
|
+
|
|
57
|
+
| Library cumulusci.robotframework.PageObjects
|
|
58
|
+
| ... robot/HEDA/resources/PageObjects.py
|
|
59
|
+
|
|
60
|
+
Page object classes need to use the @pageobject decorator from
|
|
61
|
+
cumulusci.robotframework.pageobjects. The decorator takes two
|
|
62
|
+
parameters: page_type and object_name. Both are arbitrary strings,
|
|
63
|
+
but together should uniquely identify a collection of keywords for
|
|
64
|
+
a page or objects on a page.
|
|
65
|
+
|
|
66
|
+
Examples of page_type are Listing, Home, Detail, etc. Object types
|
|
67
|
+
can be actual object types (Contact), custom object
|
|
68
|
+
(Custom_object__c) or a logical name for a type of page (eg:
|
|
69
|
+
AppointmentManager).
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
|
|
73
|
+
| from cumulusci.robotframework.pageobjects import BasePage
|
|
74
|
+
| from cumulusci.robotframework.pageobjects import pageobject
|
|
75
|
+
| ...
|
|
76
|
+
| @pageobject(page_type="Detail", object_name="Custom__c")
|
|
77
|
+
| class CustomDetailPage(BasePage):
|
|
78
|
+
| ...
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
ROBOT_LIBRARY_SCOPE = "TEST SUITE"
|
|
82
|
+
registry = {}
|
|
83
|
+
|
|
84
|
+
def __init__(self, *args):
|
|
85
|
+
self.builtin = BuiltIn()
|
|
86
|
+
logger.debug("initializing PageObjects...")
|
|
87
|
+
importer = robot.utils.Importer()
|
|
88
|
+
|
|
89
|
+
for file_path in args:
|
|
90
|
+
path = self._find_file_in_pythonpath(file_path)
|
|
91
|
+
if path:
|
|
92
|
+
try:
|
|
93
|
+
importer.import_class_or_module_by_path(str(path.resolve()))
|
|
94
|
+
logger.debug(f"imported page object from {path}")
|
|
95
|
+
except Exception as e:
|
|
96
|
+
raise ImportError(
|
|
97
|
+
f"Unable to import page object '{file_path}': ({e})", path=path
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
else:
|
|
101
|
+
raise ImportError(f"Unable to find page object file '{file_path}'")
|
|
102
|
+
|
|
103
|
+
self.current_page_object = None
|
|
104
|
+
|
|
105
|
+
# Start with this library at the front of the library search order;
|
|
106
|
+
# that may change as page objects are loaded.
|
|
107
|
+
try:
|
|
108
|
+
self.builtin.set_library_search_order("PageObjects")
|
|
109
|
+
except RobotNotRunningError:
|
|
110
|
+
# this should only happen when trying to load this library
|
|
111
|
+
# via the robot_libdoc task, in which case we don't care
|
|
112
|
+
# whether this throws an error or not.
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
def _find_file_in_pythonpath(self, filename):
|
|
116
|
+
for directory in sys.path:
|
|
117
|
+
path = Path(directory) / filename
|
|
118
|
+
if path.exists():
|
|
119
|
+
return path
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def _reset(cls):
|
|
124
|
+
"""Reset the internal data structures used to manage page objects
|
|
125
|
+
|
|
126
|
+
This is to aid testing. It probably shouldn't be used at any other time.
|
|
127
|
+
"""
|
|
128
|
+
for pobj in cls.registry.values():
|
|
129
|
+
if pobj.__module__ in sys.modules:
|
|
130
|
+
del sys.modules[pobj.__module__]
|
|
131
|
+
cls.registry = {}
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def selenium(self):
|
|
135
|
+
return self.builtin.get_library_instance("SeleniumLibrary")
|
|
136
|
+
|
|
137
|
+
def __getattr__(self, name):
|
|
138
|
+
"""Return the keyword from the current page object
|
|
139
|
+
|
|
140
|
+
This method is required by robot's dynamic library api
|
|
141
|
+
"""
|
|
142
|
+
if self.current_page_object is None:
|
|
143
|
+
raise AttributeError(name)
|
|
144
|
+
return getattr(self.current_page_object, name)
|
|
145
|
+
|
|
146
|
+
def get_keyword_names(self):
|
|
147
|
+
"""
|
|
148
|
+
This method is required by robot's dynamic library api
|
|
149
|
+
"""
|
|
150
|
+
names = get_keyword_names(self)
|
|
151
|
+
if self.current_page_object is not None:
|
|
152
|
+
names = names + get_keyword_names(self.current_page_object)
|
|
153
|
+
return names
|
|
154
|
+
|
|
155
|
+
def log_page_object_keywords(self):
|
|
156
|
+
"""Logs page objects and their keywords for all page objects
|
|
157
|
+
which have been imported into the current suite.
|
|
158
|
+
"""
|
|
159
|
+
for key in sorted(self.registry.keys()):
|
|
160
|
+
pobj = self.registry[key]
|
|
161
|
+
keywords = get_keyword_names(pobj)
|
|
162
|
+
logger.info("{}: {}".format(key, ", ".join(keywords)))
|
|
163
|
+
|
|
164
|
+
def get_page_object(self, page_type, object_name):
|
|
165
|
+
"""Return an instance of a page object
|
|
166
|
+
|
|
167
|
+
This is useful if you want to call a single page object method
|
|
168
|
+
from some other keyword without having to go to another page
|
|
169
|
+
or load the page object into a page.
|
|
170
|
+
|
|
171
|
+
This works a lot like robot's built-in "get library instance"
|
|
172
|
+
keyword, but you can specify the page object by page type
|
|
173
|
+
and object name rather than the library name, and it will
|
|
174
|
+
autoload the appropriate library (assuming its module has
|
|
175
|
+
been imported).
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
if (page_type, object_name) in self.registry:
|
|
179
|
+
cls = self.registry[(page_type, object_name)]
|
|
180
|
+
logger.debug(f"using page object class {cls}")
|
|
181
|
+
instance = cls()
|
|
182
|
+
instance._libname = instance.__class__.__name__
|
|
183
|
+
|
|
184
|
+
else:
|
|
185
|
+
# Page object has not been registered. Try to find
|
|
186
|
+
# an appropriate generic class. For example, if
|
|
187
|
+
# the requested page is "Listing", "Contact", look
|
|
188
|
+
# for a "ListingPage" class. If we find it, we'll
|
|
189
|
+
# create a library named "ContactListingPage"
|
|
190
|
+
instance = None
|
|
191
|
+
for subclass in BasePage.__subclasses__():
|
|
192
|
+
if getattr(subclass, "_page_type", None) == page_type:
|
|
193
|
+
instance = subclass(object_name)
|
|
194
|
+
instance._libname = "{}{}Page".format(
|
|
195
|
+
object_name, page_type
|
|
196
|
+
) # eg: ContactListingPageObject
|
|
197
|
+
break
|
|
198
|
+
|
|
199
|
+
if instance is None:
|
|
200
|
+
raise Exception(
|
|
201
|
+
"Unable to find a page object for '{} {}'".format(
|
|
202
|
+
page_type, object_name
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
pobj = self.builtin.get_library_instance(instance._libname)
|
|
208
|
+
|
|
209
|
+
except Exception:
|
|
210
|
+
# Hasn't been imported. Attempt to import it with the given name
|
|
211
|
+
# for the given object; If this fails, just let it bubble up
|
|
212
|
+
# because there's nothing else we can do.
|
|
213
|
+
self.builtin.import_library(
|
|
214
|
+
"cumulusci.robotframework.pageobjects._PageObjectLibrary",
|
|
215
|
+
instance,
|
|
216
|
+
instance._libname,
|
|
217
|
+
"WITH NAME",
|
|
218
|
+
instance._libname,
|
|
219
|
+
)
|
|
220
|
+
# sure would be nice if import_library returned the instance. Just sayin'.
|
|
221
|
+
pobj = self.builtin.get_library_instance(instance._libname)
|
|
222
|
+
|
|
223
|
+
return pobj
|
|
224
|
+
|
|
225
|
+
@capture_screenshot_on_error
|
|
226
|
+
def go_to_page(self, page_type, object_name, *args, **kwargs):
|
|
227
|
+
"""Go to the page of the given page object.
|
|
228
|
+
|
|
229
|
+
The URL will be computed from the page_type and object_name
|
|
230
|
+
associated with the object, plus possibly additional arguments.
|
|
231
|
+
|
|
232
|
+
Different pages support different additional arguments. For
|
|
233
|
+
example, a Listing page supports the keyword argument `filter_name`,
|
|
234
|
+
and a Detail page can be given an object id, or parameters for
|
|
235
|
+
looking up the object id.
|
|
236
|
+
|
|
237
|
+
If this keyword is able to navigate to a page, the keyword
|
|
238
|
+
`load page object` will automatically be called to load the keywords
|
|
239
|
+
for the page.
|
|
240
|
+
|
|
241
|
+
Custom page objects may define the function `_go_to_page`,
|
|
242
|
+
which will be passed in all of the keyword arguments from this
|
|
243
|
+
keyword. This allows each page object to define its own URL
|
|
244
|
+
mapping using whatever algorithm it chooses. The only
|
|
245
|
+
requirement of the function is that it should compute an
|
|
246
|
+
appropriate url and then call `self.selenium.go_to` with the
|
|
247
|
+
URL.
|
|
248
|
+
|
|
249
|
+
It is also recommended that the keyword wait until it knows
|
|
250
|
+
that the page has finished rendering before returning (eg: by
|
|
251
|
+
calling `self.salesforce.wait_until_loading_is_complete()`)
|
|
252
|
+
"""
|
|
253
|
+
pobj = self.get_page_object(page_type, object_name)
|
|
254
|
+
pobj._go_to_page(*args, **kwargs)
|
|
255
|
+
self._set_current_page_object(pobj)
|
|
256
|
+
|
|
257
|
+
@capture_screenshot_on_error
|
|
258
|
+
def current_page_should_be(self, page_type, object_name, **kwargs):
|
|
259
|
+
"""Verifies that the page appears to be the requested page
|
|
260
|
+
|
|
261
|
+
If the page matches the given page object or contains the
|
|
262
|
+
given page object, the keyword will pass.a
|
|
263
|
+
|
|
264
|
+
When this keyword is called, it will try to get the page
|
|
265
|
+
object for the given page_tyope and object_name, and call the
|
|
266
|
+
method `_is_current_page`.
|
|
267
|
+
|
|
268
|
+
Custom page objects may define this function in whatever
|
|
269
|
+
manner is necessary to determine that the current page is or
|
|
270
|
+
contains the given page object. The only requirement is that
|
|
271
|
+
this function raise an exception if it determines the current
|
|
272
|
+
page either doesn't represent the page object or doesn't
|
|
273
|
+
contain the page object.
|
|
274
|
+
|
|
275
|
+
The default implementation of the function uses the page URL
|
|
276
|
+
and compares it to a pattern based off of the page_type and
|
|
277
|
+
object_name.
|
|
278
|
+
|
|
279
|
+
"""
|
|
280
|
+
pobj = self.get_page_object(page_type, object_name)
|
|
281
|
+
pobj._is_current_page(**kwargs)
|
|
282
|
+
self.load_page_object(page_type, object_name)
|
|
283
|
+
|
|
284
|
+
def load_page_object(self, page_type, object_name=None):
|
|
285
|
+
"""Load the keywords for the page object identified by the type and object name
|
|
286
|
+
|
|
287
|
+
The page type / object name pair must have been registered
|
|
288
|
+
using the cumulusci.robotframework.pageobject decorator.
|
|
289
|
+
"""
|
|
290
|
+
pobj = self.get_page_object(page_type, object_name)
|
|
291
|
+
self._set_current_page_object(pobj)
|
|
292
|
+
return pobj
|
|
293
|
+
|
|
294
|
+
@capture_screenshot_on_error
|
|
295
|
+
def wait_for_modal(self, page_type, object_name, expected_heading=None, **kwargs):
|
|
296
|
+
"""Wait for the given page object modal to appear.
|
|
297
|
+
|
|
298
|
+
This will wait for modal to appear. If an expected heading
|
|
299
|
+
is provided, it will also validate that the modal has the
|
|
300
|
+
expected heading.
|
|
301
|
+
|
|
302
|
+
Example:
|
|
303
|
+
|
|
304
|
+
| Wait for modal to appear New Contact expected_heading=New Contact
|
|
305
|
+
|
|
306
|
+
"""
|
|
307
|
+
pobj = self.get_page_object(page_type, object_name)
|
|
308
|
+
pobj._wait_to_appear(expected_heading=expected_heading)
|
|
309
|
+
self._set_current_page_object(pobj)
|
|
310
|
+
# Ideally we would wait for something, but I can't figure out
|
|
311
|
+
# what that would be. A knowledge article simply suggests
|
|
312
|
+
# to wait a second.
|
|
313
|
+
# https://help.salesforce.com/articleView?id=000352057&language=en_US&mode=1&type=1
|
|
314
|
+
|
|
315
|
+
self.builtin.sleep("1 second")
|
|
316
|
+
return pobj
|
|
317
|
+
|
|
318
|
+
@capture_screenshot_on_error
|
|
319
|
+
def wait_for_page_object(self, page_type, object_name, **kwargs):
|
|
320
|
+
"""Wait for an element represented by a page object to appear on the page.
|
|
321
|
+
|
|
322
|
+
The associated page object will be loaded after the element appears.
|
|
323
|
+
|
|
324
|
+
page_type represents the page type (Home, Details, etc)) and
|
|
325
|
+
object_name represents the name of an object (Contact,
|
|
326
|
+
Organization, etc)
|
|
327
|
+
|
|
328
|
+
"""
|
|
329
|
+
pobj = self.get_page_object(page_type, object_name)
|
|
330
|
+
pobj._wait_to_appear()
|
|
331
|
+
self._set_current_page_object(pobj)
|
|
332
|
+
return pobj
|
|
333
|
+
|
|
334
|
+
def _set_current_page_object(self, pobj):
|
|
335
|
+
"""This does the work of importing the keywords for the given page object
|
|
336
|
+
|
|
337
|
+
Multiple page objects may be loaded. Each page object will be added
|
|
338
|
+
to the front of robot's library search order. Note: this search order
|
|
339
|
+
gets reset at the start of every suite.
|
|
340
|
+
"""
|
|
341
|
+
|
|
342
|
+
self.current_page_object = pobj
|
|
343
|
+
libname = pobj._libname
|
|
344
|
+
|
|
345
|
+
old_order = list(self.builtin.set_library_search_order())
|
|
346
|
+
if libname in old_order:
|
|
347
|
+
old_order.remove(libname)
|
|
348
|
+
new_order = [libname] + old_order
|
|
349
|
+
self.builtin.log("new search order: {}".format(new_order), "DEBUG")
|
|
350
|
+
self.builtin.set_library_search_order(*new_order)
|
|
351
|
+
return pobj
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .PageObjects import PageObjects # noqa: F401
|
|
2
|
+
from .baseobjects import BasePage # noqa: F401
|
|
3
|
+
from .PageObjectLibrary import _PageObjectLibrary # noqa: F401
|
|
4
|
+
from .PageObjects import pageobject # noqa: F401
|
|
5
|
+
from .BasePageObjects import ( # noqa: F401
|
|
6
|
+
ListingPage,
|
|
7
|
+
HomePage,
|
|
8
|
+
DetailPage,
|
|
9
|
+
NewModal,
|
|
10
|
+
EditModal,
|
|
11
|
+
)
|
|
12
|
+
from .ObjectManagerPageObject import ObjectManagerPage # noqa: F401
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
|
|
3
|
+
from cumulusci.robotframework.base_library import BaseLibrary
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BasePage(BaseLibrary):
|
|
7
|
+
_object_name = None
|
|
8
|
+
|
|
9
|
+
def __init__(self, object_name=None):
|
|
10
|
+
super().__init__()
|
|
11
|
+
if object_name:
|
|
12
|
+
self._object_name = object_name
|
|
13
|
+
|
|
14
|
+
@contextmanager
|
|
15
|
+
def _no_implicit_wait(self):
|
|
16
|
+
"""Context manager for running selenium commands without an implicit wait"""
|
|
17
|
+
current_wait = self.selenium.set_selenium_implicit_wait(0)
|
|
18
|
+
try:
|
|
19
|
+
yield
|
|
20
|
+
finally:
|
|
21
|
+
self.selenium.set_selenium_implicit_wait(current_wait)
|
|
22
|
+
|
|
23
|
+
def _wait_to_appear(self, *args, timeout="15s"):
|
|
24
|
+
"""This is the concrete implementation for the 'Wait for page object' keyword
|
|
25
|
+
|
|
26
|
+
It can be overridden by a subclass to do whatever is necessary to
|
|
27
|
+
wait for itself to appear.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
self.selenium.wait_for_condition(
|
|
32
|
+
"return (document.readyState == 'complete')"
|
|
33
|
+
)
|
|
34
|
+
self.salesforce.wait_for_aura()
|
|
35
|
+
self.builtin.wait_until_keyword_succeeds(
|
|
36
|
+
timeout,
|
|
37
|
+
"2s",
|
|
38
|
+
"Current page should be",
|
|
39
|
+
self._page_type,
|
|
40
|
+
self._object_name,
|
|
41
|
+
)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
self.builtin.log(e, "DEBUG")
|
|
44
|
+
raise Exception(
|
|
45
|
+
f"Page object {self._page_type} {self._object_name} did not appear before timeout ({timeout}) expired."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def _remove_from_library_search_order(self):
|
|
49
|
+
"""Remove the current page object from robot's library search order
|
|
50
|
+
|
|
51
|
+
Note: robot doesn't provide a way to completely unload a
|
|
52
|
+
library during execution. However, this at least makes sure that
|
|
53
|
+
all other libraries will have priority over this one.
|
|
54
|
+
"""
|
|
55
|
+
order = list(self.builtin.set_library_search_order())
|
|
56
|
+
if self._libname in order:
|
|
57
|
+
order.remove(self._libname)
|
|
58
|
+
self.builtin.set_library_search_order(*order)
|
|
59
|
+
self.builtin.log("new search order: {}".format(order), "DEBUG")
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def object_name(self):
|
|
63
|
+
object_name = self._object_name
|
|
64
|
+
|
|
65
|
+
# the length check is to skip objects from a different namespace
|
|
66
|
+
# like foobar__otherpackageobject__c
|
|
67
|
+
if object_name is not None:
|
|
68
|
+
parts = object_name.split("__")
|
|
69
|
+
if len(parts) == 2 and parts[-1] == "c":
|
|
70
|
+
# get_namespace_prefix already takes care of returning an actual
|
|
71
|
+
# prefix or an empty string depending on whether the package is managed
|
|
72
|
+
object_name = "{}{}".format(
|
|
73
|
+
self.cumulusci.get_namespace_prefix(), object_name
|
|
74
|
+
)
|
|
75
|
+
return object_name
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def selenium(self):
|
|
79
|
+
"""Returns the instance of the imported SeleniumLibrary library"""
|
|
80
|
+
return self.builtin.get_library_instance("SeleniumLibrary")
|
|
81
|
+
|
|
82
|
+
def _get_object(self, **kwargs):
|
|
83
|
+
"""Get the object associated with the given keyword arguments.
|
|
84
|
+
|
|
85
|
+
This performs a salesforce query. It will raise an exception unless
|
|
86
|
+
exactly one result is returned from the query.
|
|
87
|
+
"""
|
|
88
|
+
results = self.salesforce_api.salesforce_query(self.object_name, **kwargs)
|
|
89
|
+
if len(results) == 0:
|
|
90
|
+
human_friendly_args = ", ".join(
|
|
91
|
+
["{}={}".format(key, kwargs[key]) for key in kwargs]
|
|
92
|
+
)
|
|
93
|
+
raise Exception(
|
|
94
|
+
"no {} matches {}".format(self.object_name, human_friendly_args)
|
|
95
|
+
)
|
|
96
|
+
elif len(results) > 1:
|
|
97
|
+
raise Exception("Query returned {} objects".format(len(results)))
|
|
98
|
+
else:
|
|
99
|
+
return results[0]
|
|
100
|
+
|
|
101
|
+
def log_current_page_object(self):
|
|
102
|
+
"""Logs the name of the current page object
|
|
103
|
+
|
|
104
|
+
The current page object is also returned as an object
|
|
105
|
+
"""
|
|
106
|
+
polib = self.builtin.get_library_instance(
|
|
107
|
+
"cumulusci.robotframework.PageObjects"
|
|
108
|
+
)
|
|
109
|
+
if polib.current_page_object is None:
|
|
110
|
+
# this should not be possible, since this keyword is only available
|
|
111
|
+
# if you've loaded a page object. Still, better safe then sorry.
|
|
112
|
+
self.builtin.log("no page object has been loaded")
|
|
113
|
+
return None
|
|
114
|
+
else:
|
|
115
|
+
pobj = polib.current_page_object
|
|
116
|
+
|
|
117
|
+
self.builtin.log(
|
|
118
|
+
"current page object: {}".format(polib.current_page_object)
|
|
119
|
+
)
|
|
120
|
+
return pobj
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
*** Settings ***
|
|
2
|
+
Documentation Tests of collections of records based on Jess Lopez's recommendations
|
|
3
|
+
... Note that keywords referenced in Setup are NOT performance measured.
|
|
4
|
+
Library DateTime
|
|
5
|
+
Resource cumulusci/robotframework/Salesforce.robot
|
|
6
|
+
# Suite Teardown Delete Session Records
|
|
7
|
+
Force Tags api200
|
|
8
|
+
|
|
9
|
+
*** Keywords ***
|
|
10
|
+
Insert 200 Contacts
|
|
11
|
+
[Documentation] Create 200 Contacts in CONTACTS suite variable
|
|
12
|
+
@{objects}= Generate Test Data Contact 200
|
|
13
|
+
... FirstName=User {{number}}
|
|
14
|
+
... LastName={{fake.last_name}}
|
|
15
|
+
Salesforce Collection Insert ${objects}
|
|
16
|
+
Set Suite Variable @{CONTACTS} @{objects}
|
|
17
|
+
[return] ${objects}
|
|
18
|
+
|
|
19
|
+
Create Accounts If Necessary
|
|
20
|
+
[Documentation] Create 200 Accounts corresponding to CONTACTS suite variable
|
|
21
|
+
... and update the contacts to connect to them
|
|
22
|
+
${idlist} = Evaluate ",".join([f"'{contact['id']}'" for contact in $CONTACTS])
|
|
23
|
+
${query} = Set Variable SELECT id FROM Contact WHERE AccountId=null AND id in (${idlist})
|
|
24
|
+
${query_results} = SOQL Query ${query}
|
|
25
|
+
${contacts_without_accounts} = Set Variable ${query_results}[records]
|
|
26
|
+
${numobjects} = Get Length ${contacts_without_accounts}
|
|
27
|
+
${newobjects} = Generate Test Data Account ${numobjects}
|
|
28
|
+
... Name={{fake.name}}
|
|
29
|
+
|
|
30
|
+
${created_records}= Salesforce Collection Insert ${newobjects}
|
|
31
|
+
|
|
32
|
+
FOR ${index} IN RANGE ${numobjects}
|
|
33
|
+
${contact} = Set Variable ${contacts_without_accounts}[${index}]
|
|
34
|
+
${account_id} = Set Variable ${created_records}[${index}][id]
|
|
35
|
+
Set To Dictionary ${contact} 'AccountId' ${account_id}
|
|
36
|
+
END
|
|
37
|
+
|
|
38
|
+
Salesforce Collection Update ${CONTACTS}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Insert 200 Prospecting Opportunities
|
|
42
|
+
[Documentation] Create 200 Opportunities in OPPORTUNITIES suite variable
|
|
43
|
+
... Associate with accounts queried from Salesforce
|
|
44
|
+
... These may have been created by ``Create Accounts If Necessary``
|
|
45
|
+
... or may have been created automatically by a package like NPSP.
|
|
46
|
+
Create Accounts If Necessary
|
|
47
|
+
@{accounts}= Salesforce Query Account
|
|
48
|
+
|
|
49
|
+
${date}= Get Current Date result_format=%Y-%m-%d
|
|
50
|
+
@{objects}= Generate Test Data Opportunity 200
|
|
51
|
+
... Name=Opp {{number}}
|
|
52
|
+
... StageName=Prospecting
|
|
53
|
+
... Amount={{1000 + number}}
|
|
54
|
+
... CloseDate=${date}
|
|
55
|
+
${numobjects}= Get Length ${objects}
|
|
56
|
+
FOR ${index} IN RANGE ${numobjects}
|
|
57
|
+
${object}= Set Variable ${objects}[${index}]
|
|
58
|
+
${account}= Set Variable ${accounts}[${index}]
|
|
59
|
+
${account_id}= Set Variable ${account}[Id]
|
|
60
|
+
set to dictionary ${object} AccountId ${account_id}
|
|
61
|
+
END
|
|
62
|
+
|
|
63
|
+
Salesforce Collection Insert ${objects}
|
|
64
|
+
Set Suite Variable @{OPPORTUNITIES} @{objects}
|
|
65
|
+
|
|
66
|
+
*** Test Cases ***
|
|
67
|
+
|
|
68
|
+
Perftest - Insert 200 Contacts
|
|
69
|
+
Start Performance Timer
|
|
70
|
+
Insert 200 Contacts
|
|
71
|
+
Stop Performance Timer
|
|
72
|
+
|
|
73
|
+
Perftest - Insert 200 Contacts With Addresses
|
|
74
|
+
Start Performance Timer
|
|
75
|
+
@{objects}= Generate Test Data Contact 200
|
|
76
|
+
... FirstName={{fake.first_name}}
|
|
77
|
+
... LastName={{fake.last_name}}
|
|
78
|
+
... MailingStreet={{fake.street_address}}
|
|
79
|
+
... MailingCity=New York
|
|
80
|
+
... MailingState=NY
|
|
81
|
+
... MailingPostalCode=12345
|
|
82
|
+
... Email={{fake.email(domain="salesforce.com")}}
|
|
83
|
+
Salesforce Collection Insert ${objects}
|
|
84
|
+
Stop Performance Timer
|
|
85
|
+
|
|
86
|
+
Perftest - Insert 200 Prospecting Opportunities
|
|
87
|
+
Start Performance Timer
|
|
88
|
+
[Setup] Run Keywords
|
|
89
|
+
... Insert 200 Contacts
|
|
90
|
+
... AND Create Accounts If Necessary
|
|
91
|
+
Insert 200 Prospecting Opportunities
|
|
92
|
+
Stop Performance Timer
|
|
93
|
+
|
|
94
|
+
Perftest - Change 200 Opportunity States to Closed-Won
|
|
95
|
+
Start Performance Timer
|
|
96
|
+
[Setup] Run Keywords
|
|
97
|
+
... Insert 200 Contacts
|
|
98
|
+
... AND Create Accounts If Necessary
|
|
99
|
+
... AND Insert 200 Prospecting Opportunities
|
|
100
|
+
|
|
101
|
+
FOR ${record} IN @{OPPORTUNITIES}
|
|
102
|
+
Set To Dictionary ${record} StageName Closed Won
|
|
103
|
+
END
|
|
104
|
+
Salesforce Collection Update ${OPPORTUNITIES}
|
|
105
|
+
Stop Performance Timer
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This class is used by test_pageobjects
|
|
3
|
+
"""
|
|
4
|
+
from cumulusci.robotframework.pageobjects import ListingPage, pageobject
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# The point of this class is to test out using an alias
|
|
8
|
+
@pageobject(page_type="Listing", object_name="Custom Object")
|
|
9
|
+
class CustomObjectListingPage(ListingPage):
|
|
10
|
+
_object_name = "CustomObject__c"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from cumulusci.robotframework.pageobjects import BasePage, pageobject
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@pageobject(page_type="Test", object_name="Foo__c")
|
|
5
|
+
class FooTestPage(BasePage):
|
|
6
|
+
def foo_keyword_1(self, message):
|
|
7
|
+
self.builtin.log(message)
|
|
8
|
+
return "foo keyword 1: {}".format(message)
|