davinci_crd_test_kit 0.13.0 → 0.14.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/inferno_crd_client_suite.json.erb +20 -14
- data/config/presets/inferno_crd_client_suite_prefetch_subset_v221.json.erb +125 -0
- data/config/presets/inferno_crd_client_suite_v221.json.erb +124 -0
- data/config/presets/inferno_crd_server_suite.json.erb +58 -1
- data/config/presets/inferno_crd_server_suite_v221.json.erb +94 -0
- data/config/presets/ri_crd_request_generator.json_v221.json.erb +13 -0
- data/config/presets/ri_crd_server.json.erb +19 -19
- data/lib/davinci_crd_test_kit/client/client_base_urls.rb +80 -0
- data/lib/davinci_crd_test_kit/{client_hook_request_validation.rb → client/client_hook_request_validation.rb} +1 -1
- data/lib/davinci_crd_test_kit/client/crd_client_options.rb +30 -0
- data/lib/davinci_crd_test_kit/client/endpoints/cds_services_discovery_handler.rb +34 -0
- data/lib/davinci_crd_test_kit/client/endpoints/custom_service_response.rb +342 -0
- data/lib/davinci_crd_test_kit/client/endpoints/gather_response_generation_data.rb +410 -0
- data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +233 -0
- data/lib/davinci_crd_test_kit/{mock_service_response.rb → client/endpoints/mock_service_response.rb} +165 -59
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/companions_prerequisites.json +1 -0
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/create_update_coverage_information.json +3 -2
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/launch_smart_app.json +8 -1
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/propose_alternate_request.json +1 -0
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/request_form_completion.json +17 -16
- data/lib/davinci_crd_test_kit/client/multi_request_message_helper.rb +35 -0
- data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +38 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_create_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_read_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_search_test.rb +234 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_update_test.rb +43 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_validation_test.rb +63 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/decode_auth_token_test.rb +65 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +109 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_header_test.rb +70 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +85 -0
- data/lib/davinci_crd_test_kit/{routes/cds-services.json → client/v2.0.1/cds-services-v201.json} +1 -1
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +108 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_card_must_support_group.rb +31 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +105 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +105 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_fhir_api_group.rb +790 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +74 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +111 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +116 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +113 -0
- data/lib/davinci_crd_test_kit/{client_registration_group.rb → client/v2.0.1/client_registration_group.rb} +12 -8
- data/lib/davinci_crd_test_kit/client/v2.0.1/client_urls.rb +13 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/crd_client_suite.rb +134 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/appointment_book_receive_request_test.rb +129 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_discharge_receive_request_test.rb +126 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_start_receive_request_test.rb +126 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_dispatch_receive_request_test.rb +138 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_select_receive_request_test.rb +134 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_sign_receive_request_test.rb +136 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +93 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +62 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +62 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_registration_verification_test.rb +94 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_service_registration_attestation_test.rb +40 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +86 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_optional_fields_test.rb +63 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +96 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_required_fields_test.rb +55 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_context_test.rb +70 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_prefetch_test.rb +62 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +83 -0
- data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +79 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +212 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_crd_update_verification_group.rb +18 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +69 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +120 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_header_test.rb +92 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +93 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +198 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +202 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +102 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +28 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +96 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +95 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +88 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +64 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +32 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +101 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +102 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +107 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +27 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_urls.rb +27 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +229 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +63 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +60 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +45 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +135 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +103 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +156 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +157 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +157 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +165 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +165 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +165 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +64 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +49 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_registration_verification_test.rb +161 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +107 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +47 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +152 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +55 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +123 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +127 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +55 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +54 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +48 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +74 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +30 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +77 -0
- data/lib/davinci_crd_test_kit/cross_suite/base_urls.rb +20 -0
- data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +312 -0
- data/lib/davinci_crd_test_kit/{cards_validation.rb → cross_suite/cards_validation.rb} +104 -47
- data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu201_metadata.yml +27 -0
- data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu221_metadata.yml +60 -0
- data/lib/davinci_crd_test_kit/cross_suite/fhirpath_on_cds_request.rb +177 -0
- data/lib/davinci_crd_test_kit/{hook_request_field_validation.rb → cross_suite/hook_request_field_validation.rb} +282 -203
- data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +220 -0
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +462 -0
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_contents_validation.rb +81 -0
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +48 -0
- data/lib/davinci_crd_test_kit/cross_suite/profiles_and_resource_types.rb +63 -0
- data/lib/davinci_crd_test_kit/cross_suite/replace_tokens.rb +38 -0
- data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +202 -0
- data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +274 -0
- data/lib/davinci_crd_test_kit/{suggestion_actions_validation.rb → cross_suite/suggestion_actions_validation.rb} +70 -50
- data/lib/davinci_crd_test_kit/cross_suite/tags.rb +42 -0
- data/lib/davinci_crd_test_kit/metadata.rb +10 -44
- data/lib/davinci_crd_test_kit/requirements/cds-hooks-library_1.0.1_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/requirements/cds-hooks_2.0_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +742 -65
- data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +279 -54
- data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +1430 -0
- data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +36 -45
- data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +143 -0
- data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.0.1_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
- data/lib/davinci_crd_test_kit/server/endpoints/jwk_set_endpoint_handler.rb +13 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_create_endpoint.rb +23 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_delete_endpoint.rb +30 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_metadata_endpoint.rb +112 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_read_endpoint.rb +21 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_request_handler.rb +261 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_search_endpoint.rb +561 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_update_endpoint.rb +24 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/stress-test-Bundle.json +54687 -0
- data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr_endpoints.rb +95 -0
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +225 -0
- data/lib/davinci_crd_test_kit/{jwt_helper.rb → server/jwt_helper.rb} +1 -12
- data/lib/davinci_crd_test_kit/server/resource_extractor.rb +68 -0
- data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +165 -0
- data/lib/davinci_crd_test_kit/server/server_base_urls.rb +30 -0
- data/lib/davinci_crd_test_kit/{server_hook_helper.rb → server/server_hook_helper.rb} +1 -1
- data/lib/davinci_crd_test_kit/{server_hook_request_validation.rb → server/server_hook_request_validation.rb} +1 -1
- data/lib/davinci_crd_test_kit/{test_helper.rb → server/server_test_helper.rb} +7 -3
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Appointment.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ClaimResponse.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/CommunicationRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Coverage.yml +21 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Device.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/DeviceRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Encounter.yml +7 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Location.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/MedicationRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/NutritionOrder.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Organization.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Patient.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Practitioner.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/PractitionerRole.yml +40 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ServiceRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Task.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/VisionPrescription.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +99 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_endpoint_test.rb +90 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_services_validation_test.rb +67 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/interaction/server_invoke_hook_test.rb +12 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +34 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/external_reference_card_across_hooks_validation_test.rb +30 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/instructions_card_received_across_hooks_test.rb +27 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_appointment_book_group.rb +191 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_demonstrate_hook_response_group.rb +93 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_discovery_group.rb +62 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_discharge_group.rb +186 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_start_group.rb +186 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +73 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_dispatch_group.rb +191 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_select_group.rb +211 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_sign_group.rb +216 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_required_card_response_validation_group.rb +28 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/server_urls.rb +13 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_context_validation_test.rb +30 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_optional_fields_validation_test.rb +39 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_required_fields_validation_test.rb +40 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/additional_orders_validation_test.rb +59 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/card_optional_fields_validation_test.rb +51 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_received_test.rb +65 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_validation_test.rb +120 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +70 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/external_reference_card_validation_test.rb +37 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/form_completion_response_validation_test.rb +67 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/instructions_card_received_test.rb +30 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/launch_smart_app_card_validation_test.rb +39 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/propose_alternate_request_card_validation_test.rb +46 -0
- data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/service_response_validation_test.rb +83 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withorder.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withoutorder.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/CommunicationRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Coverage.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Device.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/DeviceRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Encounter.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Location.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/MedicationRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/NutritionOrder.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Organization.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Patient.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/PractitionerRole.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/ServiceRequest.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/VisionPrescription.yml +5 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +115 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_configuration_test.rb +159 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_endpoint_test.rb +90 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_prefetch_support_test.rb +43 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_services_validation_test.rb +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_test.rb +17 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_must_support_test.rb +71 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +36 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/supported_us_core_versions_test.rb +118 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +213 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +93 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +69 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +194 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +194 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +73 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +214 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +219 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +241 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_required_card_response_validation_group.rb +30 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_urls.rb +13 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +30 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_no_custom_extensions_test.rb +120 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +39 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +40 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +66 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/all_responses_include_coverage_information_test.rb +123 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/card_optional_fields_validation_test.rb +57 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_info_configuration_test.rb +83 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_received_test.rb +65 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +184 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +75 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +47 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +91 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +137 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +32 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +49 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/order_dispatch_coverage_information_test.rb +38 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +54 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +97 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +78 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +78 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +78 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_billing_options_test.rb +43 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_configuration_test.rb +44 -0
- data/lib/davinci_crd_test_kit/version.rb +2 -2
- data/lib/davinci_crd_test_kit.rb +4 -2
- metadata +297 -93
- data/lib/davinci_crd_test_kit/client_fhir_api_group.rb +0 -785
- data/lib/davinci_crd_test_kit/client_hooks_group.rb +0 -74
- data/lib/davinci_crd_test_kit/client_tests/appointment_book_receive_request_test.rb +0 -93
- data/lib/davinci_crd_test_kit/client_tests/client_appointment_book_group.rb +0 -75
- data/lib/davinci_crd_test_kit/client_tests/client_display_cards_attest.rb +0 -48
- data/lib/davinci_crd_test_kit/client_tests/client_encounter_discharge_group.rb +0 -73
- data/lib/davinci_crd_test_kit/client_tests/client_encounter_start_group.rb +0 -73
- data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_create_test.rb +0 -42
- data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_read_test.rb +0 -40
- data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_search_test.rb +0 -232
- data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_update_test.rb +0 -42
- data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_validation_test.rb +0 -61
- data/lib/davinci_crd_test_kit/client_tests/client_order_dispatch_group.rb +0 -79
- data/lib/davinci_crd_test_kit/client_tests/client_order_select_group.rb +0 -82
- data/lib/davinci_crd_test_kit/client_tests/client_order_sign_group.rb +0 -81
- data/lib/davinci_crd_test_kit/client_tests/client_registration_verification_test.rb +0 -88
- data/lib/davinci_crd_test_kit/client_tests/decode_auth_token_test.rb +0 -60
- data/lib/davinci_crd_test_kit/client_tests/encounter_discharge_receive_request_test.rb +0 -90
- data/lib/davinci_crd_test_kit/client_tests/encounter_start_receive_request_test.rb +0 -90
- data/lib/davinci_crd_test_kit/client_tests/hook_request_optional_fields_test.rb +0 -57
- data/lib/davinci_crd_test_kit/client_tests/hook_request_required_fields_test.rb +0 -49
- data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_context_test.rb +0 -68
- data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_prefetch_test.rb +0 -69
- data/lib/davinci_crd_test_kit/client_tests/order_dispatch_receive_request_test.rb +0 -102
- data/lib/davinci_crd_test_kit/client_tests/order_select_receive_request_test.rb +0 -98
- data/lib/davinci_crd_test_kit/client_tests/order_sign_receive_request_test.rb +0 -101
- data/lib/davinci_crd_test_kit/client_tests/retrieve_jwks_test.rb +0 -105
- data/lib/davinci_crd_test_kit/client_tests/submitted_response_validation.rb +0 -48
- data/lib/davinci_crd_test_kit/client_tests/token_header_test.rb +0 -65
- data/lib/davinci_crd_test_kit/client_tests/token_payload_test.rb +0 -78
- data/lib/davinci_crd_test_kit/crd_client_suite.rb +0 -193
- data/lib/davinci_crd_test_kit/crd_options.rb +0 -9
- data/lib/davinci_crd_test_kit/crd_server_suite.rb +0 -125
- data/lib/davinci_crd_test_kit/igs/davinci-crd-2.0.1.tgz +0 -0
- data/lib/davinci_crd_test_kit/routes/cds_services_discovery_handler.rb +0 -18
- data/lib/davinci_crd_test_kit/routes/hook_request_endpoint.rb +0 -77
- data/lib/davinci_crd_test_kit/routes/jwk_set_endpoint_handler.rb +0 -15
- data/lib/davinci_crd_test_kit/server_appointment_book_group.rb +0 -176
- data/lib/davinci_crd_test_kit/server_demonstrate_hook_response_group.rb +0 -77
- data/lib/davinci_crd_test_kit/server_discovery_group.rb +0 -60
- data/lib/davinci_crd_test_kit/server_encounter_discharge_group.rb +0 -170
- data/lib/davinci_crd_test_kit/server_encounter_start_group.rb +0 -170
- data/lib/davinci_crd_test_kit/server_hooks_group.rb +0 -71
- data/lib/davinci_crd_test_kit/server_order_dispatch_group.rb +0 -176
- data/lib/davinci_crd_test_kit/server_order_select_group.rb +0 -195
- data/lib/davinci_crd_test_kit/server_order_sign_group.rb +0 -201
- data/lib/davinci_crd_test_kit/server_required_card_response_validation_group.rb +0 -26
- data/lib/davinci_crd_test_kit/server_tests/additional_orders_validation_test.rb +0 -68
- data/lib/davinci_crd_test_kit/server_tests/card_optional_fields_validation_test.rb +0 -47
- data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_across_hooks_validation_test.rb +0 -32
- data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_received_test.rb +0 -63
- data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_validation_test.rb +0 -118
- data/lib/davinci_crd_test_kit/server_tests/create_or_update_coverage_info_response_validation_test.rb +0 -71
- data/lib/davinci_crd_test_kit/server_tests/discovery_endpoint_test.rb +0 -88
- data/lib/davinci_crd_test_kit/server_tests/discovery_services_validation_test.rb +0 -65
- data/lib/davinci_crd_test_kit/server_tests/external_reference_card_across_hooks_validation_test.rb +0 -28
- data/lib/davinci_crd_test_kit/server_tests/external_reference_card_validation_test.rb +0 -36
- data/lib/davinci_crd_test_kit/server_tests/form_completion_response_validation_test.rb +0 -78
- data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_across_hooks_test.rb +0 -25
- data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_test.rb +0 -26
- data/lib/davinci_crd_test_kit/server_tests/launch_smart_app_card_validation_test.rb +0 -38
- data/lib/davinci_crd_test_kit/server_tests/propose_alternate_request_card_validation_test.rb +0 -63
- data/lib/davinci_crd_test_kit/server_tests/service_call_test.rb +0 -101
- data/lib/davinci_crd_test_kit/server_tests/service_request_context_validation_test.rb +0 -28
- data/lib/davinci_crd_test_kit/server_tests/service_request_optional_fields_validation_test.rb +0 -37
- data/lib/davinci_crd_test_kit/server_tests/service_request_required_fields_validation_test.rb +0 -38
- data/lib/davinci_crd_test_kit/server_tests/service_response_validation_test.rb +0 -81
- data/lib/davinci_crd_test_kit/tags.rb +0 -10
- data/lib/davinci_crd_test_kit/urls.rb +0 -52
- /data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/external_reference.json +0 -0
- /data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/instructions.json +0 -0
- /data/lib/davinci_crd_test_kit/{crd_jwks.json → server/endpoints/crd_jwks.json} +0 -0
- /data/lib/davinci_crd_test_kit/{jwks.rb → server/endpoints/jwks.rb} +0 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
require_relative '../../cross_suite/tags'
|
|
2
|
+
|
|
3
|
+
module DaVinciCRDTestKit
|
|
4
|
+
# Make requests to client's FHIR server to use in building responses
|
|
5
|
+
module GatherResponseGenerationData
|
|
6
|
+
REFERENCES_TO_READ_BY_RESOURCE_TYPE = {
|
|
7
|
+
Appointment: [
|
|
8
|
+
'basedOn',
|
|
9
|
+
'participant.actor'
|
|
10
|
+
],
|
|
11
|
+
CommunicationRequest: [
|
|
12
|
+
'requester',
|
|
13
|
+
'sender',
|
|
14
|
+
'recipient'
|
|
15
|
+
],
|
|
16
|
+
DeviceRequest: [
|
|
17
|
+
'requester',
|
|
18
|
+
'performer'
|
|
19
|
+
],
|
|
20
|
+
MedicationRequest: [
|
|
21
|
+
'requester',
|
|
22
|
+
'performer',
|
|
23
|
+
'medicationReference',
|
|
24
|
+
'dispenseRequest.performer'
|
|
25
|
+
],
|
|
26
|
+
NutritionOrder: [
|
|
27
|
+
'orderer'
|
|
28
|
+
],
|
|
29
|
+
ServiceRequest: [
|
|
30
|
+
'requester',
|
|
31
|
+
'performer',
|
|
32
|
+
'locationReference'
|
|
33
|
+
],
|
|
34
|
+
VisionPrescription: [
|
|
35
|
+
'prescriber'
|
|
36
|
+
],
|
|
37
|
+
Encounter: [
|
|
38
|
+
'participant.individual',
|
|
39
|
+
'location.location',
|
|
40
|
+
'serviceProvider'
|
|
41
|
+
],
|
|
42
|
+
PractitionerRole: [
|
|
43
|
+
'practitioner',
|
|
44
|
+
'organization',
|
|
45
|
+
'location'
|
|
46
|
+
]
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
def hook_instance_data_fetch_tag
|
|
50
|
+
@hook_instance_data_fetch_tag ||= TagMethods.hook_instance_data_fetch_tag(request_body['hookInstance'])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def gather_appointment_book_data
|
|
54
|
+
appointment_book_to_read = []
|
|
55
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
56
|
+
encounter_id = request_body.dig('context', 'encounterId')
|
|
57
|
+
user_id = request_body.dig('context', 'userId')
|
|
58
|
+
appointment_book_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
59
|
+
appointment_book_to_read << "Encounter/#{encounter_id}" if encounter_id.present?
|
|
60
|
+
appointment_book_to_read << user_id if user_id.present?
|
|
61
|
+
|
|
62
|
+
appointment_book_to_analyze = extract_bundle_entries(request_body.dig('context', 'appointments'))
|
|
63
|
+
|
|
64
|
+
gather_data_for_request(appointment_book_to_read, appointment_book_to_analyze)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def gather_encounter_start_data
|
|
68
|
+
encounter_start_to_read = []
|
|
69
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
70
|
+
encounter_id = request_body.dig('context', 'encounterId')
|
|
71
|
+
user_id = request_body.dig('context', 'userId')
|
|
72
|
+
encounter_start_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
73
|
+
encounter_start_to_read << "Encounter/#{encounter_id}" if encounter_id.present?
|
|
74
|
+
encounter_start_to_read << user_id if user_id.present?
|
|
75
|
+
|
|
76
|
+
gather_data_for_request(encounter_start_to_read, [])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def gather_encounter_discharge_data
|
|
80
|
+
encounter_discharge_to_read = []
|
|
81
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
82
|
+
encounter_id = request_body.dig('context', 'encounterId')
|
|
83
|
+
user_id = request_body.dig('context', 'userId')
|
|
84
|
+
encounter_discharge_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
85
|
+
encounter_discharge_to_read << "Encounter/#{encounter_id}" if encounter_id.present?
|
|
86
|
+
encounter_discharge_to_read << user_id if user_id.present?
|
|
87
|
+
|
|
88
|
+
gather_data_for_request(encounter_discharge_to_read, [])
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def gather_order_select_data
|
|
92
|
+
order_sign_to_read = []
|
|
93
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
94
|
+
encounter_id = request_body.dig('context', 'encounterId')
|
|
95
|
+
user_id = request_body.dig('context', 'userId')
|
|
96
|
+
order_sign_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
97
|
+
order_sign_to_read << "Encounter/#{encounter_id}" if encounter_id.present?
|
|
98
|
+
order_sign_to_read << user_id if user_id.present?
|
|
99
|
+
|
|
100
|
+
order_sign_to_analyze = extract_bundle_entries(request_body.dig('context', 'draftOrders')).select do |resource|
|
|
101
|
+
request_body.dig('context', 'selections').include?("#{resource['resourceType']}/#{resource['id']}")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
gather_data_for_request(order_sign_to_read, order_sign_to_analyze)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def gather_order_sign_data
|
|
108
|
+
order_sign_to_read = []
|
|
109
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
110
|
+
encounter_id = request_body.dig('context', 'encounterId')
|
|
111
|
+
user_id = request_body.dig('context', 'userId')
|
|
112
|
+
order_sign_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
113
|
+
order_sign_to_read << "Encounter/#{encounter_id}" if encounter_id.present?
|
|
114
|
+
order_sign_to_read << user_id if user_id.present?
|
|
115
|
+
|
|
116
|
+
order_sign_to_analyze = extract_bundle_entries(request_body.dig('context', 'draftOrders'))
|
|
117
|
+
|
|
118
|
+
gather_data_for_request(order_sign_to_read, order_sign_to_analyze)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def gather_order_dispatch_data
|
|
122
|
+
order_dispatch_to_read = []
|
|
123
|
+
patient_id = request_body.dig('context', 'patientId')
|
|
124
|
+
order_id = request_body.dig('context', 'order')
|
|
125
|
+
performer_id = request_body.dig('context', 'performer')
|
|
126
|
+
order_dispatch_to_read << "Patient/#{patient_id}" if patient_id.present?
|
|
127
|
+
order_dispatch_to_read << order_id if order_id.present?
|
|
128
|
+
order_dispatch_to_read << performer_id if performer_id.present?
|
|
129
|
+
|
|
130
|
+
gather_data_for_request(order_dispatch_to_read, [request_body.dig('context', 'task')].compact)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def extract_bundle_entries(bundle)
|
|
134
|
+
return [] unless bundle.present? && bundle.is_a?(Hash) && bundle['entry'].is_a?(Array)
|
|
135
|
+
|
|
136
|
+
bundle['entry'].map do |entry|
|
|
137
|
+
next unless entry.is_a?(Hash) && entry['resource'].is_a?(Hash)
|
|
138
|
+
|
|
139
|
+
entry['resource']
|
|
140
|
+
end.compact
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def gather_data_for_request(to_read_list, to_analyze_list)
|
|
144
|
+
to_analyze_list.each do |resource|
|
|
145
|
+
next unless resource.present?
|
|
146
|
+
|
|
147
|
+
find_references_to_read(resource, to_read_list)
|
|
148
|
+
analyzed_resources["#{resource['resourceType']}/#{resource['id']}"] = resource
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
read_and_analyze(to_read_list.pop, to_read_list) until to_read_list.empty?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def read_and_analyze(reference, to_read_list)
|
|
155
|
+
normalized_reference = normalize_reference(reference)
|
|
156
|
+
return if analyzed_resources.key?(normalized_reference)
|
|
157
|
+
|
|
158
|
+
resource =
|
|
159
|
+
if prefetched_resources.key?(normalized_reference)
|
|
160
|
+
prefetched_resources[normalized_reference]
|
|
161
|
+
else
|
|
162
|
+
fetch_reference(normalized_reference)
|
|
163
|
+
end
|
|
164
|
+
analyzed_resources[normalized_reference] = resource
|
|
165
|
+
return unless resource.present?
|
|
166
|
+
|
|
167
|
+
find_references_to_read(resource, to_read_list)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# turn absolute references into relative if
|
|
171
|
+
# for the fhir server indicated in the request
|
|
172
|
+
def normalize_reference(reference)
|
|
173
|
+
server = "#{request_body['fhirServer']&.chomp('/')}/"
|
|
174
|
+
|
|
175
|
+
if request_body['fhirServer'].present? && reference.starts_with?(server)
|
|
176
|
+
reference[server.length..]
|
|
177
|
+
else
|
|
178
|
+
reference
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def fetch_reference(reference, additional_tag: nil, parse_as_fhir: false)
|
|
183
|
+
response = execute_request(reference)
|
|
184
|
+
return nil unless response.present?
|
|
185
|
+
|
|
186
|
+
tags = [DATA_FETCH_TAG, hook_instance_data_fetch_tag]
|
|
187
|
+
tags << additional_tag if additional_tag.present?
|
|
188
|
+
persist_query_request(response, tags)
|
|
189
|
+
return nil unless response.status.to_s.starts_with?('2')
|
|
190
|
+
|
|
191
|
+
begin
|
|
192
|
+
parse_as_fhir ? FHIR.from_contents(response.body) : JSON.parse(response.body)
|
|
193
|
+
rescue JSON::ParserError
|
|
194
|
+
nil
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def find_references_to_read(resource, to_read_list)
|
|
199
|
+
references_to_read = REFERENCES_TO_READ_BY_RESOURCE_TYPE[resource['resourceType']&.to_sym]
|
|
200
|
+
return [] unless references_to_read.present?
|
|
201
|
+
|
|
202
|
+
references_to_read.each do |target_path|
|
|
203
|
+
get_literal_reference_values(resource, target_path).each do |reference|
|
|
204
|
+
to_read_list << reference unless to_read_list.include?(reference)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Precondition: at most one level of nesting in the path
|
|
210
|
+
def get_literal_reference_values(resource, path)
|
|
211
|
+
if path.include?('.')
|
|
212
|
+
first_element, path = path.split('.')
|
|
213
|
+
resource = resource[first_element]
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
reference_objects =
|
|
217
|
+
case resource
|
|
218
|
+
when Hash
|
|
219
|
+
[resource[path]].flatten
|
|
220
|
+
when Array
|
|
221
|
+
resource.map { |entry| entry[path] }
|
|
222
|
+
else
|
|
223
|
+
[]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
reference_objects.map { |entry| entry['reference'] if entry.present? }.compact
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def request_coverage
|
|
230
|
+
@request_coverage ||= find_coverage_for_request
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def prefetched_coverage
|
|
234
|
+
@prefetched_coverage ||=
|
|
235
|
+
if request_body.dig('prefetch', 'coverage').present?
|
|
236
|
+
FHIR.from_contents(request_body.dig('prefetch', 'coverage').to_json)
|
|
237
|
+
elsif request_body.dig('prefetch', 'cov').present?
|
|
238
|
+
FHIR.from_contents(request_body.dig('prefetch', 'cov').to_json)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def find_coverage_for_request
|
|
243
|
+
resource =
|
|
244
|
+
if prefetched_coverage.present?
|
|
245
|
+
prefetched_coverage
|
|
246
|
+
else
|
|
247
|
+
query_for_coverages
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
return unless resource.is_a?(FHIR::Bundle)
|
|
251
|
+
|
|
252
|
+
resource.entry&.first&.resource
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def fhir_server_connection
|
|
256
|
+
@fhir_server_connection ||=
|
|
257
|
+
if request_body['fhirServer'].present? &&
|
|
258
|
+
request_body['fhirAuthorization'].present? &&
|
|
259
|
+
request_body['fhirAuthorization']['access_token'].present?
|
|
260
|
+
Faraday.new(url: request_body['fhirServer'], request: { open_timeout: 10 },
|
|
261
|
+
headers: data_request_headers)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def data_request_headers
|
|
266
|
+
@data_request_headers ||=
|
|
267
|
+
{ 'Authorization' => "Bearer #{request_body['fhirAuthorization']['access_token']}" }
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def execute_request(query)
|
|
271
|
+
fhir_server_connection&.get(query)
|
|
272
|
+
rescue Faraday::Error => e
|
|
273
|
+
# Warning: This is a hack. If there is an error with the request such that we never get a response, we have
|
|
274
|
+
# no clean way to persist that information for the Inferno test to check later. The solution here
|
|
275
|
+
# is to persist the request anyway with a status of nil, using the error message as response body
|
|
276
|
+
Faraday::Response.new(response_body: e.message, url: fhir_server_connection.url_prefix.to_s)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def persist_query_request(response, tags)
|
|
280
|
+
inferno_request_headers = data_request_headers.map { |name, value| { name:, value: } }
|
|
281
|
+
inferno_response_headers = response.headers&.map { |name, value| { name:, value: } }
|
|
282
|
+
requests_repo.create(
|
|
283
|
+
verb: 'GET',
|
|
284
|
+
url: response.env.url.to_s,
|
|
285
|
+
direction: 'outgoing',
|
|
286
|
+
status: response.status,
|
|
287
|
+
request_body: response.env.request_body,
|
|
288
|
+
response_body: response.env.response_body,
|
|
289
|
+
test_session_id: test_run.test_session_id,
|
|
290
|
+
result_id: result.id,
|
|
291
|
+
request_headers: inferno_request_headers,
|
|
292
|
+
response_headers: inferno_response_headers,
|
|
293
|
+
tags:
|
|
294
|
+
)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def query_for_coverages
|
|
298
|
+
query = "Coverage?patient=#{request_body.dig('context', 'patientId')}&status=active"
|
|
299
|
+
response = execute_request(query)
|
|
300
|
+
return nil unless response.present?
|
|
301
|
+
|
|
302
|
+
persist_query_request(response, [DATA_FETCH_TAG, hook_instance_data_fetch_tag])
|
|
303
|
+
return nil unless response.status.to_s.starts_with?('2')
|
|
304
|
+
|
|
305
|
+
FHIR.from_contents(response.body)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def analyzed_resources
|
|
309
|
+
@analyzed_resources ||= {}
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def prefetched_resources
|
|
313
|
+
@prefetched_resources ||=
|
|
314
|
+
if request_body['prefetch'].blank? || !request_body['prefetch'].is_a?(Hash)
|
|
315
|
+
{}
|
|
316
|
+
else
|
|
317
|
+
request_body['prefetch'].values.each_with_object({}) do |prefetched_resource, resource_hash|
|
|
318
|
+
next unless prefetched_resource.is_a?(Hash)
|
|
319
|
+
|
|
320
|
+
add_prefetch_resource_to_resource_hash(prefetched_resource, resource_hash)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def add_prefetch_resource_to_resource_hash(prefetched_resource, resource_hash)
|
|
326
|
+
if prefetched_resource['resourceType'] == 'Bundle'
|
|
327
|
+
prefetched_resource['entry']&.each do |entry|
|
|
328
|
+
next unless entry_has_required_details?(entry)
|
|
329
|
+
|
|
330
|
+
one_resource = entry['resource']
|
|
331
|
+
key = "#{one_resource['resourceType']}/#{one_resource['id']}"
|
|
332
|
+
resource_hash[key] = one_resource
|
|
333
|
+
end
|
|
334
|
+
elsif resource_has_required_details?(prefetched_resource)
|
|
335
|
+
|
|
336
|
+
key = "#{prefetched_resource['resourceType']}/#{prefetched_resource['id']}"
|
|
337
|
+
resource_hash[key] = prefetched_resource
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def entry_has_required_details?(entry)
|
|
342
|
+
entry.present? &&
|
|
343
|
+
entry.is_a?(Hash) &&
|
|
344
|
+
entry['resource'].present? &&
|
|
345
|
+
resource_has_required_details?(entry['resource'])
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def resource_has_required_details?(resource)
|
|
349
|
+
resource.is_a?(Hash) && resource['resourceType'].present? && resource['id'].present?
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# gather additional fhir resources not requested via prefetch
|
|
353
|
+
# not used for response generation, but verified later
|
|
354
|
+
def request_additional_fhir_data
|
|
355
|
+
request_coverage_payer
|
|
356
|
+
request_parent_locations
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def prefetched_coverage_resource
|
|
360
|
+
if prefetched_coverage.is_a?(FHIR::Bundle)
|
|
361
|
+
prefetched_coverage.entry.first&.resource
|
|
362
|
+
else
|
|
363
|
+
prefetched_coverage
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def request_coverage_payer
|
|
368
|
+
return unless prefetched_coverage.present?
|
|
369
|
+
|
|
370
|
+
coverage_resource = prefetched_coverage_resource
|
|
371
|
+
return unless coverage_resource.present? && coverage_resource.payor.first&.reference.present?
|
|
372
|
+
|
|
373
|
+
fetch_reference(coverage_resource.payor.first.reference, additional_tag: PAYER_ORG_FETCH_TAG)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def request_parent_locations
|
|
377
|
+
prefetched_locations_and_parents_hash
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def prefetched_location_bundle
|
|
381
|
+
locations_data = request_body.dig('prefetch', 'locations') || request_body.dig('prefetch', 'locs')
|
|
382
|
+
locations = FHIR.from_contents(locations_data.to_json) if locations_data.present?
|
|
383
|
+
return locations if locations.is_a?(FHIR::Bundle)
|
|
384
|
+
return nil unless locations.is_a?(FHIR::Location)
|
|
385
|
+
|
|
386
|
+
FHIR::Bundle.new({ entry: [FHIR::Bundle::Entry.new({ resource: locations })] })
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def prefetched_locations_and_parents_hash
|
|
390
|
+
prefetched_location_bundle&.entry&.each_with_object({}) do |entry, hash|
|
|
391
|
+
add_location_to_hash(entry.resource, hash)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def add_location_to_hash(location, location_hash)
|
|
396
|
+
return unless location.is_a?(FHIR::Location) && location.id.present?
|
|
397
|
+
|
|
398
|
+
relative_reference = "#{location.resourceType}/#{location.id}"
|
|
399
|
+
return if location_hash.key?(relative_reference)
|
|
400
|
+
|
|
401
|
+
location_hash[relative_reference] = location
|
|
402
|
+
return unless location.partOf&.reference.present?
|
|
403
|
+
|
|
404
|
+
parent_location = fetch_reference(location.partOf.reference,
|
|
405
|
+
additional_tag: PARENT_LOCATION_FETCH_TAG,
|
|
406
|
+
parse_as_fhir: true)
|
|
407
|
+
add_location_to_hash(parent_location, location_hash)
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
require_relative 'gather_response_generation_data'
|
|
2
|
+
require_relative 'mock_service_response'
|
|
3
|
+
require_relative 'custom_service_response'
|
|
4
|
+
require_relative '../../cross_suite/cards_identification'
|
|
5
|
+
require_relative '../../cross_suite/tags'
|
|
6
|
+
|
|
7
|
+
module DaVinciCRDTestKit
|
|
8
|
+
class HookRequestEndpoint < Inferno::DSL::SuiteEndpoint
|
|
9
|
+
include DaVinciCRDTestKit::MockServiceResponse
|
|
10
|
+
include DaVinciCRDTestKit::GatherResponseGenerationData
|
|
11
|
+
include DaVinciCRDTestKit::CustomServiceResponse
|
|
12
|
+
include DaVinciCRDTestKit::CardsIdentification
|
|
13
|
+
|
|
14
|
+
AVAILABLE_HOOKS = [
|
|
15
|
+
'appointment-book',
|
|
16
|
+
'encounter-start',
|
|
17
|
+
'encounter-discharge',
|
|
18
|
+
'order-select',
|
|
19
|
+
'order-sign',
|
|
20
|
+
'order-dispatch'
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
def ig_version
|
|
24
|
+
@ig_version ||= requested_version || request.env['PATH_INFO'].match(/(v\d+)/)&.[](1) || 'v201'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# JSON round-trip normalizes the Hanami params object to a plain string-keyed Hash
|
|
28
|
+
def request_body
|
|
29
|
+
@request_body ||= JSON.parse(request.params.to_json)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def requested_version
|
|
33
|
+
requested = request_body.dig('extension', 'davinci-crd.requestedVersion').to_s
|
|
34
|
+
if requested == '2.2'
|
|
35
|
+
'v221'
|
|
36
|
+
elsif requested == '2.0'
|
|
37
|
+
'v201'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_run_identifier
|
|
42
|
+
iss
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def iss
|
|
46
|
+
@iss ||=
|
|
47
|
+
begin
|
|
48
|
+
payload, = JWT.decode(token, nil, false)
|
|
49
|
+
payload['iss']
|
|
50
|
+
rescue JWT::DecodeError
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def token
|
|
56
|
+
@token ||= request.headers['authorization']&.delete_prefix('Bearer ')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# from the hook body
|
|
60
|
+
def requested_hook
|
|
61
|
+
@requested_hook ||= request_body['hook']
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# from the url
|
|
65
|
+
def invoked_hook
|
|
66
|
+
@invoked_hook ||= request.env['PATH_INFO'].match(%r{/([^/]+)-(?:service|subset)$})&.[](1)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# from the waiting test
|
|
70
|
+
def tested_hook
|
|
71
|
+
@tested_hook ||= test.config.options[:hook_name]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def wrong_hook_for_test?
|
|
75
|
+
tested_hook.present? && tested_hook != ANY_HOOK_TAG && requested_hook != tested_hook
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def make_response
|
|
79
|
+
if invoked_hook != requested_hook
|
|
80
|
+
error_response("#{request.env['PATH_INFO']} serves the #{invoked_hook}, but the client " \
|
|
81
|
+
"requested the #{requested_hook} hook.",
|
|
82
|
+
code: 400,
|
|
83
|
+
outcome_code: 'value')
|
|
84
|
+
elsif wrong_hook_for_test?
|
|
85
|
+
error_response("Hook '#{requested_hook}' is not being tested in the current session. " \
|
|
86
|
+
"This session is currently testing the '#{tested_hook}' hook.",
|
|
87
|
+
code: 422,
|
|
88
|
+
outcome_code: 'value')
|
|
89
|
+
elsif hook_instance_already_used?
|
|
90
|
+
error_response(
|
|
91
|
+
"Invalid Request: Hook instance `#{request_body['hookInstance']}` has already been used in this session.",
|
|
92
|
+
outcome_code: 'value'
|
|
93
|
+
)
|
|
94
|
+
elsif AVAILABLE_HOOKS.include?(requested_hook)
|
|
95
|
+
process_valid_hook
|
|
96
|
+
else
|
|
97
|
+
error_response("Invalid Request: hook `#{requested_hook}` is not supported by this server.",
|
|
98
|
+
outcome_code: 'value')
|
|
99
|
+
end
|
|
100
|
+
rescue StandardError => e
|
|
101
|
+
error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}",
|
|
102
|
+
code: 500,
|
|
103
|
+
outcome_code: 'exception')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def process_valid_hook
|
|
107
|
+
if ig_version == 'v201'
|
|
108
|
+
send(:"gather_#{requested_hook.gsub('-', '_')}_data")
|
|
109
|
+
request_coverage
|
|
110
|
+
elsif ig_version == 'v221'
|
|
111
|
+
request_additional_fhir_data
|
|
112
|
+
end
|
|
113
|
+
response_body = apply_hook_configuration(hook_response)
|
|
114
|
+
return unless response_body.present?
|
|
115
|
+
|
|
116
|
+
response.body = response_body.to_json
|
|
117
|
+
response.headers.merge!({ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' })
|
|
118
|
+
response.status = 200
|
|
119
|
+
response.format = :json
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def response_approach
|
|
123
|
+
JSON.parse(result.input_json)
|
|
124
|
+
.find { |input| input['name'].ends_with?('_response_approach') }
|
|
125
|
+
&.dig('value')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def hook_response
|
|
129
|
+
if response_approach == 'custom'
|
|
130
|
+
build_custom_hook_response
|
|
131
|
+
else
|
|
132
|
+
build_mock_hook_response
|
|
133
|
+
end
|
|
134
|
+
rescue StandardError => e
|
|
135
|
+
error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}", code: 500)
|
|
136
|
+
nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def apply_hook_configuration(response_body)
|
|
140
|
+
return response_body unless response_body.present? && coverage_info_disabled?
|
|
141
|
+
|
|
142
|
+
cards = response_body['cards']
|
|
143
|
+
response_body['cards'] = cards.reject { |card| coverage_info_card_type?(card) } if cards.is_a?(Array)
|
|
144
|
+
|
|
145
|
+
system_actions = response_body['systemActions']
|
|
146
|
+
if system_actions.is_a?(Array)
|
|
147
|
+
response_body['systemActions'] = system_actions.reject { |action| coverage_info_system_action_type?(action) }
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
response_body
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def coverage_info_disabled?
|
|
154
|
+
request_body.dig('extension', 'davinci-crd.configuration', COVERAGE_INFO_CONFIGURATION_CODE) == false
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def hook_instance_already_used?
|
|
158
|
+
requests_repo.tagged_requests(test_run.test_session_id, [hook_instance_tag]).present?
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def tags
|
|
162
|
+
return [LONG_RUNNING_GROUP_TAG] if long_running_group?
|
|
163
|
+
return [DUPLICATED_HOOK_INSTANCE_TAG] if hook_instance_already_used?
|
|
164
|
+
|
|
165
|
+
return [] if invoked_hook != requested_hook ||
|
|
166
|
+
wrong_hook_for_test? ||
|
|
167
|
+
!AVAILABLE_HOOKS.include?(requested_hook)
|
|
168
|
+
|
|
169
|
+
[hook_instance_tag, hook_or_group_tag]
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def hook_instance_tag
|
|
173
|
+
TagMethods.hook_instance_tag(request_body['hookInstance'])
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def hook_or_group_tag
|
|
177
|
+
if test.config.options[:crd_test_group].present?
|
|
178
|
+
test.config.options[:crd_test_group]
|
|
179
|
+
else
|
|
180
|
+
DaVinciCRDTestKit.const_get(:"#{name.upcase}_TAG")
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def error_response(error_message, code: 400, outcome_code: 'invalid')
|
|
185
|
+
response.status = code
|
|
186
|
+
response.body = error_operation_outcome(outcome_code, error_message).to_json
|
|
187
|
+
response.headers.merge!({ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' })
|
|
188
|
+
response.format = :json
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def error_operation_outcome(code, text)
|
|
192
|
+
{
|
|
193
|
+
resourceType: 'OperationOutcome',
|
|
194
|
+
issue: [
|
|
195
|
+
{
|
|
196
|
+
severity: 'error',
|
|
197
|
+
code:,
|
|
198
|
+
details: {
|
|
199
|
+
text:
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def name
|
|
207
|
+
requested_hook.gsub('-', '_')
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# -----------------------
|
|
211
|
+
# Long Running Group handling
|
|
212
|
+
# -----------------------
|
|
213
|
+
|
|
214
|
+
def long_running_group?
|
|
215
|
+
test.config.options[:crd_test_group] == LONG_RUNNING_GROUP_TAG
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def long_running_pause_time
|
|
219
|
+
JSON.parse(result.input_json)
|
|
220
|
+
.find { |input| input['name'].include?('long_running_pause_time') }
|
|
221
|
+
&.dig('value').to_i
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# end the wait immediately after the long-running request returns
|
|
225
|
+
# pause here because update_result runs before response generation
|
|
226
|
+
def update_result
|
|
227
|
+
return unless long_running_group?
|
|
228
|
+
|
|
229
|
+
sleep long_running_pause_time
|
|
230
|
+
results_repo.update(result.id, result: 'pass', result_message: '')
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|