davinci_pas_test_kit 0.15.2 → 0.16.0
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.
- checksums.yaml +4 -4
- data/config/presets/g33_br_provider.json +13 -0
- data/lib/davinci_pas_test_kit/client/abstract_approval_submit_test.rb +28 -17
- data/lib/davinci_pas_test_kit/client/abstract_denial_submit_test.rb +26 -16
- data/lib/davinci_pas_test_kit/client/abstract_gather_must_support_test.rb +43 -26
- data/lib/davinci_pas_test_kit/client/abstract_modification_submit_test.rb +29 -19
- data/lib/davinci_pas_test_kit/client/abstract_response_attest.rb +75 -6
- data/lib/davinci_pas_test_kit/client/abstract_subscription_create_test.rb +26 -9
- data/lib/davinci_pas_test_kit/client/abstract_subscription_update_delete_test.rb +91 -0
- data/lib/davinci_pas_test_kit/client/client_bundle_validation_helper.rb +245 -0
- data/lib/davinci_pas_test_kit/client/client_input_descriptions.rb +91 -25
- data/lib/davinci_pas_test_kit/client/endpoints/claim_endpoint.rb +108 -68
- data/lib/davinci_pas_test_kit/client/endpoints/endpoint_session_identification.rb +24 -0
- data/lib/davinci_pas_test_kit/client/endpoints/expired_token.rb +40 -0
- data/lib/davinci_pas_test_kit/client/endpoints/subscription_create_endpoint.rb +7 -12
- data/lib/davinci_pas_test_kit/client/endpoints/subscription_delete_endpoint.rb +13 -0
- data/lib/davinci_pas_test_kit/client/endpoints/subscription_read_endpoint.rb +13 -0
- data/lib/davinci_pas_test_kit/client/endpoints/subscription_status_endpoint.rb +15 -20
- data/lib/davinci_pas_test_kit/client/endpoints/subscription_update_endpoint.rb +13 -0
- data/lib/davinci_pas_test_kit/client/endpoints/token_endpoint.rb +16 -0
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_request_must_support_beneficiary_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_request_must_support_beneficiary_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/communication_request/client_submit_response_must_support_communication_request_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_inquire_request_must_support_coverage_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/coverage/client_submit_request_must_support_coverage_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/encounter/client_submit_request_must_support_encounter_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_request_must_support_insurer_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_inquire_response_must_support_insurer_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_request_must_support_insurer_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/insurer/client_submit_response_must_support_insurer_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_must_support_group.rb +1 -1
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_inquire_response_must_support_group.rb +9 -31
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_must_support_group.rb +1 -1
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_client_submit_response_must_support_group.rb +10 -32
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_inquiry_request_bundle/client_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_inquiry_response_bundle/client_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_request_bundle/client_submit_request_must_support_pas_request_bundle_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/pas_response_bundle/client_submit_response_must_support_pas_response_bundle_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_request_must_support_practitioner_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_request_must_support_practitioner_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner/client_submit_response_must_support_practitioner_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_request_must_support_practitioner_role_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_request_must_support_practitioner_role_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_request_must_support_requestor_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_inquire_response_must_support_requestor_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_request_must_support_requestor_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/requestor/client_submit_response_must_support_requestor_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_inquire_request_must_support_subscriber_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/subscriber/client_submit_request_must_support_subscriber_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_inquire_response_must_support_beneficiary_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/beneficiary/client_submit_response_must_support_beneficiary_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_inquiry/client_inquire_request_must_support_claim_inquiry_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claim_update/client_submit_request_must_support_claim_update_test.rb +3 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claiminquiryresponse/client_inquire_response_must_support_claiminquiryresponse_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/claimresponse/client_submit_response_must_support_claimresponse_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/communication_request/client_submit_response_must_support_communication_request_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_inquire_response_must_support_insurer_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/insurer/client_submit_response_must_support_insurer_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_must_support_group.rb +8 -6
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_inquire_response_must_support_group.rb +9 -31
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_must_support_group.rb +13 -9
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_client_submit_response_must_support_group.rb +10 -32
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_inquiry_response_bundle/client_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/pas_response_bundle/client_submit_response_must_support_pas_response_bundle_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_inquire_response_must_support_practitioner_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner/client_submit_response_must_support_practitioner_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_inquire_response_must_support_practitioner_role_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/practitioner_role/client_submit_response_must_support_practitioner_role_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_inquire_response_must_support_requestor_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/requestor/client_submit_response_must_support_requestor_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/jobs/send_pas_subscription_notification.rb +64 -3
- data/lib/davinci_pas_test_kit/client/pas_client_subscription_pas_conformance_test.rb +4 -3
- data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_other_display_test.rb +6 -4
- data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_smart_display_test.rb +8 -4
- data/lib/davinci_pas_test_kit/client/registration/abstract_configuration_udap_display_test.rb +9 -4
- data/lib/davinci_pas_test_kit/client/registration/abstract_other_auth_attest_test.rb +5 -4
- data/lib/davinci_pas_test_kit/client/request_count_gating.rb +14 -0
- data/lib/davinci_pas_test_kit/client/response_generator.rb +50 -9
- data/lib/davinci_pas_test_kit/client/session_identification.rb +26 -7
- data/lib/davinci_pas_test_kit/client/subscription_notification_trigger.rb +80 -0
- data/lib/davinci_pas_test_kit/client/subscription_setup_requirement.rb +59 -0
- data/lib/davinci_pas_test_kit/client/user_input_response.rb +27 -6
- data/lib/davinci_pas_test_kit/client/v2.0.1/client_suite.rb +30 -15
- data/lib/davinci_pas_test_kit/client/v2.0.1/must_support/pas_client_must_support_request_profiles_test.rb +2 -2
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_approval_group.rb +8 -7
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_smart_group.rb +4 -4
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_auth_udap_group.rb +4 -4
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_denial_group.rb +8 -7
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_must_support_group.rb +38 -52
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_pended_group.rb +28 -22
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_registration_group.rb +2 -2
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_subscription_setup_group.rb +2 -2
- data/lib/davinci_pas_test_kit/client/v2.0.1/pas_client_workflows_group.rb +2 -2
- data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +15 -21
- data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +29 -29
- data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_pended_submit_test.rb +49 -40
- data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_request_bundle_validation_test.rb +15 -21
- data/lib/davinci_pas_test_kit/client/v2.0.1/workflows/pas_client_response_bundle_validation_test.rb +29 -29
- data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_provider_review_attestation_test.rb +45 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_security_attestation_test.rb +42 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/attestations/client_subscription_error_recovery_attestation_test.rb +42 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/client_suite.rb +64 -12
- data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_failure_submit_test.rb +20 -10
- data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_operation_outcome_validation_test.rb +11 -5
- data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_response_validation_test.rb +21 -12
- data/lib/davinci_pas_test_kit/client/v2.2.1/error_handling/pas_client_processing_error_submit_test.rb +19 -8
- data/lib/davinci_pas_test_kit/client/v2.2.1/must_support/must_support_with_attestation_option.rb +90 -40
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_approval_group.rb +12 -11
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_attestations_group.rb +32 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_smart_group.rb +4 -4
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_auth_udap_group.rb +4 -4
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_claim_updates_group.rb +24 -6
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_denial_group.rb +12 -10
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_modification_group.rb +13 -14
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_must_support_group.rb +55 -59
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_operation_failure_group.rb +8 -5
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_pended_group.rb +53 -41
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_processing_error_group.rb +9 -7
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_registration_group.rb +2 -2
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_setup_group.rb +9 -4
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_subscription_update_delete_group.rb +57 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_workflows_group.rb +22 -2
- data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_create_test.rb +2 -1
- data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_put_update_pas_conformance_test.rb +49 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/subscription/pas_client_subscription_update_delete_test.rb +12 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_referenced_resources_test.rb +5 -6
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_claim_update_submit_tests.rb +82 -56
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_request_bundle_validation_test.rb +17 -20
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_inquire_response_bundle_validation_test.rb +59 -27
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_modification_verification_test.rb +0 -3
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_send_notification_test.rb +138 -0
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_pended_submit_test.rb +32 -85
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_request_bundle_validation_test.rb +16 -21
- data/lib/davinci_pas_test_kit/client/v2.2.1/workflows/pas_client_response_bundle_validation_test.rb +27 -27
- data/lib/davinci_pas_test_kit/cross_suite/generated/v2.0.1/task/metadata.yml +0 -4
- data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/metadata.yml +0 -1
- data/lib/davinci_pas_test_kit/cross_suite/generated/v2.2.1/task/metadata.yml +0 -4
- data/lib/davinci_pas_test_kit/cross_suite/pas_bundle_validation.rb +489 -289
- data/lib/davinci_pas_test_kit/cross_suite/pas_constants.rb +7 -0
- data/lib/davinci_pas_test_kit/cross_suite/pas_subscription_verification.rb +8 -4
- data/lib/davinci_pas_test_kit/cross_suite/referenced_resource_presence_validation.rb +141 -0
- data/lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb +13 -11
- data/lib/davinci_pas_test_kit/cross_suite/tags.rb +11 -6
- data/lib/davinci_pas_test_kit/cross_suite/validator_configuration.rb +16 -0
- data/lib/davinci_pas_test_kit/cross_suite/validator_suppressions.rb +4 -0
- data/lib/davinci_pas_test_kit/docs/demo/PAS Client Suite Demonstration.postman_collection.json +3 -3
- data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +1 -0
- data/lib/davinci_pas_test_kit/generator/client_must_support_group_generator.rb +47 -16
- data/lib/davinci_pas_test_kit/generator/must_support_target_profiles.rb +17 -0
- data/lib/davinci_pas_test_kit/generator/must_support_test_generator.rb +8 -2
- data/lib/davinci_pas_test_kit/generator/profile_metadata.rb +1 -1
- data/lib/davinci_pas_test_kit/generator/server_suite_generator.rb +4 -9
- data/lib/davinci_pas_test_kit/generator/templates/client_must_support_group.rb.erb +22 -3
- data/lib/davinci_pas_test_kit/generator/templates/client_must_support_response_group.rb.erb +7 -16
- data/lib/davinci_pas_test_kit/generator/templates/must_support.rb.erb +8 -8
- data/lib/davinci_pas_test_kit/generator/templates/server_suite.rb.erb +6 -7
- data/lib/davinci_pas_test_kit/generator/use_case_group_generator.rb +5 -5
- data/lib/davinci_pas_test_kit/parameters_helper.rb +13 -5
- data/lib/davinci_pas_test_kit/pas_notification_conformance_test.rb +2 -2
- data/lib/davinci_pas_test_kit/requirements/davinci_pas_test_kit_requirements.csv +14 -7
- data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v201_requirements_coverage.csv +21 -21
- data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_client_suite_v221_requirements_coverage.csv +30 -26
- data/lib/davinci_pas_test_kit/requirements/generated/davinci_pas_server_suite_v221_requirements_coverage.csv +12 -6
- data/lib/davinci_pas_test_kit/requirements/hl7.fhir.us.davinci-pas_2.2.1_requirements.xlsx +0 -0
- data/lib/davinci_pas_test_kit/server/claim_operation_logic.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_inquiry_request_bundle/server_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_inquiry_response_bundle/server_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_request_bundle/server_submit_request_must_support_pas_request_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_response_bundle/server_submit_response_must_support_pas_response_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_approval_use_case_group.rb +3 -3
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_denial_use_case_group.rb +3 -3
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/pas_server_pended_use_case_group.rb +6 -6
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/server_suite.rb +6 -7
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_inquire_response_must_support_task_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.0.1/task/server_submit_response_must_support_task_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_request_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_inquire_response_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_request_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/beneficiary/server_submit_response_must_support_beneficiary_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_inquiry/server_inquire_request_must_support_claim_inquiry_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claim_update/server_submit_request_must_support_claim_update_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claiminquiryresponse/server_inquire_response_must_support_claiminquiryresponse_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/claimresponse/server_submit_response_must_support_claimresponse_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/communication_request/server_submit_response_must_support_communication_request_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_inquire_request_must_support_coverage_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/coverage/server_submit_request_must_support_coverage_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/encounter/server_submit_request_must_support_encounter_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_request_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_inquire_response_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_request_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/insurer/server_submit_response_must_support_insurer_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_inquiry_request_bundle/server_inquire_request_must_support_pas_inquiry_request_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_inquiry_response_bundle/server_inquire_response_must_support_pas_inquiry_response_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_request_bundle/server_submit_request_must_support_pas_request_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_response_bundle/server_submit_response_must_support_pas_response_bundle_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_approval_use_case_group.rb +3 -3
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_denial_use_case_group.rb +3 -3
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/pas_server_pended_use_case_group.rb +4 -4
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_request_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_inquire_response_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_request_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner/server_submit_response_must_support_practitioner_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_request_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_inquire_response_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_request_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/practitioner_role/server_submit_response_must_support_practitioner_role_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_request_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_inquire_response_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_request_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/requestor/server_submit_response_must_support_requestor_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/server_suite.rb +6 -7
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_inquire_request_must_support_subscriber_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/subscriber/server_submit_request_must_support_subscriber_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_inquire_response_must_support_task_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/generated/v2.2.1/task/server_submit_response_must_support_task_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/pas_claim_response_decision_test.rb +2 -2
- data/lib/davinci_pas_test_kit/server/server_request_bundle_validation_test.rb +4 -6
- data/lib/davinci_pas_test_kit/server/server_response_bundle_validation_test.rb +4 -6
- data/lib/davinci_pas_test_kit/server/v2.0.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/v2.0.1/pas_server_subscription_setup.rb +1 -1
- data/lib/davinci_pas_test_kit/server/v2.2.1/must_support/pas_server_must_support_request_profiles_test.rb +1 -1
- data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_claim_updates_group.rb +1 -1
- data/lib/davinci_pas_test_kit/server/v2.2.1/pas_server_subscription_setup.rb +1 -1
- data/lib/davinci_pas_test_kit/version.rb +2 -2
- metadata +31 -13
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_inquire_response_must_support_task_test.rb +0 -45
- data/lib/davinci_pas_test_kit/client/generated/v2.0.1/task/client_submit_response_must_support_task_test.rb +0 -45
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_inquire_response_must_support_task_test.rb +0 -55
- data/lib/davinci_pas_test_kit/client/generated/v2.2.1/task/client_submit_response_must_support_task_test.rb +0 -55
- data/lib/davinci_pas_test_kit/client/v2.2.1/pas_client_error_handling_group.rb +0 -20
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
require_relative 'request_count_gating'
|
|
2
|
+
|
|
3
|
+
module DaVinciPASTestKit
|
|
4
|
+
module ClientBundleValidationHelper
|
|
5
|
+
include RequestCountGating
|
|
6
|
+
|
|
7
|
+
###########################################################################
|
|
8
|
+
# Tags and Request Loading
|
|
9
|
+
###########################################################################
|
|
10
|
+
def request_type_tag
|
|
11
|
+
case operation_name
|
|
12
|
+
when 'inquire'
|
|
13
|
+
INQUIRE_TAG
|
|
14
|
+
when 'submit'
|
|
15
|
+
SUBMIT_TAG
|
|
16
|
+
else
|
|
17
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
18
|
+
'PAS Client Bundle Validation Test',
|
|
19
|
+
"invalid operation name #{operation_name}"
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def workflow_tag
|
|
25
|
+
config.options[:workflow_tag]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# workflow_tag may be a single tag or an Array of tags; normalized to an Array so fetch_requests
|
|
29
|
+
# doesn't need its own is_a?(Array) check.
|
|
30
|
+
def workflow_tags
|
|
31
|
+
Array(workflow_tag)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def fetch_requests
|
|
35
|
+
tags = workflow_tags.presence || [nil]
|
|
36
|
+
tags.flat_map { |tag| load_tagged_requests(*[request_type_tag, tag].compact) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
###########################################################################
|
|
40
|
+
# Request Count
|
|
41
|
+
###########################################################################
|
|
42
|
+
|
|
43
|
+
# Raises if there are multiple requests and the test doesn't allow that.
|
|
44
|
+
# Skips if there are no requests and the test doesn't allow that.
|
|
45
|
+
# @param requests [Array<Inferno::Entities::Request>] the requests loaded for this test.
|
|
46
|
+
# @param description [String] identifies the requests in the raised message, e.g.
|
|
47
|
+
# "submit requests".
|
|
48
|
+
def check_request_count(requests, description)
|
|
49
|
+
if requests.length > 1 && !multiple_requests_ok?
|
|
50
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
51
|
+
'multiple request handling',
|
|
52
|
+
"#{requests.length} #{description} were tagged for validation by this test, which does not expect " \
|
|
53
|
+
'more than one.'
|
|
54
|
+
)
|
|
55
|
+
elsif requests.empty?
|
|
56
|
+
if no_requests_ok?
|
|
57
|
+
pass "No #{description} analyzed."
|
|
58
|
+
else
|
|
59
|
+
skip "No #{description} received."
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
###########################################################################
|
|
65
|
+
# Extraction logic
|
|
66
|
+
###########################################################################
|
|
67
|
+
|
|
68
|
+
def message_contents(request)
|
|
69
|
+
case message_direction_name
|
|
70
|
+
when 'request'
|
|
71
|
+
request.request_body
|
|
72
|
+
when 'response'
|
|
73
|
+
request.response_body
|
|
74
|
+
else
|
|
75
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
76
|
+
'PAS Client Bundle Validation Test',
|
|
77
|
+
"invalid message direction name #{message_direction_name}"
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def parameters_target_parameter_name
|
|
83
|
+
case message_direction_name
|
|
84
|
+
when 'request'
|
|
85
|
+
'resource'
|
|
86
|
+
when 'response'
|
|
87
|
+
'return'
|
|
88
|
+
else
|
|
89
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
90
|
+
'PAS Client Bundle Validation Test',
|
|
91
|
+
"invalid message direction name #{message_direction_name}"
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
###########################################################################
|
|
97
|
+
# Validation logic
|
|
98
|
+
###########################################################################
|
|
99
|
+
|
|
100
|
+
# Finds Bundles in the requests and determines which ones are non-conformant.
|
|
101
|
+
#
|
|
102
|
+
# Assumes this is the only thing logging to `messages` during this run and that it's
|
|
103
|
+
# called at most once, so every message present afterward is one it logged itself.
|
|
104
|
+
def non_conformant_bundles
|
|
105
|
+
requests = fetch_requests
|
|
106
|
+
check_request_count(requests, "$#{operation_name} #{message_direction_name}s")
|
|
107
|
+
requests.each_with_index { |request, index| validate_request(request, index) }
|
|
108
|
+
|
|
109
|
+
messages
|
|
110
|
+
.select { |message| message[:type] == 'error' }
|
|
111
|
+
.map { |message| message[:message].split(':', 2).first }
|
|
112
|
+
.uniq
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Validates one request/response, extracting and checking the Bundle(s) it contains and
|
|
116
|
+
# logging any problem found along the way - this only logs, callers determine what failed
|
|
117
|
+
# from `messages` afterward (see non_conformant_bundles).
|
|
118
|
+
def validate_request(request, index)
|
|
119
|
+
message_label = entity_label("#{message_direction_name.capitalize} #{index + 1}")
|
|
120
|
+
contents = message_contents(request)
|
|
121
|
+
message_resource = resource_from_message_contents(contents, message_label)
|
|
122
|
+
return if message_resource.blank?
|
|
123
|
+
|
|
124
|
+
# extraction varies - provided by test class if not using the default. May contain nil
|
|
125
|
+
# placeholders for positions that held something other than a Bundle (already reported),
|
|
126
|
+
# so Bundle labels keep their original position.
|
|
127
|
+
bundles = bundles_from_message_resource(message_resource, message_label)
|
|
128
|
+
parameters_has_errors?(message_resource, message_label) if response_parameters?(message_resource)
|
|
129
|
+
echoed_from = echo_source_bundle(request)
|
|
130
|
+
|
|
131
|
+
if bundles.length > 1
|
|
132
|
+
bundles.each_with_index do |bundle, bundle_index|
|
|
133
|
+
next if bundle.nil?
|
|
134
|
+
|
|
135
|
+
bundle_label = entity_label("#{message_label.delete_suffix(':')} Bundle #{bundle_index + 1}")
|
|
136
|
+
bundle_has_errors?(bundle, bundle_label, echoed_from)
|
|
137
|
+
end
|
|
138
|
+
else
|
|
139
|
+
bundles.compact.each { |bundle| bundle_has_errors?(bundle, message_label, echoed_from) }
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# A label identifying one request/response, or a Bundle within one, for use as a message
|
|
144
|
+
# prefix. Always ends in ':' so a logged message's entity can be recovered by splitting on
|
|
145
|
+
# its first ':' - see non_conformant_bundles.
|
|
146
|
+
def entity_label(description)
|
|
147
|
+
"#{description}:"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def resource_from_message_contents(contents, label)
|
|
151
|
+
resource = FHIR.from_contents(contents)
|
|
152
|
+
messages << { type: 'error', message: "#{label} Not a FHIR resource." } unless resource.present?
|
|
153
|
+
resource
|
|
154
|
+
rescue StandardError
|
|
155
|
+
messages << { type: 'error', message: "#{label} Invalid JSON." }
|
|
156
|
+
nil
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# standard Bundle extraction: 1 Bundle, not wrapped in Parameters
|
|
160
|
+
def bundles_from_message_resource(message_resource, message_label)
|
|
161
|
+
case message_resource
|
|
162
|
+
when FHIR::Bundle
|
|
163
|
+
[message_resource]
|
|
164
|
+
when FHIR::Parameters
|
|
165
|
+
messages << { type: 'error',
|
|
166
|
+
message: "#{message_label} expected a Bundle resource, got Parameters." }
|
|
167
|
+
target_parameter_name = parameters_target_parameter_name
|
|
168
|
+
matching_resources = extract_resources_from_parameters(message_resource, target_parameter_name)
|
|
169
|
+
|
|
170
|
+
if matching_resources.empty?
|
|
171
|
+
messages << { type: 'error',
|
|
172
|
+
message: "#{message_label} Parameters resource had no Bundle " \
|
|
173
|
+
"in a '#{target_parameter_name}' entry." }
|
|
174
|
+
[]
|
|
175
|
+
elsif matching_resources.length > 1
|
|
176
|
+
messages << { type: 'error',
|
|
177
|
+
message: "#{message_label} Parameters resource had multiple '#{target_parameter_name}' " \
|
|
178
|
+
'entries, but only one allowed (Bundles not validated).' }
|
|
179
|
+
[]
|
|
180
|
+
elsif matching_resources.first.is_a?(FHIR::Bundle)
|
|
181
|
+
[matching_resources.first]
|
|
182
|
+
else
|
|
183
|
+
messages << { type: 'error',
|
|
184
|
+
message: "#{message_label} Parameters resource '#{target_parameter_name}' entry expected to " \
|
|
185
|
+
"contain a Bundle, got #{matching_resources.first&.resourceType}" }
|
|
186
|
+
[]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
else
|
|
190
|
+
messages << { type: 'error',
|
|
191
|
+
message: "#{message_label} expected a Bundle resource, got #{message_resource.resourceType}." }
|
|
192
|
+
[]
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# The request Bundle a response answers, so resources the response echoes back from it may keep
|
|
197
|
+
# the extensions they had in it - see PasBundleValidation#perform_no_custom_extensions_validation. Unwraps
|
|
198
|
+
# Parameters-wrapped requests (v2.2.1 $inquire). Nil when validating requests, or when the
|
|
199
|
+
# request has no Bundle.
|
|
200
|
+
def echo_source_bundle(request)
|
|
201
|
+
return unless message_direction_name == 'response'
|
|
202
|
+
|
|
203
|
+
request_resource = FHIR.from_contents(request.request_body)
|
|
204
|
+
if request_resource.is_a?(FHIR::Parameters)
|
|
205
|
+
request_resource = extract_resources_from_parameters(request_resource, 'resource').first
|
|
206
|
+
end
|
|
207
|
+
request_resource if request_resource.is_a?(FHIR::Bundle)
|
|
208
|
+
rescue StandardError
|
|
209
|
+
nil
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# A Parameters wrapper Inferno sends around the response Bundles (v2.2.1 $inquire), which may be
|
|
213
|
+
# tester-provided, so it is checked for custom extensions too.
|
|
214
|
+
def response_parameters?(message_resource)
|
|
215
|
+
message_direction_name == 'response' && message_resource.is_a?(FHIR::Parameters)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def parameters_has_errors?(parameters, label)
|
|
219
|
+
parameters_messages = perform_no_custom_extensions_parameters_validation(parameters)
|
|
220
|
+
parameters_messages.each { |m| messages << { type: m[:type], message: "#{label} #{m[:message]}" } }
|
|
221
|
+
parameters_messages.any? { |m| m[:type] == 'error' }
|
|
222
|
+
rescue NoMethodError, TypeError, ArgumentError => e
|
|
223
|
+
messages << { type: 'error', message: "#{label} Parameters could not be validated: #{e.message}" }
|
|
224
|
+
true
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def bundle_has_errors?(bundle, label, echoed_from = nil)
|
|
228
|
+
# Responses are sent by Inferno and may be tester-provided, so custom extensions aren't allowed.
|
|
229
|
+
bundle_messages =
|
|
230
|
+
if message_direction_name == 'response'
|
|
231
|
+
perform_no_custom_extensions_validation(bundle, operation_name, message_direction_name, ig_version,
|
|
232
|
+
echoed_from:)
|
|
233
|
+
else
|
|
234
|
+
perform_bundle_validation(bundle, operation_name, message_direction_name, ig_version)
|
|
235
|
+
end
|
|
236
|
+
bundle_messages.each { |m| messages << { type: m[:type], message: "#{label} #{m[:message]}" } }
|
|
237
|
+
bundle_messages.any? { |m| m[:type] == 'error' }
|
|
238
|
+
rescue NoMethodError, TypeError, ArgumentError => e
|
|
239
|
+
# a malformed Bundle (e.g., an entry with no resource) shouldn't stop the remaining
|
|
240
|
+
# requests/Bundles from being validated
|
|
241
|
+
messages << { type: 'error', message: "#{label} could not be validated: #{e.message}" }
|
|
242
|
+
true
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
@@ -2,38 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
module DaVinciPASTestKit
|
|
4
4
|
INPUT_CLIENT_ID_LOCKED =
|
|
5
|
-
'The client\'s registered Client Id for use in obtaining access tokens. ' \
|
|
5
|
+
'The PAS client\'s registered Client Id for use in obtaining access tokens. ' \
|
|
6
6
|
'Run the **1** Client Registration group to configure this input.'
|
|
7
7
|
INPUT_SESSION_URL_PATH_LOCKED =
|
|
8
8
|
'The additional path used to create session-specific endpoints. Run the ' \
|
|
9
9
|
'**1** Client Registration group to configure this input.'
|
|
10
10
|
|
|
11
|
-
# Shared
|
|
12
|
-
#
|
|
11
|
+
# Shared text for the "Demonstrate Must Support Coverage" group and its combined $submit/$inquire
|
|
12
|
+
# response_attest test, identical across PAS versions in each client/vX/pas_client_must_support_group.rb
|
|
13
|
+
# other than the requirement each version's attest test verifies.
|
|
14
|
+
MUST_SUPPORT_RECEIVE_GROUP_TITLE = 'Demonstrate Must Support Coverage'
|
|
15
|
+
MUST_SUPPORT_RECEIVE_GROUP_DESCRIPTION =
|
|
16
|
+
%(
|
|
17
|
+
During this group, Inferno will wait while the tester uses the PAS client to
|
|
18
|
+
make `$submit` and `$inquire` operation requests to Inferno demonstrating coverage
|
|
19
|
+
of must support elements not yet demonstrated.
|
|
20
|
+
|
|
21
|
+
Inferno then asks for confirmation that all responses were handled
|
|
22
|
+
without error and verifies the conformance of all requests and responses.
|
|
23
|
+
)
|
|
24
|
+
MUST_SUPPORT_SUBMIT_INQUIRE_ATTEST_TITLE =
|
|
25
|
+
'PAS client handled the $submit and $inquire responses without erroring'
|
|
26
|
+
MUST_SUPPORT_SUBMIT_INQUIRE_ATTEST_DESCRIPTION =
|
|
27
|
+
%(
|
|
28
|
+
During this test, the tester will verify that the PAS client handled
|
|
29
|
+
the `$submit` and `$inquire` operation responses, making the result available to
|
|
30
|
+
the user without failing or erroring.
|
|
31
|
+
)
|
|
32
|
+
MUST_SUPPORT_SUBMIT_INQUIRE_ATTEST_MESSAGE =
|
|
33
|
+
'I attest that the PAS client correctly handled the `$submit` and `$inquire` ' \
|
|
34
|
+
'operation responses received from Inferno during this test, making the details ' \
|
|
35
|
+
'available to users without errors.'
|
|
36
|
+
|
|
37
|
+
# Text for the v2.2.1 must support group, where the analysis is a separate group from the receive group
|
|
38
|
+
MUST_SUPPORT_COVERAGE_GROUP_TITLE = 'Must Support Coverage'
|
|
39
|
+
MUST_SUPPORT_COVERAGE_GROUP_DESCRIPTION =
|
|
40
|
+
%(
|
|
41
|
+
During this group, Inferno checks that the requests and responses exchanged during the
|
|
42
|
+
PAS scenario group and the most recent run of the "Demonstrate Must Support Coverage" group
|
|
43
|
+
include all required profiles and must support elements.
|
|
44
|
+
|
|
45
|
+
This group can be re-run on its own, for example after re-running another group, without
|
|
46
|
+
repeating the "Demonstrate Must Support Coverage" group or losing the requests made
|
|
47
|
+
during it.
|
|
48
|
+
)
|
|
49
|
+
MUST_SUPPORT_SEPARATE_GROUPS_DESCRIPTION =
|
|
50
|
+
<<~DESCRIPTION
|
|
51
|
+
The "Demonstrate Must Support Coverage" and "Must Support Coverage" groups can be run
|
|
52
|
+
separately. Re-running "Demonstrate Must Support Coverage" replaces the requests made during
|
|
53
|
+
its previous run, while "Must Support Coverage" can be re-run on its own to re-evaluate
|
|
54
|
+
coverage without making those requests again.
|
|
55
|
+
DESCRIPTION
|
|
56
|
+
|
|
57
|
+
def self.must_support_group_description(ig_version, wiki_anchor)
|
|
58
|
+
<<~DESCRIPTION
|
|
59
|
+
During these tests, Inferno will check that the PAS client demonstrates support for
|
|
60
|
+
all required profiles and must support elements. When looking for demonstration of
|
|
61
|
+
these profiles and elements, Inferno will consider requests and responses from
|
|
62
|
+
interactions performed during the PAS scenario group as well as additional ones
|
|
63
|
+
made when executing this group.
|
|
64
|
+
|
|
65
|
+
For additional details on these tests, what they check for, and the requirements
|
|
66
|
+
underlying them, see the ["Client Must Support Tests" section](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Client-Must-Support)
|
|
67
|
+
of the Da Vinci PAS Test Kit wiki, specifically
|
|
68
|
+
- [Which messages Inferno considers when looking for demonstration of must support elements](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Client-Must-Support#evaluated-messages).
|
|
69
|
+
- [What PAS clients must demonstrate to pass these #{ig_version} client must support tests](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Client-Must-Support##{wiki_anchor}).
|
|
70
|
+
DESCRIPTION
|
|
71
|
+
end
|
|
72
|
+
|
|
13
73
|
def self.ms_responses_input_description(operation)
|
|
14
74
|
<<~DESCRIPTION
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
75
|
+
A JSON list of objects ([format](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#response-option-format))
|
|
76
|
+
that Inferno will use to respond to #{operation} requests during the
|
|
77
|
+
*Demonstrate Must Support Coverage* group. For each request, Inferno will
|
|
78
|
+
[select](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#response-option-evaluation)
|
|
79
|
+
and [instantiate](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#response-instantiation)
|
|
80
|
+
a response to return from this list. If no entries match or instantiation fails, Inferno will
|
|
81
|
+
[mock](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#mocked-responses)
|
|
82
|
+
a response.
|
|
83
|
+
DESCRIPTION
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.user_response_input_description(operation, workflow, group_name)
|
|
87
|
+
timing_description = "during the *#{group_name}* group to indicate that the request has been #{workflow}"
|
|
88
|
+
user_response_input_description_base(operation, workflow, timing_description)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.user_response_input_description_for_update_tests(operation, default_decision, test_name)
|
|
92
|
+
timing_description = "during the *#{test_name}* test in the *Claim Updates* group"
|
|
93
|
+
user_response_input_description_base(operation, default_decision, timing_description)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.user_response_input_description_base(operation, workflow, timing_description)
|
|
97
|
+
<<~DESCRIPTION
|
|
98
|
+
If provided, this JSON will be [instantiated](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#response-instantiation)
|
|
99
|
+
and sent in response to the #{operation} request received #{timing_description}.
|
|
100
|
+
If not provided or if instantiation fails, Inferno will [mock](https://github.com/inferno-framework/davinci-pas-test-kit/wiki/Controlling-Simulated-Responses#mocked-responses)
|
|
101
|
+
the response based on the submitted Claim and indicate it has been #{workflow}. In either
|
|
102
|
+
case, the response will be validated against the PAS Response Bundle profile.
|
|
37
103
|
DESCRIPTION
|
|
38
104
|
end
|
|
39
105
|
end
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require_relative '../user_input_response'
|
|
2
|
+
require_relative 'endpoint_session_identification'
|
|
3
|
+
require_relative 'expired_token'
|
|
2
4
|
require_relative '../response_generator'
|
|
5
|
+
require_relative '../subscription_notification_trigger'
|
|
3
6
|
require_relative '../client_urls'
|
|
4
|
-
require_relative '../jobs/send_pas_subscription_notification'
|
|
5
7
|
require_relative '../../cross_suite/fhirpath_utils'
|
|
6
8
|
require_relative '../../cross_suite/response_selection_utils'
|
|
7
9
|
require 'subscriptions_test_kit'
|
|
@@ -11,24 +13,25 @@ module DaVinciPASTestKit
|
|
|
11
13
|
class ClaimEndpoint < Inferno::DSL::SuiteEndpoint
|
|
12
14
|
include SubscriptionsTestKit::SubscriptionsR5BackportR4Client::SubscriptionSimulationUtils
|
|
13
15
|
include ResponseGenerator
|
|
16
|
+
include SubscriptionNotificationTrigger
|
|
14
17
|
include ClientURLs
|
|
15
18
|
include FhirpathUtils
|
|
16
19
|
include ResponseSelectionUtils
|
|
20
|
+
include EndpointSessionIdentification
|
|
21
|
+
include ExpiredToken
|
|
17
22
|
|
|
18
23
|
# override the one from URLs to make it version specific
|
|
19
24
|
def suite_id
|
|
20
25
|
request.path.split('/custom/')[1].split('/')[0] # request.path = {base inferno path}/custom/{suite_id}/...
|
|
21
26
|
end
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
return request.params[:session_path] if request.params[:session_path].present?
|
|
25
|
-
|
|
26
|
-
UDAPSecurityTestKit::MockUDAPServer.issued_token_to_client_id(
|
|
27
|
-
request.headers['authorization']&.delete_prefix('Bearer ')
|
|
28
|
-
)
|
|
29
|
-
end
|
|
28
|
+
error_response_format :operation_outcome
|
|
30
29
|
|
|
31
30
|
def tags
|
|
31
|
+
# Requests rejected for an expired token or a rejected $inquire are not treated as
|
|
32
|
+
# submissions of any workflow.
|
|
33
|
+
return [] if expired_token? || !operation_enabled?
|
|
34
|
+
|
|
32
35
|
operation_tag = operation == 'submit' ? SUBMIT_TAG : INQUIRE_TAG
|
|
33
36
|
workflow_tag = WORKFLOW_TAG_MAP[workflow]
|
|
34
37
|
|
|
@@ -52,6 +55,13 @@ module DaVinciPASTestKit
|
|
|
52
55
|
test.config.options[:suppress_notifications] == true
|
|
53
56
|
end
|
|
54
57
|
|
|
58
|
+
# Tests must opt in to each operation with the submit_enabled and inquire_enabled options. Inferno responds
|
|
59
|
+
# to every request for an operation that is not enabled with an OperationOutcome, without tagging the
|
|
60
|
+
# request or continuing the test.
|
|
61
|
+
def operation_enabled?
|
|
62
|
+
%w[inquire submit].include?(operation) && test.config.options[:"#{operation}_enabled"] == true
|
|
63
|
+
end
|
|
64
|
+
|
|
55
65
|
def workflow
|
|
56
66
|
case test.id
|
|
57
67
|
when /.*pended.*/
|
|
@@ -70,7 +80,7 @@ module DaVinciPASTestKit
|
|
|
70
80
|
end
|
|
71
81
|
|
|
72
82
|
def must_support_workflow?
|
|
73
|
-
test.id =~ /.*must_support.*/
|
|
83
|
+
test.id =~ /.*must_support.*/
|
|
74
84
|
end
|
|
75
85
|
|
|
76
86
|
WORKFLOW_TAG_MAP = {
|
|
@@ -87,6 +97,11 @@ module DaVinciPASTestKit
|
|
|
87
97
|
|
|
88
98
|
response.format = :json
|
|
89
99
|
|
|
100
|
+
unless operation_enabled?
|
|
101
|
+
make_rejected_operation_response
|
|
102
|
+
return
|
|
103
|
+
end
|
|
104
|
+
|
|
90
105
|
# Handle the operation failure and processing error workflows, which require a user-provided response.
|
|
91
106
|
if workflow == :operation_failure
|
|
92
107
|
make_operation_failure_response
|
|
@@ -136,10 +151,11 @@ module DaVinciPASTestKit
|
|
|
136
151
|
end
|
|
137
152
|
|
|
138
153
|
def update_result
|
|
139
|
-
if
|
|
154
|
+
if expired_token?
|
|
140
155
|
UDAPSecurityTestKit::MockUDAPServer.update_response_for_expired_token(response, 'Bearer token')
|
|
141
156
|
return
|
|
142
157
|
end
|
|
158
|
+
return unless operation_enabled? # keep waiting for the request that the test is looking for
|
|
143
159
|
|
|
144
160
|
results_repo.update_result(result.id, 'pass') unless test.config.options[:accepts_multiple_requests]
|
|
145
161
|
end
|
|
@@ -152,19 +168,29 @@ module DaVinciPASTestKit
|
|
|
152
168
|
private
|
|
153
169
|
|
|
154
170
|
# Resolves the user-provided response, using criteria-based selection for must support
|
|
155
|
-
# workflows or the single-response approach for other workflows
|
|
171
|
+
# workflows or the single-response approach for other workflows
|
|
172
|
+
# and replaces {{fhirpath}} tokens with values from the request.
|
|
156
173
|
def resolve_user_response(req_bundle)
|
|
157
|
-
if must_support_workflow?
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
174
|
+
user_response = if must_support_workflow?
|
|
175
|
+
select_must_support_response(req_bundle)
|
|
176
|
+
else
|
|
177
|
+
UserInputResponse.user_inputted_response(test, operation, result)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
return nil unless user_response.present?
|
|
181
|
+
|
|
182
|
+
replace_tokens(user_response, req_bundle)
|
|
183
|
+
rescue FhirpathUtils::FhirpathServiceError => e
|
|
184
|
+
add_result_warning(
|
|
185
|
+
'Unable to instantiate a tester-provided response, so Inferno will generate a default response: ' \
|
|
186
|
+
"#{e.message}"
|
|
187
|
+
)
|
|
188
|
+
nil
|
|
162
189
|
end
|
|
163
190
|
|
|
164
191
|
# Selects the first tester-provided response candidate whose selection criteria all
|
|
165
192
|
# match the incoming request, extracts its response Bundle (unwrapping it when the
|
|
166
|
-
# candidate pairs the Bundle with criteria),
|
|
167
|
-
# values from the request. Returns nil, causing Inferno to generate a default
|
|
193
|
+
# candidate pairs the Bundle with criteria). Returns nil, causing Inferno to generate a default
|
|
168
194
|
# response, if no candidates are provided or none match. Problems with the
|
|
169
195
|
# tester-provided input or the FHIRPath service also result in nil, with a warning
|
|
170
196
|
# on the waiting test so that the tester can see what went wrong.
|
|
@@ -188,20 +214,22 @@ module DaVinciPASTestKit
|
|
|
188
214
|
"Selected tester-provided response bundle #{selected_index + 1} of #{candidates.length} " \
|
|
189
215
|
"for #{operation_url_suffix} request ##{request_number}."
|
|
190
216
|
)
|
|
191
|
-
|
|
217
|
+
entity_response(candidates[selected_index])
|
|
192
218
|
rescue UserInputResponse::InvalidInputError, FhirpathUtils::FhirpathServiceError => e
|
|
193
219
|
add_result_warning(
|
|
194
|
-
|
|
220
|
+
'Unable to select a tester-provided response, so Inferno will generate a default response: ' \
|
|
221
|
+
"#{e.message}"
|
|
195
222
|
)
|
|
196
223
|
nil
|
|
197
224
|
end
|
|
198
225
|
|
|
199
226
|
# Replaces {{fhirpath}} tokens using values from the incoming request, round-tripping
|
|
200
|
-
# the result through the FHIR model to normalize it.
|
|
201
|
-
#
|
|
202
|
-
#
|
|
227
|
+
# the result through the FHIR model to normalize it. The response may be a parsed hash
|
|
228
|
+
# (must support workflow) or the raw JSON string of a single input. If a replaced value
|
|
229
|
+
# breaks the JSON structure, the result cannot be returned as a FHIR response, so nil is
|
|
230
|
+
# returned with a warning on the waiting test and Inferno generates a default response.
|
|
203
231
|
def replace_tokens(bundle_hash, req_bundle)
|
|
204
|
-
bundle_json = bundle_hash.to_json
|
|
232
|
+
bundle_json = bundle_hash.is_a?(String) ? bundle_hash : bundle_hash.to_json
|
|
205
233
|
replaced = replace_tokens_in_string(bundle_json, req_bundle)
|
|
206
234
|
return bundle_json if replaced.equal?(bundle_json)
|
|
207
235
|
|
|
@@ -252,68 +280,80 @@ module DaVinciPASTestKit
|
|
|
252
280
|
end
|
|
253
281
|
|
|
254
282
|
def make_processing_error_response
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
response.status = 400
|
|
258
|
-
response.body = FHIR::OperationOutcome.new(
|
|
259
|
-
issue: FHIR::OperationOutcome::Issue.new(
|
|
260
|
-
severity: 'fatal', code: 'required',
|
|
261
|
-
details: FHIR::CodeableConcept.new(
|
|
262
|
-
text: 'The processing_error_response input is required for this test and was not provided.'
|
|
263
|
-
)
|
|
264
|
-
)
|
|
265
|
-
).to_json
|
|
283
|
+
unless UserInputResponse.user_inputted_response(test, operation, result).present?
|
|
284
|
+
error_outcome_response('The processing_error_response input is required for this test and was not provided.')
|
|
266
285
|
return
|
|
267
286
|
end
|
|
268
287
|
|
|
288
|
+
req_bundle = FHIR.from_contents(request.body.string)
|
|
289
|
+
if req_bundle.blank?
|
|
290
|
+
handle_missing_required_elements(nil, response)
|
|
291
|
+
return
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Unlike other workflows, there is no mocked response to fall back to when instantiation fails.
|
|
295
|
+
instantiated_response = resolve_user_response(req_bundle)
|
|
296
|
+
if instantiated_response.blank?
|
|
297
|
+
error_outcome_response('The processing_error_response input could not be instantiated. ' \
|
|
298
|
+
'See the warnings on the waiting test for details.')
|
|
299
|
+
return
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
claim_entry = req_bundle.entry&.find { |e| e&.resource&.resourceType == 'Claim' }
|
|
269
303
|
response.status = 200
|
|
270
|
-
response.body =
|
|
304
|
+
response.body = update_tester_provided_response(instantiated_response, claim_entry&.fullUrl, operation,
|
|
305
|
+
ig_version)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def make_rejected_operation_response
|
|
309
|
+
response.status = 501
|
|
310
|
+
response.body = FHIR::OperationOutcome.new(
|
|
311
|
+
issue: FHIR::OperationOutcome::Issue.new(
|
|
312
|
+
severity: 'error', code: 'not-supported',
|
|
313
|
+
details: FHIR::CodeableConcept.new(
|
|
314
|
+
text: "Inferno does not support the $#{operation} operation during this test."
|
|
315
|
+
)
|
|
316
|
+
)
|
|
317
|
+
).to_json
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def error_outcome_response(text)
|
|
321
|
+
response.status = 400
|
|
322
|
+
response.body = FHIR::OperationOutcome.new(
|
|
323
|
+
issue: FHIR::OperationOutcome::Issue.new(
|
|
324
|
+
severity: 'fatal', code: 'required', details: FHIR::CodeableConcept.new(text:)
|
|
325
|
+
)
|
|
326
|
+
).to_json
|
|
271
327
|
end
|
|
272
328
|
|
|
273
329
|
def operation
|
|
274
330
|
request.path.split('$').last
|
|
275
331
|
end
|
|
276
332
|
|
|
277
|
-
|
|
278
|
-
notification_bearer_token = client_access_token_input(result)
|
|
279
|
-
notification_contents = notification_json(response_bundle_json, decision, generated_claim_response_uuid)
|
|
333
|
+
# Helper methods for SubscriptionNotificationTrigger
|
|
280
334
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
ig_version)
|
|
335
|
+
def notification_test_run_id
|
|
336
|
+
test_run.id
|
|
284
337
|
end
|
|
285
338
|
|
|
286
|
-
def
|
|
287
|
-
|
|
288
|
-
|
|
339
|
+
def notification_test_session_id
|
|
340
|
+
test_run.test_session_id
|
|
341
|
+
end
|
|
289
342
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
else
|
|
293
|
-
generate_notification(response_bundle_json, decision)
|
|
294
|
-
end
|
|
343
|
+
def notification_result_id
|
|
344
|
+
result.id
|
|
295
345
|
end
|
|
296
346
|
|
|
297
|
-
def
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
mock_full_resource_notification_bundle(response_bundle_json, subscription_reference, subscription_topic,
|
|
304
|
-
decision, ig_version)
|
|
305
|
-
else # assume id-only since empty not allowed - if asked for empty, other failures will occur
|
|
306
|
-
mock_id_only_notification_bundle(response_bundle_json, subscription_reference, subscription_topic,
|
|
307
|
-
ig_version)
|
|
308
|
-
end
|
|
347
|
+
def notification_bearer_token
|
|
348
|
+
client_access_token_input(result)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def tester_notification_bundle
|
|
352
|
+
notification_bundle_input(result)
|
|
309
353
|
end
|
|
310
354
|
|
|
311
|
-
def
|
|
312
|
-
|
|
313
|
-
&.find do |ext|
|
|
314
|
-
ext['url'] == 'http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content'
|
|
315
|
-
end
|
|
316
|
-
content_ext&.dig('valueCode')
|
|
355
|
+
def client_subscription_json
|
|
356
|
+
find_subscription(test_run.test_session_id, as_json: true)
|
|
317
357
|
end
|
|
318
358
|
end
|
|
319
359
|
end
|