regscale-cli 6.21.2.0__py3-none-any.whl → 6.28.2.1__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.
- regscale/_version.py +1 -1
- regscale/airflow/hierarchy.py +2 -2
- regscale/core/app/api.py +5 -2
- regscale/core/app/application.py +36 -6
- regscale/core/app/internal/control_editor.py +73 -21
- regscale/core/app/internal/evidence.py +727 -204
- regscale/core/app/internal/login.py +4 -2
- regscale/core/app/internal/model_editor.py +219 -64
- regscale/core/app/utils/app_utils.py +86 -12
- regscale/core/app/utils/catalog_utils/common.py +1 -1
- regscale/core/login.py +21 -4
- regscale/core/utils/async_graphql_client.py +363 -0
- regscale/core/utils/date.py +77 -1
- regscale/dev/cli.py +26 -0
- regscale/dev/code_gen.py +109 -24
- regscale/dev/version.py +72 -0
- regscale/integrations/commercial/__init__.py +30 -2
- regscale/integrations/commercial/aws/audit_manager_compliance.py +3908 -0
- regscale/integrations/commercial/aws/cli.py +3107 -54
- regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
- regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
- regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
- regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
- regscale/integrations/commercial/{amazon → aws}/common.py +71 -19
- regscale/integrations/commercial/aws/config_compliance.py +914 -0
- regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
- regscale/integrations/commercial/aws/control_compliance_analyzer.py +439 -0
- regscale/integrations/commercial/aws/evidence_generator.py +283 -0
- regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
- regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
- regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
- regscale/integrations/commercial/aws/iam_evidence.py +574 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +338 -22
- regscale/integrations/commercial/aws/inventory/base.py +107 -5
- regscale/integrations/commercial/aws/inventory/resources/analytics.py +390 -0
- regscale/integrations/commercial/aws/inventory/resources/applications.py +234 -0
- regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +328 -9
- regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
- regscale/integrations/commercial/aws/inventory/resources/database.py +481 -31
- regscale/integrations/commercial/aws/inventory/resources/developer_tools.py +253 -0
- regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
- regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
- regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
- regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
- regscale/integrations/commercial/aws/inventory/resources/machine_learning.py +358 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +390 -67
- regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
- regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +288 -29
- regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
- regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
- regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
- regscale/integrations/commercial/aws/kms_evidence.py +879 -0
- regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
- regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
- regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
- regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
- regscale/integrations/commercial/aws/org_evidence.py +666 -0
- regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
- regscale/integrations/commercial/aws/s3_evidence.py +632 -0
- regscale/integrations/commercial/aws/scanner.py +1072 -205
- regscale/integrations/commercial/aws/security_hub.py +319 -0
- regscale/integrations/commercial/aws/session_manager.py +282 -0
- regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
- regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
- regscale/integrations/commercial/jira.py +489 -153
- regscale/integrations/commercial/microsoft_defender/defender.py +326 -5
- regscale/integrations/commercial/microsoft_defender/defender_api.py +348 -14
- regscale/integrations/commercial/microsoft_defender/defender_constants.py +157 -0
- regscale/integrations/commercial/qualys/__init__.py +167 -68
- regscale/integrations/commercial/qualys/scanner.py +305 -39
- regscale/integrations/commercial/sarif/sairf_importer.py +432 -0
- regscale/integrations/commercial/sarif/sarif_converter.py +67 -0
- regscale/integrations/commercial/sicura/api.py +79 -42
- regscale/integrations/commercial/sicura/commands.py +8 -2
- regscale/integrations/commercial/sicura/scanner.py +83 -44
- regscale/integrations/commercial/stigv2/ckl_parser.py +5 -5
- regscale/integrations/commercial/synqly/assets.py +133 -16
- regscale/integrations/commercial/synqly/edr.py +2 -8
- regscale/integrations/commercial/synqly/query_builder.py +536 -0
- regscale/integrations/commercial/synqly/ticketing.py +27 -0
- regscale/integrations/commercial/synqly/vulnerabilities.py +165 -28
- regscale/integrations/commercial/tenablev2/cis_parsers.py +453 -0
- regscale/integrations/commercial/tenablev2/cis_scanner.py +447 -0
- regscale/integrations/commercial/tenablev2/commands.py +146 -5
- regscale/integrations/commercial/tenablev2/scanner.py +1 -3
- regscale/integrations/commercial/tenablev2/stig_parsers.py +113 -57
- regscale/integrations/commercial/wizv2/WizDataMixin.py +1 -1
- regscale/integrations/commercial/wizv2/click.py +191 -76
- regscale/integrations/commercial/wizv2/compliance/__init__.py +15 -0
- regscale/integrations/commercial/wizv2/{policy_compliance_helpers.py → compliance/helpers.py} +78 -60
- regscale/integrations/commercial/wizv2/compliance_report.py +1592 -0
- regscale/integrations/commercial/wizv2/core/__init__.py +133 -0
- regscale/integrations/commercial/wizv2/{async_client.py → core/client.py} +7 -3
- regscale/integrations/commercial/wizv2/{constants.py → core/constants.py} +92 -89
- regscale/integrations/commercial/wizv2/core/file_operations.py +237 -0
- regscale/integrations/commercial/wizv2/fetchers/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{data_fetcher.py → fetchers/policy_assessment.py} +66 -9
- regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
- regscale/integrations/commercial/wizv2/issue.py +776 -28
- regscale/integrations/commercial/wizv2/models/__init__.py +0 -0
- regscale/integrations/commercial/wizv2/parsers/__init__.py +34 -0
- regscale/integrations/commercial/wizv2/{parsers.py → parsers/main.py} +1 -1
- regscale/integrations/commercial/wizv2/processors/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{finding_processor.py → processors/finding.py} +1 -1
- regscale/integrations/commercial/wizv2/reports.py +243 -0
- regscale/integrations/commercial/wizv2/sbom.py +1 -1
- regscale/integrations/commercial/wizv2/scanner.py +1031 -441
- regscale/integrations/commercial/wizv2/utils/__init__.py +48 -0
- regscale/integrations/commercial/wizv2/{utils.py → utils/main.py} +116 -61
- regscale/integrations/commercial/wizv2/variables.py +89 -3
- regscale/integrations/compliance_integration.py +1036 -151
- regscale/integrations/control_matcher.py +432 -0
- regscale/integrations/due_date_handler.py +333 -0
- regscale/integrations/milestone_manager.py +291 -0
- regscale/integrations/public/__init__.py +14 -0
- regscale/integrations/public/cci_importer.py +834 -0
- regscale/integrations/public/csam/__init__.py +0 -0
- regscale/integrations/public/csam/csam.py +938 -0
- regscale/integrations/public/csam/csam_agency_defined.py +179 -0
- regscale/integrations/public/csam/csam_common.py +154 -0
- regscale/integrations/public/csam/csam_controls.py +432 -0
- regscale/integrations/public/csam/csam_poam.py +124 -0
- regscale/integrations/public/fedramp/click.py +77 -6
- regscale/integrations/public/fedramp/docx_parser.py +10 -1
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +675 -289
- regscale/integrations/public/fedramp/fedramp_five.py +1 -1
- regscale/integrations/public/fedramp/poam/scanner.py +75 -7
- regscale/integrations/public/fedramp/poam_export_v5.py +888 -0
- regscale/integrations/scanner_integration.py +1961 -430
- regscale/models/integration_models/CCI_List.xml +1 -0
- regscale/models/integration_models/aqua.py +2 -2
- regscale/models/integration_models/cisa_kev_data.json +805 -11
- regscale/models/integration_models/flat_file_importer/__init__.py +5 -8
- regscale/models/integration_models/nexpose.py +36 -10
- regscale/models/integration_models/qualys.py +3 -4
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +87 -18
- regscale/models/integration_models/synqly_models/filter_parser.py +332 -0
- regscale/models/integration_models/synqly_models/ocsf_mapper.py +124 -25
- regscale/models/integration_models/synqly_models/synqly_model.py +89 -16
- regscale/models/locking.py +12 -8
- regscale/models/platform.py +4 -2
- regscale/models/regscale_models/__init__.py +7 -0
- regscale/models/regscale_models/assessment.py +2 -1
- regscale/models/regscale_models/catalog.py +1 -1
- regscale/models/regscale_models/compliance_settings.py +251 -1
- regscale/models/regscale_models/component.py +1 -0
- regscale/models/regscale_models/control_implementation.py +236 -41
- regscale/models/regscale_models/control_objective.py +74 -5
- regscale/models/regscale_models/file.py +2 -0
- regscale/models/regscale_models/form_field_value.py +5 -3
- regscale/models/regscale_models/inheritance.py +44 -0
- regscale/models/regscale_models/issue.py +301 -102
- regscale/models/regscale_models/milestone.py +33 -14
- regscale/models/regscale_models/organization.py +3 -0
- regscale/models/regscale_models/regscale_model.py +310 -73
- regscale/models/regscale_models/security_plan.py +4 -2
- regscale/models/regscale_models/vulnerability.py +3 -3
- regscale/regscale.py +25 -4
- regscale/templates/__init__.py +0 -0
- regscale/utils/threading/threadhandler.py +20 -15
- regscale/validation/record.py +23 -1
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/METADATA +17 -33
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/RECORD +310 -111
- tests/core/__init__.py +0 -0
- tests/core/utils/__init__.py +0 -0
- tests/core/utils/test_async_graphql_client.py +472 -0
- tests/fixtures/test_fixture.py +13 -8
- tests/regscale/core/test_login.py +171 -4
- tests/regscale/integrations/commercial/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
- tests/regscale/integrations/commercial/aws/test_aws_analytics_collector.py +260 -0
- tests/regscale/integrations/commercial/aws/test_aws_applications_collector.py +242 -0
- tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
- tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
- tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
- tests/regscale/integrations/commercial/aws/test_aws_developer_tools_collector.py +203 -0
- tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
- tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
- tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
- tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
- tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
- tests/regscale/integrations/commercial/aws/test_aws_machine_learning_collector.py +237 -0
- tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
- tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
- tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
- tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
- tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
- tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
- tests/regscale/integrations/commercial/aws/test_control_compliance_analyzer.py +375 -0
- tests/regscale/integrations/commercial/aws/test_datetime_parsing.py +223 -0
- tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
- tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
- tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
- tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
- tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
- tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
- tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
- tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
- tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
- tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
- tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
- tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
- tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
- tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
- tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
- tests/regscale/integrations/commercial/conftest.py +28 -0
- tests/regscale/integrations/commercial/microsoft_defender/__init__.py +1 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender.py +1517 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_api.py +1748 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_constants.py +327 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_scanner.py +487 -0
- tests/regscale/integrations/commercial/test_aws.py +3742 -0
- tests/regscale/integrations/commercial/test_burp.py +48 -0
- tests/regscale/integrations/commercial/test_crowdstrike.py +49 -0
- tests/regscale/integrations/commercial/test_dependabot.py +341 -0
- tests/regscale/integrations/commercial/test_gcp.py +1543 -0
- tests/regscale/integrations/commercial/test_gitlab.py +549 -0
- tests/regscale/integrations/commercial/test_ip_mac_address_length.py +84 -0
- tests/regscale/integrations/commercial/test_jira.py +2204 -0
- tests/regscale/integrations/commercial/test_npm_audit.py +42 -0
- tests/regscale/integrations/commercial/test_okta.py +1228 -0
- tests/regscale/integrations/commercial/test_sarif_converter.py +251 -0
- tests/regscale/integrations/commercial/test_sicura.py +349 -0
- tests/regscale/integrations/commercial/test_snow.py +423 -0
- tests/regscale/integrations/commercial/test_sonarcloud.py +394 -0
- tests/regscale/integrations/commercial/test_sqlserver.py +186 -0
- tests/regscale/integrations/commercial/test_stig.py +33 -0
- tests/regscale/integrations/commercial/test_stig_mapper.py +153 -0
- tests/regscale/integrations/commercial/test_stigv2.py +406 -0
- tests/regscale/integrations/commercial/test_wiz.py +1365 -0
- tests/regscale/integrations/commercial/test_wiz_inventory.py +256 -0
- tests/regscale/integrations/commercial/wizv2/__init__.py +339 -0
- tests/regscale/integrations/commercial/wizv2/compliance/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/compliance/test_helpers.py +903 -0
- tests/regscale/integrations/commercial/wizv2/core/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/core/test_auth.py +701 -0
- tests/regscale/integrations/commercial/wizv2/core/test_client.py +1037 -0
- tests/regscale/integrations/commercial/wizv2/core/test_file_operations.py +989 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/test_policy_assessment.py +805 -0
- tests/regscale/integrations/commercial/wizv2/parsers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/parsers/test_main.py +1153 -0
- tests/regscale/integrations/commercial/wizv2/processors/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/processors/test_finding.py +671 -0
- tests/regscale/integrations/commercial/wizv2/test_WizDataMixin.py +537 -0
- tests/regscale/integrations/commercial/wizv2/test_click_comprehensive.py +851 -0
- tests/regscale/integrations/commercial/wizv2/test_compliance_report_comprehensive.py +910 -0
- tests/regscale/integrations/commercial/wizv2/test_compliance_report_normalization.py +138 -0
- tests/regscale/integrations/commercial/wizv2/test_file_cleanup.py +283 -0
- tests/regscale/integrations/commercial/wizv2/test_file_operations.py +260 -0
- tests/regscale/integrations/commercial/wizv2/test_issue.py +343 -0
- tests/regscale/integrations/commercial/wizv2/test_issue_comprehensive.py +1203 -0
- tests/regscale/integrations/commercial/wizv2/test_reports.py +497 -0
- tests/regscale/integrations/commercial/wizv2/test_sbom.py +643 -0
- tests/regscale/integrations/commercial/wizv2/test_scanner_comprehensive.py +805 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_click_client_id.py +165 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_report.py +1394 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_unit.py +341 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_control_normalization.py +138 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_findings_comprehensive.py +364 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_inventory_comprehensive.py +644 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_status_mapping.py +149 -0
- tests/regscale/integrations/commercial/wizv2/test_wizv2.py +1218 -0
- tests/regscale/integrations/commercial/wizv2/test_wizv2_utils.py +519 -0
- tests/regscale/integrations/commercial/wizv2/utils/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/utils/test_main.py +1523 -0
- tests/regscale/integrations/public/__init__.py +0 -0
- tests/regscale/integrations/public/fedramp/__init__.py +1 -0
- tests/regscale/integrations/public/fedramp/test_gen_asset_list.py +150 -0
- tests/regscale/integrations/public/fedramp/test_poam_export_v5.py +1293 -0
- tests/regscale/integrations/public/test_alienvault.py +220 -0
- tests/regscale/integrations/public/test_cci.py +1053 -0
- tests/regscale/integrations/public/test_cisa.py +1021 -0
- tests/regscale/integrations/public/test_emass.py +518 -0
- tests/regscale/integrations/public/test_fedramp.py +1152 -0
- tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
- tests/regscale/integrations/public/test_file_uploads.py +506 -0
- tests/regscale/integrations/public/test_oscal.py +453 -0
- tests/regscale/integrations/test_compliance_status_mapping.py +406 -0
- tests/regscale/integrations/test_control_matcher.py +1421 -0
- tests/regscale/integrations/test_control_matching.py +155 -0
- tests/regscale/integrations/test_milestone_manager.py +408 -0
- tests/regscale/models/test_control_implementation.py +118 -3
- tests/regscale/models/test_form_field_value_integration.py +304 -0
- tests/regscale/models/test_issue.py +378 -1
- tests/regscale/models/test_module_integration.py +582 -0
- tests/regscale/models/test_tenable_integrations.py +811 -105
- regscale/integrations/commercial/wizv2/policy_compliance.py +0 -3057
- regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +0 -7388
- regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +0 -9605
- regscale/integrations/public/fedramp/parts_mapper.py +0 -107
- /regscale/integrations/commercial/{amazon → sarif}/__init__.py +0 -0
- /regscale/integrations/commercial/wizv2/{wiz_auth.py → core/auth.py} +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/LICENSE +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/WHEEL +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
from unittest.mock import MagicMock, patch
|
|
3
3
|
|
|
4
|
+
from regscale.core.app.application import Application
|
|
4
5
|
from regscale.models import ControlImplementation
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class TestControlImplementation(unittest.TestCase):
|
|
8
|
-
@patch("regscale.models.regscale_models.control_implementation.ControlImplementation._get_api_handler
|
|
9
|
-
def test_get_control_map_by_plan_lower_case_keys(self,
|
|
9
|
+
@patch("regscale.models.regscale_models.control_implementation.ControlImplementation._get_api_handler")
|
|
10
|
+
def test_get_control_map_by_plan_lower_case_keys(self, mock_api_handler):
|
|
10
11
|
# Create a mock response object with 'ok' attribute and 'json' method
|
|
11
12
|
mock_response = MagicMock()
|
|
12
13
|
mock_response.ok = True
|
|
@@ -15,7 +16,10 @@ class TestControlImplementation(unittest.TestCase):
|
|
|
15
16
|
{"control": {"controlId": "AC-6"}, "id": 2},
|
|
16
17
|
]
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
# Set up the mock API handler to return the mock response when .get() is called
|
|
20
|
+
mock_handler = MagicMock()
|
|
21
|
+
mock_handler.get.return_value = mock_response
|
|
22
|
+
mock_api_handler.return_value = mock_handler
|
|
19
23
|
|
|
20
24
|
# Expected result should have lower case control IDs as keys
|
|
21
25
|
expected_result = {"ca-1": 1, "ac-6": 2}
|
|
@@ -25,3 +29,114 @@ class TestControlImplementation(unittest.TestCase):
|
|
|
25
29
|
|
|
26
30
|
# Assert that the result matches the expected result
|
|
27
31
|
self.assertEqual(result, expected_result)
|
|
32
|
+
|
|
33
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
34
|
+
def test_get_export_query_with_none_control_owner(self, mock_graph):
|
|
35
|
+
"""Test get_export_query handles None controlOwner gracefully."""
|
|
36
|
+
# Mock API response with None controlOwner
|
|
37
|
+
mock_graph.return_value = {
|
|
38
|
+
"controlImplementations": {
|
|
39
|
+
"totalCount": 1,
|
|
40
|
+
"items": [
|
|
41
|
+
{
|
|
42
|
+
"id": 1,
|
|
43
|
+
"controlID": 100,
|
|
44
|
+
"controlOwner": None, # None control owner
|
|
45
|
+
"control": {
|
|
46
|
+
"title": "Test Control",
|
|
47
|
+
"description": "Test Description",
|
|
48
|
+
"controlId": "AC-1",
|
|
49
|
+
},
|
|
50
|
+
"status": "Implemented",
|
|
51
|
+
"policy": "Test Policy",
|
|
52
|
+
"implementation": "Test Implementation",
|
|
53
|
+
"responsibility": "Provider",
|
|
54
|
+
"inheritable": True,
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Call the method under test
|
|
61
|
+
app = Application()
|
|
62
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
63
|
+
|
|
64
|
+
# Verify the result handles None gracefully
|
|
65
|
+
self.assertEqual(len(result), 1)
|
|
66
|
+
self.assertEqual(result[0]["controlOwnerId"], "Unassigned")
|
|
67
|
+
|
|
68
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
69
|
+
def test_get_export_query_with_none_control(self, mock_graph):
|
|
70
|
+
"""Test get_export_query handles None control gracefully."""
|
|
71
|
+
# Mock API response with None control
|
|
72
|
+
mock_graph.return_value = {
|
|
73
|
+
"controlImplementations": {
|
|
74
|
+
"totalCount": 1,
|
|
75
|
+
"items": [
|
|
76
|
+
{
|
|
77
|
+
"id": 1,
|
|
78
|
+
"controlID": 100,
|
|
79
|
+
"controlOwner": {
|
|
80
|
+
"firstName": "John",
|
|
81
|
+
"lastName": "Doe",
|
|
82
|
+
"userName": "jdoe",
|
|
83
|
+
},
|
|
84
|
+
"control": None, # None control
|
|
85
|
+
"status": "Implemented",
|
|
86
|
+
"policy": "Test Policy",
|
|
87
|
+
"implementation": "Test Implementation",
|
|
88
|
+
"responsibility": "Provider",
|
|
89
|
+
"inheritable": True,
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Call the method under test
|
|
96
|
+
app = Application()
|
|
97
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
98
|
+
|
|
99
|
+
# Verify the result handles None gracefully
|
|
100
|
+
self.assertEqual(len(result), 1)
|
|
101
|
+
self.assertEqual(result[0]["controlName"], "")
|
|
102
|
+
self.assertEqual(result[0]["controlTitle"], "")
|
|
103
|
+
self.assertEqual(result[0]["description"], "")
|
|
104
|
+
|
|
105
|
+
@patch("regscale.core.app.api.Api.graph")
|
|
106
|
+
def test_get_export_query_with_partial_control_owner(self, mock_graph):
|
|
107
|
+
"""Test get_export_query handles partial controlOwner data gracefully."""
|
|
108
|
+
# Mock API response with partial controlOwner data
|
|
109
|
+
mock_graph.return_value = {
|
|
110
|
+
"controlImplementations": {
|
|
111
|
+
"totalCount": 1,
|
|
112
|
+
"items": [
|
|
113
|
+
{
|
|
114
|
+
"id": 1,
|
|
115
|
+
"controlID": 100,
|
|
116
|
+
"controlOwner": {
|
|
117
|
+
"firstName": None,
|
|
118
|
+
"lastName": "Doe",
|
|
119
|
+
"userName": "jdoe",
|
|
120
|
+
},
|
|
121
|
+
"control": {
|
|
122
|
+
"title": "Test Control",
|
|
123
|
+
"description": "Test Description",
|
|
124
|
+
"controlId": "AC-1",
|
|
125
|
+
},
|
|
126
|
+
"status": "Implemented",
|
|
127
|
+
"policy": "Test Policy",
|
|
128
|
+
"implementation": "Test Implementation",
|
|
129
|
+
"responsibility": "Provider",
|
|
130
|
+
"inheritable": True,
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Call the method under test
|
|
137
|
+
app = Application()
|
|
138
|
+
result = ControlImplementation.get_export_query(app, parent_id=1, parent_module="securityplans")
|
|
139
|
+
|
|
140
|
+
# Verify the result handles partial data gracefully
|
|
141
|
+
self.assertEqual(len(result), 1)
|
|
142
|
+
self.assertEqual(result[0]["controlOwnerId"], "Doe, (jdoe)")
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Integration tests for FormFieldValue model API endpoints"""
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
from unittest.mock import MagicMock, patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
from requests import Response
|
|
10
|
+
|
|
11
|
+
from regscale.models.regscale_models.form_field_value import FormFieldValue
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestFormFieldValueIntegration:
|
|
15
|
+
"""Integration tests for FormFieldValue model covering all API endpoints"""
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def mock_api_handler(self):
|
|
19
|
+
"""Mock API handler for testing"""
|
|
20
|
+
with patch("regscale.models.regscale_models.form_field_value.FormFieldValue._get_api_handler") as mock:
|
|
21
|
+
yield mock.return_value
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def sample_form_field_data(self):
|
|
25
|
+
"""Sample form field data for testing"""
|
|
26
|
+
return [{"formFieldId": 1, "data": "Test Value 1"}, {"formFieldId": 2, "data": "Test Value 2"}]
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def sample_form_field_values(self):
|
|
30
|
+
"""Sample FormFieldValue objects for testing"""
|
|
31
|
+
return [FormFieldValue(formFieldId=1, data="Test Value 1"), FormFieldValue(formFieldId=2, data="Test Value 2")]
|
|
32
|
+
|
|
33
|
+
def test_save_custom_data_success(self, mock_api_handler, sample_form_field_values):
|
|
34
|
+
"""Test POST /api/formFieldValue/saveFormFields/{recordId}/{moduleName} - Success"""
|
|
35
|
+
# Setup
|
|
36
|
+
mock_response = MagicMock(spec=Response)
|
|
37
|
+
mock_response.ok = True
|
|
38
|
+
mock_api_handler.post.return_value = mock_response
|
|
39
|
+
|
|
40
|
+
record_id = 123
|
|
41
|
+
module_name = "cases"
|
|
42
|
+
|
|
43
|
+
# Execute
|
|
44
|
+
result = FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
45
|
+
|
|
46
|
+
# Assert
|
|
47
|
+
assert result is True
|
|
48
|
+
mock_api_handler.post.assert_called_once()
|
|
49
|
+
|
|
50
|
+
call_args = mock_api_handler.post.call_args
|
|
51
|
+
assert call_args[1]["endpoint"] == "/api/formFieldValue/saveFormFields/123/cases"
|
|
52
|
+
|
|
53
|
+
# Check that data was filtered to only include formFieldId and data
|
|
54
|
+
expected_data = [{"formFieldId": 1, "data": "Test Value 1"}, {"formFieldId": 2, "data": "Test Value 2"}]
|
|
55
|
+
assert call_args[1]["data"] == expected_data
|
|
56
|
+
|
|
57
|
+
def test_save_custom_data_failure(self, mock_api_handler, sample_form_field_values):
|
|
58
|
+
"""Test POST /api/formFieldValue/saveFormFields/{recordId}/{moduleName} - Failure"""
|
|
59
|
+
# Setup
|
|
60
|
+
mock_response = MagicMock(spec=Response)
|
|
61
|
+
mock_response.ok = False
|
|
62
|
+
mock_api_handler.post.return_value = mock_response
|
|
63
|
+
|
|
64
|
+
record_id = 123
|
|
65
|
+
module_name = "cases"
|
|
66
|
+
|
|
67
|
+
# Mock log_response_error
|
|
68
|
+
with patch.object(FormFieldValue, "log_response_error") as mock_log:
|
|
69
|
+
# Execute
|
|
70
|
+
result = FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
71
|
+
|
|
72
|
+
# Assert
|
|
73
|
+
assert result is False
|
|
74
|
+
mock_log.assert_called_once_with(response=mock_response)
|
|
75
|
+
|
|
76
|
+
def test_save_custom_data_empty_data(self, mock_api_handler):
|
|
77
|
+
"""Test save_custom_data with empty data list"""
|
|
78
|
+
# Setup
|
|
79
|
+
mock_response = MagicMock(spec=Response)
|
|
80
|
+
mock_response.ok = True
|
|
81
|
+
mock_api_handler.post.return_value = mock_response
|
|
82
|
+
|
|
83
|
+
# Execute
|
|
84
|
+
result = FormFieldValue.save_custom_data(123, "cases", [])
|
|
85
|
+
|
|
86
|
+
# Assert
|
|
87
|
+
assert result is True
|
|
88
|
+
mock_api_handler.post.assert_called_once()
|
|
89
|
+
call_args = mock_api_handler.post.call_args
|
|
90
|
+
assert call_args[1]["data"] == []
|
|
91
|
+
|
|
92
|
+
def test_get_field_values_success(self, mock_api_handler):
|
|
93
|
+
"""Test GET /api/formFieldValue/getFieldValues/{recordId}/{moduleName}/{formId} - Success"""
|
|
94
|
+
# Setup
|
|
95
|
+
mock_response = MagicMock(spec=Response)
|
|
96
|
+
mock_response.ok = True
|
|
97
|
+
mock_response.json.return_value = [
|
|
98
|
+
{"formFieldName": "Field1", "formFieldId": 1, "data": "Value1"},
|
|
99
|
+
{"formFieldName": "Field2", "formFieldId": 2, "data": "Value2"},
|
|
100
|
+
]
|
|
101
|
+
mock_api_handler.get.return_value = mock_response
|
|
102
|
+
|
|
103
|
+
record_id = 123
|
|
104
|
+
module_name = "cases"
|
|
105
|
+
form_id = 456
|
|
106
|
+
|
|
107
|
+
# Execute
|
|
108
|
+
result = FormFieldValue.get_field_values(record_id, module_name, form_id)
|
|
109
|
+
|
|
110
|
+
# Assert
|
|
111
|
+
assert len(result) == 2
|
|
112
|
+
assert all(isinstance(item, FormFieldValue) for item in result)
|
|
113
|
+
assert result[0].formFieldId == 1
|
|
114
|
+
assert result[0].data == "Value1"
|
|
115
|
+
assert result[1].formFieldId == 2
|
|
116
|
+
assert result[1].data == "Value2"
|
|
117
|
+
|
|
118
|
+
mock_api_handler.get.assert_called_once()
|
|
119
|
+
call_args = mock_api_handler.get.call_args
|
|
120
|
+
assert call_args[1]["endpoint"] == "/api/formFieldValue/getFieldValues/123/cases/456"
|
|
121
|
+
|
|
122
|
+
def test_get_field_values_failure(self, mock_api_handler):
|
|
123
|
+
"""Test GET /api/formFieldValue/getFieldValues/{recordId}/{moduleName}/{formId} - Failure"""
|
|
124
|
+
# Setup
|
|
125
|
+
mock_response = MagicMock(spec=Response)
|
|
126
|
+
mock_response.ok = False
|
|
127
|
+
mock_api_handler.get.return_value = mock_response
|
|
128
|
+
|
|
129
|
+
# Mock log_response_error
|
|
130
|
+
with patch.object(FormFieldValue, "log_response_error") as mock_log:
|
|
131
|
+
# Execute
|
|
132
|
+
result = FormFieldValue.get_field_values(123, "cases", 456)
|
|
133
|
+
|
|
134
|
+
# Assert
|
|
135
|
+
assert result == []
|
|
136
|
+
mock_log.assert_called_once_with(response=mock_response)
|
|
137
|
+
|
|
138
|
+
def test_get_field_values_empty_response(self, mock_api_handler):
|
|
139
|
+
"""Test get_field_values with empty response"""
|
|
140
|
+
# Setup
|
|
141
|
+
mock_response = MagicMock(spec=Response)
|
|
142
|
+
mock_response.ok = True
|
|
143
|
+
mock_response.json.return_value = []
|
|
144
|
+
mock_api_handler.get.return_value = mock_response
|
|
145
|
+
|
|
146
|
+
# Execute
|
|
147
|
+
result = FormFieldValue.get_field_values(123, "cases", 456)
|
|
148
|
+
|
|
149
|
+
# Assert
|
|
150
|
+
assert result == []
|
|
151
|
+
|
|
152
|
+
def test_get_field_values_by_name_endpoint(self, mock_api_handler):
|
|
153
|
+
"""Test that the missing getFieldValuesByName endpoint would work if implemented"""
|
|
154
|
+
# Note: This endpoint is mentioned in the requirements but not implemented in the model
|
|
155
|
+
# This test demonstrates how it would be tested if implemented
|
|
156
|
+
|
|
157
|
+
# Setup - Mock the endpoint as if it were implemented
|
|
158
|
+
with patch.object(FormFieldValue, "_get_additional_endpoints") as mock_endpoints:
|
|
159
|
+
mock_endpoints.return_value = {
|
|
160
|
+
"get_field_values_by_name": "/api/{model_slug}/getFieldValuesByName/{recordId}/{moduleName}/{regscaleId}"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
mock_response = MagicMock(spec=Response)
|
|
164
|
+
mock_response.ok = True
|
|
165
|
+
mock_response.json.return_value = [{"formFieldName": "TestField", "formFieldId": 1, "data": "TestValue"}]
|
|
166
|
+
mock_api_handler.get.return_value = mock_response
|
|
167
|
+
|
|
168
|
+
# This would be the method if implemented
|
|
169
|
+
def get_field_values_by_name(
|
|
170
|
+
cls, record_id: int, module_name: str, regscale_id: str
|
|
171
|
+
) -> List[FormFieldValue]:
|
|
172
|
+
result = cls._get_api_handler().get(
|
|
173
|
+
endpoint=cls.get_endpoint("get_field_values_by_name").format(
|
|
174
|
+
model_slug=cls.get_module_slug(),
|
|
175
|
+
recordId=record_id,
|
|
176
|
+
moduleName=module_name,
|
|
177
|
+
regscaleId=regscale_id,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
if result and result.ok:
|
|
181
|
+
return [cls(**o) for o in result.json()]
|
|
182
|
+
return []
|
|
183
|
+
|
|
184
|
+
# Add method to class temporarily for testing
|
|
185
|
+
FormFieldValue.get_field_values_by_name = classmethod(get_field_values_by_name)
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
# Execute
|
|
189
|
+
result = FormFieldValue.get_field_values_by_name(123, "cases", "test-regscale-id")
|
|
190
|
+
|
|
191
|
+
# Assert
|
|
192
|
+
assert len(result) == 1
|
|
193
|
+
assert isinstance(result[0], FormFieldValue)
|
|
194
|
+
mock_api_handler.get.assert_called_once()
|
|
195
|
+
call_args = mock_api_handler.get.call_args
|
|
196
|
+
expected_endpoint = "/api/formFieldValue/getFieldValuesByName/123/cases/test-regscale-id"
|
|
197
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|
|
198
|
+
finally:
|
|
199
|
+
# Clean up
|
|
200
|
+
delattr(FormFieldValue, "get_field_values_by_name")
|
|
201
|
+
|
|
202
|
+
def test_filter_dict_keys(self):
|
|
203
|
+
"""Test the filter_dict_keys static method"""
|
|
204
|
+
# Setup
|
|
205
|
+
data = {
|
|
206
|
+
"formFieldId": 1,
|
|
207
|
+
"data": "test value",
|
|
208
|
+
"extra_field": "should be filtered out",
|
|
209
|
+
"another_field": "also filtered",
|
|
210
|
+
}
|
|
211
|
+
allowed_fields = ["formFieldId", "data"]
|
|
212
|
+
|
|
213
|
+
# Execute
|
|
214
|
+
result = FormFieldValue.filter_dict_keys(data, allowed_fields)
|
|
215
|
+
|
|
216
|
+
# Assert
|
|
217
|
+
assert result == {"formFieldId": 1, "data": "test value"}
|
|
218
|
+
assert "extra_field" not in result
|
|
219
|
+
assert "another_field" not in result
|
|
220
|
+
|
|
221
|
+
def test_filter_dict_keys_empty_data(self):
|
|
222
|
+
"""Test filter_dict_keys with empty data"""
|
|
223
|
+
result = FormFieldValue.filter_dict_keys({}, ["formFieldId", "data"])
|
|
224
|
+
assert result == {}
|
|
225
|
+
|
|
226
|
+
def test_filter_dict_keys_empty_allowed_fields(self):
|
|
227
|
+
"""Test filter_dict_keys with empty allowed fields"""
|
|
228
|
+
data = {"formFieldId": 1, "data": "test"}
|
|
229
|
+
result = FormFieldValue.filter_dict_keys(data, [])
|
|
230
|
+
assert result == {}
|
|
231
|
+
|
|
232
|
+
def test_module_slug(self):
|
|
233
|
+
"""Test that the module slug is correctly set"""
|
|
234
|
+
assert FormFieldValue._module_slug == "formFieldValue"
|
|
235
|
+
|
|
236
|
+
def test_additional_endpoints(self):
|
|
237
|
+
"""Test that additional endpoints are correctly defined"""
|
|
238
|
+
endpoints = FormFieldValue._get_additional_endpoints()
|
|
239
|
+
|
|
240
|
+
assert "post_save_form_fields" in endpoints
|
|
241
|
+
assert "get_field_value" in endpoints
|
|
242
|
+
|
|
243
|
+
assert endpoints["post_save_form_fields"] == "/api/{model_slug}/saveFormFields/{recordId}/{moduleName}"
|
|
244
|
+
assert endpoints["get_field_value"] == "/api/{model_slug}/getFieldValues/{recordId}/{moduleName}/{formId}"
|
|
245
|
+
|
|
246
|
+
def test_field_aliases(self):
|
|
247
|
+
"""Test that field aliases work correctly"""
|
|
248
|
+
# Test that 'data' field can be set via 'fieldValue' alias
|
|
249
|
+
form_field = FormFieldValue(formFieldId=1, fieldValue="test value")
|
|
250
|
+
assert form_field.data == "test value"
|
|
251
|
+
|
|
252
|
+
# Test dict creation with alias
|
|
253
|
+
form_field_dict = form_field.dict(by_alias=True)
|
|
254
|
+
assert "fieldValue" in form_field_dict
|
|
255
|
+
assert form_field_dict["fieldValue"] == "test value"
|
|
256
|
+
|
|
257
|
+
@pytest.mark.parametrize(
|
|
258
|
+
"record_id,module_name,expected_endpoint",
|
|
259
|
+
[
|
|
260
|
+
(123, "cases", "/api/formFieldValue/saveFormFields/123/cases"),
|
|
261
|
+
(456, "assets", "/api/formFieldValue/saveFormFields/456/assets"),
|
|
262
|
+
(789, "issues", "/api/formFieldValue/saveFormFields/789/issues"),
|
|
263
|
+
],
|
|
264
|
+
)
|
|
265
|
+
def test_save_custom_data_endpoint_formation(
|
|
266
|
+
self, mock_api_handler, sample_form_field_values, record_id, module_name, expected_endpoint
|
|
267
|
+
):
|
|
268
|
+
"""Test endpoint formation for different parameters"""
|
|
269
|
+
# Setup
|
|
270
|
+
mock_response = MagicMock(spec=Response)
|
|
271
|
+
mock_response.ok = True
|
|
272
|
+
mock_api_handler.post.return_value = mock_response
|
|
273
|
+
|
|
274
|
+
# Execute
|
|
275
|
+
FormFieldValue.save_custom_data(record_id, module_name, sample_form_field_values)
|
|
276
|
+
|
|
277
|
+
# Assert
|
|
278
|
+
call_args = mock_api_handler.post.call_args
|
|
279
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|
|
280
|
+
|
|
281
|
+
@pytest.mark.parametrize(
|
|
282
|
+
"record_id,module_name,form_id,expected_endpoint",
|
|
283
|
+
[
|
|
284
|
+
(123, "cases", 456, "/api/formFieldValue/getFieldValues/123/cases/456"),
|
|
285
|
+
(789, "assets", 101, "/api/formFieldValue/getFieldValues/789/assets/101"),
|
|
286
|
+
(999, "issues", 202, "/api/formFieldValue/getFieldValues/999/issues/202"),
|
|
287
|
+
],
|
|
288
|
+
)
|
|
289
|
+
def test_get_field_values_endpoint_formation(
|
|
290
|
+
self, mock_api_handler, record_id, module_name, form_id, expected_endpoint
|
|
291
|
+
):
|
|
292
|
+
"""Test endpoint formation for get_field_values with different parameters"""
|
|
293
|
+
# Setup
|
|
294
|
+
mock_response = MagicMock(spec=Response)
|
|
295
|
+
mock_response.ok = True
|
|
296
|
+
mock_response.json.return_value = []
|
|
297
|
+
mock_api_handler.get.return_value = mock_response
|
|
298
|
+
|
|
299
|
+
# Execute
|
|
300
|
+
FormFieldValue.get_field_values(record_id, module_name, form_id)
|
|
301
|
+
|
|
302
|
+
# Assert
|
|
303
|
+
call_args = mock_api_handler.get.call_args
|
|
304
|
+
assert call_args[1]["endpoint"] == expected_endpoint
|