davinci_crd_test_kit 0.13.0 → 0.14.1
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 +188 -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 +239 -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}/external_reference.json +1 -1
- data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/launch_smart_app.json +1 -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 +109 -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 +102 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +101 -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 +84 -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 +107 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +108 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +113 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +33 -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 +234 -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 +54 -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 +108 -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 +133 -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 +75 -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 +321 -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 +476 -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 +203 -0
- data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +435 -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 +46 -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/server/jobs/invoke_hook_no_special_requests.rb +17 -0
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_with_bad_auth.rb +14 -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 +183 -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} +3 -3
- 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 +118 -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/discovery/discovery_standard_prefetch_expressions_test.rb +166 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_single_request_test.rb +22 -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 +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +94 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +71 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +107 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +107 -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 +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +115 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +132 -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/specific_coverage_response_group.rb +23 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_info_reason_test.rb +108 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_not_found_group.rb +116 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_active_coverage_group.rb +115 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_member_found_group.rb +117 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_group.rb +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_invoke_test.rb +22 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +31 -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 +40 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +41 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +109 -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/coverage_info_configuration_test.rb +83 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_card_absence_test.rb +76 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +130 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +119 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +89 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +126 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +174 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +83 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +88 -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 +81 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +63 -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 +307 -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}/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,476 @@
|
|
|
1
|
+
require_relative 'fhirpath_on_cds_request'
|
|
2
|
+
require_relative 'replace_tokens'
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module DaVinciCRDTestKit
|
|
6
|
+
# -----------------------------------------------------------------------
|
|
7
|
+
# Prefetch Check Helper Class
|
|
8
|
+
# -----------------------------------------------------------------------
|
|
9
|
+
class PrefetchCompletenessChecker
|
|
10
|
+
include FhirpathOnCDSRequest
|
|
11
|
+
include ReplaceTokens
|
|
12
|
+
|
|
13
|
+
attr_accessor :hook_request, :request_index, :services_file_path,
|
|
14
|
+
:instantiated_prefetch_templates,
|
|
15
|
+
:observed_fhirpath_collection_as_comma_delimited_string
|
|
16
|
+
|
|
17
|
+
def initialize(hook_request, request_index, services_file_path)
|
|
18
|
+
@hook_request = hook_request
|
|
19
|
+
@request_index = request_index
|
|
20
|
+
@services_file_path = services_file_path
|
|
21
|
+
@observed_fhirpath_collection_as_comma_delimited_string = false
|
|
22
|
+
@instantiated_prefetch_templates = {}
|
|
23
|
+
extract_prefetched_resources
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def check_prefetched_data
|
|
27
|
+
return ["#{request_error_prefix} No prefetch data provided."] unless hook_request.key?('prefetch')
|
|
28
|
+
|
|
29
|
+
hook_prefetch_templates.each do |prefetch_key, prefetch_request|
|
|
30
|
+
check_prefetch_template(prefetch_key, prefetch_request)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
hook_request['prefetch'].each_key do |prefetch_template|
|
|
34
|
+
next if hook_prefetch_templates.key?(prefetch_template)
|
|
35
|
+
|
|
36
|
+
errors << "#{request_error_prefix} Extra prefetch data " \
|
|
37
|
+
"provided in unrequested template '#{prefetch_template}'."
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
errors.uniq
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# -----------------------------------------------------------------------
|
|
44
|
+
# Complete vs Subset Prefetch Difference Checking
|
|
45
|
+
# -----------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
def data_set_different_with_alternate_service?(alternate_services_file_path, compare_key_map)
|
|
48
|
+
PrefetchCompletenessChecker.new(hook_request, request_index, alternate_services_file_path)
|
|
49
|
+
.data_sets_different?(self, compare_key_map)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Precondition: the original checker passed without errors meaning the expected set was present
|
|
53
|
+
# handles both subset < complete and complete > subset checks via two checks.
|
|
54
|
+
# - differences in the calculated id set for `_id` searches signal differences in the data sets.
|
|
55
|
+
# - errors during instantiation signal that a resource in the set wasn't present. Since the original
|
|
56
|
+
# set was complete, this will only happen if the original set was a subset and the complete set
|
|
57
|
+
# includes more data, meaning that the sets are different. (NOTE: triggers an error rather than a different
|
|
58
|
+
# set of ids because fhirpath like `...resolve().id` requires the resource be present to evaluate it)
|
|
59
|
+
def data_sets_different?(original_service_checker, compare_key_map)
|
|
60
|
+
template_key_map = compare_key_map.transform_keys { |key| "%#{key}." }.transform_values { |value| "%#{value}." }
|
|
61
|
+
hook_prefetch_templates.each do |prefetch_key, prefetch_request|
|
|
62
|
+
data_set_different = data_set_different?(original_service_checker,
|
|
63
|
+
compare_key_map,
|
|
64
|
+
template_key_map,
|
|
65
|
+
prefetch_key,
|
|
66
|
+
prefetch_request)
|
|
67
|
+
|
|
68
|
+
return true if data_set_different
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def data_set_different?(original_service_checker, compare_key_map, template_key_map, prefetch_key, prefetch_request)
|
|
77
|
+
return false if ['patient', 'pat', 'encounter', 'enc', 'coverage', 'cov'].include?(prefetch_key)
|
|
78
|
+
|
|
79
|
+
mapped_prefetch_request = prefetch_request.gsub(/%[a-zA-Z]+\./, template_key_map)
|
|
80
|
+
instantiated_request = instantiate_template(prefetch_key, mapped_prefetch_request)
|
|
81
|
+
return true if errors.present? # fetch errors - there was more data to include for complete (complete > subset)
|
|
82
|
+
|
|
83
|
+
compare_prefetch_key = compare_key_map.key?(prefetch_key) ? compare_key_map[prefetch_key] : prefetch_key
|
|
84
|
+
original_instantiated_request = original_service_checker.instantiated_prefetch_templates[compare_prefetch_key]
|
|
85
|
+
# don't try to compare when the original didn't have this key
|
|
86
|
+
return false unless original_instantiated_request.present?
|
|
87
|
+
|
|
88
|
+
_, alternate_ids = resource_type_and_ids_from_search(instantiated_request)
|
|
89
|
+
_, original_ids = resource_type_and_ids_from_search(original_instantiated_request)
|
|
90
|
+
|
|
91
|
+
# missing ids - the subset requested strictly less data (subset < complete)
|
|
92
|
+
alternate_ids != original_ids
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# -----------------------------------------------------------------------
|
|
96
|
+
# Errors to return
|
|
97
|
+
# -----------------------------------------------------------------------
|
|
98
|
+
def errors
|
|
99
|
+
@errors ||= []
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def request_error_prefix
|
|
103
|
+
"(Request #{request_index + 1})"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def error_prefix
|
|
107
|
+
"#{request_error_prefix} Prefetch Template #{@current_prefetch_key} -"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# -----------------------------------------------------------------------
|
|
111
|
+
# Requested Prefetch Templates
|
|
112
|
+
# -----------------------------------------------------------------------
|
|
113
|
+
def hook_prefetch_templates
|
|
114
|
+
@hook_prefetch_templates ||=
|
|
115
|
+
JSON.parse(File.read(services_file_path))['services'].find do |service|
|
|
116
|
+
service['hook'] == hook_request['hook']
|
|
117
|
+
end['prefetch']
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# -----------------------------------------------------------------------
|
|
121
|
+
# Instantiated Prefetch Templates
|
|
122
|
+
# -----------------------------------------------------------------------
|
|
123
|
+
def instantiate_template(prefetch_key, prefetch_request)
|
|
124
|
+
instantiated_request = replace_tokens_in_string(prefetch_request.dup, hook_request)
|
|
125
|
+
instantiated_prefetch_templates[prefetch_key] = instantiated_request
|
|
126
|
+
instantiated_request
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# -----------------------------------------------------------------------
|
|
130
|
+
# Check of actual prefetch against an instantiated request
|
|
131
|
+
# -----------------------------------------------------------------------
|
|
132
|
+
def check_prefetch_template(prefetch_key, prefetch_request)
|
|
133
|
+
@current_prefetch_key = prefetch_key
|
|
134
|
+
instantiated_request = instantiate_template(prefetch_key, prefetch_request)
|
|
135
|
+
if demonstrates_collection_as_comma_delimited_string?(prefetch_request, instantiated_request)
|
|
136
|
+
@observed_fhirpath_collection_as_comma_delimited_string = true
|
|
137
|
+
end
|
|
138
|
+
unless hook_request['prefetch'].key?(prefetch_key)
|
|
139
|
+
errors << "#{error_prefix} No prefetch data provided."
|
|
140
|
+
return
|
|
141
|
+
end
|
|
142
|
+
check_provided_against_request(hook_request['prefetch'][prefetch_key], instantiated_request)
|
|
143
|
+
rescue FhirpathServiceError => e
|
|
144
|
+
raise "#{error_prefix} FHIRPath service error while evaluating prefetch template. " \
|
|
145
|
+
"This indicates an implementation problem in Inferno - please log a ticket. Details: #{e.message}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def check_provided_against_request(prefetched_value, instantiated_request)
|
|
149
|
+
if instantiated_request.include?('?')
|
|
150
|
+
if id_search?(instantiated_request)
|
|
151
|
+
check_id_search(prefetched_value, instantiated_request)
|
|
152
|
+
elsif instantiated_request.starts_with?('Coverage')
|
|
153
|
+
check_coverage_search(prefetched_value, instantiated_request)
|
|
154
|
+
else
|
|
155
|
+
raise "#{error_prefix} Unexpected search template '#{instantiated_request}'. " \
|
|
156
|
+
'This indicates an implementation problem in the test kit — please log a ticket.'
|
|
157
|
+
end
|
|
158
|
+
else
|
|
159
|
+
check_read(prefetched_value, instantiated_request)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def id_search?(request_string)
|
|
164
|
+
resource_type = request_string.split('?').first
|
|
165
|
+
request_string.starts_with?("#{resource_type}?_id=")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def check_coverage_search(prefetched_value, _instantiated_request)
|
|
169
|
+
unless prefetched_value.present?
|
|
170
|
+
errors << "#{error_prefix} requested Coverage not provided."
|
|
171
|
+
return
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
check_is_fhir_resource(prefetched_value, target_resource_type: 'Bundle')
|
|
175
|
+
if prefetched_value['resourceType'] == 'Bundle'
|
|
176
|
+
unless prefetched_value['entry']&.size == 1
|
|
177
|
+
errors << "#{error_prefix} exactly one Coverage must be provided."
|
|
178
|
+
return
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
check_coverage(prefetched_value.dig('entry', 0, 'resource'))
|
|
182
|
+
elsif prefetched_value['resourceType'] == 'Coverage'
|
|
183
|
+
check_coverage(prefetched_value)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def check_coverage(prefetched_coverage)
|
|
188
|
+
unless prefetched_coverage['resourceType'].present?
|
|
189
|
+
errors << "#{error_prefix} entry in prefetched Coverage Bundle is not a FHIR resource (no resourceType)."
|
|
190
|
+
return
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
unless prefetched_coverage['resourceType'] == 'Coverage'
|
|
194
|
+
errors << "#{error_prefix} entry in prefetched Coverage Bundle has an unexpected type: " \
|
|
195
|
+
"expected Coverage, got #{prefetched_coverage['resourceType']}."
|
|
196
|
+
return
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
unless prefetched_coverage['status'] == 'active'
|
|
200
|
+
errors << "#{error_prefix} prefetched Coverage has an unexpected status: " \
|
|
201
|
+
"expected active, got #{prefetched_coverage['status']}."
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
check_coverage_beneficiary(prefetched_coverage)
|
|
205
|
+
|
|
206
|
+
nil
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def check_coverage_beneficiary(prefetched_coverage)
|
|
210
|
+
target_patient_id = hook_request.dig('context', 'patientId')
|
|
211
|
+
patient_id = target_patient_id&.delete_prefix('Patient/')
|
|
212
|
+
relative_ref = "Patient/#{patient_id}"
|
|
213
|
+
fhir_server = hook_request['fhirServer']&.chomp('/')
|
|
214
|
+
absolute_ref = "#{fhir_server}/#{relative_ref}" if fhir_server.present?
|
|
215
|
+
|
|
216
|
+
actual_ref = prefetched_coverage.dig('beneficiary', 'reference')
|
|
217
|
+
return if actual_ref == relative_ref || (absolute_ref && actual_ref == absolute_ref)
|
|
218
|
+
|
|
219
|
+
expected_refs = [relative_ref, absolute_ref].compact.join(' or ')
|
|
220
|
+
errors << "#{error_prefix} prefetched Coverage has an unexpected beneficiary reference: " \
|
|
221
|
+
"expected #{expected_refs}, got #{actual_ref}."
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def check_read(prefetched_value, instantiated_request)
|
|
225
|
+
resource_type, resource_id = instantiated_request.split('/')
|
|
226
|
+
|
|
227
|
+
resource_requested = resource_id.present?
|
|
228
|
+
|
|
229
|
+
unless prefetched_value.present?
|
|
230
|
+
if resource_requested
|
|
231
|
+
errors << "#{error_prefix} requested resource '#{full_url_for_target_id(instantiated_request)}' not provided."
|
|
232
|
+
end
|
|
233
|
+
return
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
check_is_fhir_resource(prefetched_value, target_resource_type: resource_type)
|
|
237
|
+
unless prefetched_value.key?('id')
|
|
238
|
+
errors << "#{error_prefix} prefetched #{resource_type} is missing an id."
|
|
239
|
+
return
|
|
240
|
+
end
|
|
241
|
+
unless prefetched_value['id'] == resource_id
|
|
242
|
+
errors << "#{error_prefix} prefetched #{resource_type} has unexpected id: " \
|
|
243
|
+
"expected #{resource_id}, got #{prefetched_value['id']}."
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
nil
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def resource_type_and_ids_from_search(instantiated_search)
|
|
250
|
+
resource_type, id_list = instantiated_search.split('?_id=')
|
|
251
|
+
target_ids = id_list.present? ? id_list.split(',').map { |id| "#{resource_type}/#{id}" }.uniq.sort : []
|
|
252
|
+
|
|
253
|
+
[resource_type, target_ids]
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def check_id_search(prefetched_value, instantiated_request)
|
|
257
|
+
resource_type, target_ids = resource_type_and_ids_from_search(instantiated_request)
|
|
258
|
+
resources_requested = target_ids.present?
|
|
259
|
+
|
|
260
|
+
unless prefetched_value.present?
|
|
261
|
+
if resources_requested
|
|
262
|
+
errors << "#{error_prefix} requested resources not provided: " \
|
|
263
|
+
"#{target_ids.map { |id| full_url_for_target_id(id) }.join(', ')}."
|
|
264
|
+
end
|
|
265
|
+
return
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
check_is_fhir_resource(prefetched_value, target_resource_type: 'Bundle')
|
|
269
|
+
check_bundle_entry_resource_type(prefetched_value, resource_type)
|
|
270
|
+
check_ids(target_ids, actual_ids(prefetched_value))
|
|
271
|
+
nil
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def actual_ids(prefetched_value)
|
|
275
|
+
return [] unless prefetched_value['entry'].present?
|
|
276
|
+
|
|
277
|
+
prefetched_value['entry'].map do |entry|
|
|
278
|
+
type = entry.dig('resource', 'resourceType')
|
|
279
|
+
id = entry.dig('resource', 'id')
|
|
280
|
+
next unless type.present? && id.present?
|
|
281
|
+
|
|
282
|
+
type_and_id = "#{type}/#{id}"
|
|
283
|
+
[type_and_id, entry['fullUrl'].presence || type_and_id]
|
|
284
|
+
end.compact
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def check_ids(target_ids, actual_id_pairs)
|
|
288
|
+
actual_type_ids = actual_id_pairs.map(&:first)
|
|
289
|
+
unless actual_type_ids.size == actual_type_ids.uniq.size
|
|
290
|
+
errors << "#{error_prefix} prefetched Bundle has multiple entries with the same resource id."
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
actual_ids_map = actual_id_pairs.to_h
|
|
294
|
+
|
|
295
|
+
missing_ids = target_ids - actual_type_ids
|
|
296
|
+
if missing_ids.present?
|
|
297
|
+
errors << "#{error_prefix} prefetched Bundle missing expected entries: " \
|
|
298
|
+
"#{missing_ids.map { |id| full_url_for_target_id(id) }.join('\', \'')}."
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
extra_ids = actual_type_ids - target_ids
|
|
302
|
+
return unless extra_ids.present?
|
|
303
|
+
|
|
304
|
+
errors << "#{error_prefix} prefetched Bundle includes unrequested entries: " \
|
|
305
|
+
"#{extra_ids.map { |id| actual_ids_map[id] }.join('\', \'')}."
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# NOTE: would possibly fail in the case of duplicate <resource>/<id> with different
|
|
309
|
+
# base urls but this will cause other problems since in the _id search form those
|
|
310
|
+
# would be the same. So not worth trying to work around it.
|
|
311
|
+
def full_url_for_target_id(type_and_id)
|
|
312
|
+
prefetched_resources.keys.find { |url| url.end_with?("/#{type_and_id}") } ||
|
|
313
|
+
fhir_server_url_for(type_and_id)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def fhir_server_url_for(type_and_id)
|
|
317
|
+
return type_and_id unless hook_request['fhirServer'].present?
|
|
318
|
+
|
|
319
|
+
"#{hook_request['fhirServer'].chomp('/')}/#{type_and_id}"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def check_bundle_entry_resource_type(bundle, target_resource_type)
|
|
323
|
+
bundle['entry']&.each_with_index do |entry, index|
|
|
324
|
+
entry_resource_type = entry.dig('resource', 'resourceType')
|
|
325
|
+
next if entry_resource_type == target_resource_type
|
|
326
|
+
|
|
327
|
+
errors << if entry_resource_type.present?
|
|
328
|
+
"#{error_prefix} prefetched Bundle entry #{index + 1} has an unexpected resourceType: " \
|
|
329
|
+
"expected #{target_resource_type}, got #{entry_resource_type}."
|
|
330
|
+
else
|
|
331
|
+
"#{error_prefix} prefetched Bundle entry #{index + 1} is not a FHIR resource (no resourceType)."
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def check_is_fhir_resource(prefetched_value, target_resource_type: nil)
|
|
337
|
+
unless prefetched_value.key?('resourceType')
|
|
338
|
+
errors << "#{error_prefix} prefetched value is not a FHIR resource (no resourceType)."
|
|
339
|
+
return
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
return if target_resource_type.blank? || prefetched_value['resourceType'] == target_resource_type
|
|
343
|
+
|
|
344
|
+
errors << "#{error_prefix} prefetched value has unexpected resourceType: " \
|
|
345
|
+
"expected #{target_resource_type}, got #{prefetched_value['resourceType']}."
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# -----------------------------------------------------------------------
|
|
349
|
+
# Map of prefetched resources by fullUrl
|
|
350
|
+
# -----------------------------------------------------------------------
|
|
351
|
+
def prefetched_resources
|
|
352
|
+
@prefetched_resources ||= {}
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def extract_prefetched_resources
|
|
356
|
+
hook_request['prefetch']&.each_value do |prefetch_resource|
|
|
357
|
+
next unless prefetch_resource&.dig('resourceType').present?
|
|
358
|
+
|
|
359
|
+
if prefetch_resource['resourceType'] == 'Bundle'
|
|
360
|
+
extract_resources_from_prefetched_bundle(prefetch_resource)
|
|
361
|
+
else
|
|
362
|
+
extract_prefetched_resource_instance(prefetch_resource)
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def extract_resources_from_prefetched_bundle(bundle)
|
|
368
|
+
bundle['entry']&.each do |entry|
|
|
369
|
+
next unless entry['resource'].present?
|
|
370
|
+
|
|
371
|
+
if entry['fullUrl'].present?
|
|
372
|
+
prefetched_resources[entry['fullUrl']] = entry['resource'] unless prefetched_resources.key?(entry['fullUrl'])
|
|
373
|
+
else
|
|
374
|
+
extract_prefetched_resource_instance(entry['resource'])
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# no fullUrl available, so assume that it is a restful FHIR url
|
|
380
|
+
# relative to the fhirServer of the hook request
|
|
381
|
+
def extract_prefetched_resource_instance(resource_instance)
|
|
382
|
+
return unless resource_instance['id'].present? &&
|
|
383
|
+
resource_instance['resourceType'].present? &&
|
|
384
|
+
hook_request['fhirServer'].present?
|
|
385
|
+
|
|
386
|
+
fhir_server =
|
|
387
|
+
if hook_request['fhirServer'].ends_with?('/')
|
|
388
|
+
hook_request['fhirServer']
|
|
389
|
+
else
|
|
390
|
+
"#{hook_request['fhirServer']}/"
|
|
391
|
+
end
|
|
392
|
+
key = "#{fhir_server}#{resource_instance['resourceType']}/#{resource_instance['id']}"
|
|
393
|
+
return if prefetched_resources.key?(key)
|
|
394
|
+
|
|
395
|
+
prefetched_resources[key] = resource_instance
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
# -------------------------------------------------------------------------
|
|
399
|
+
# fhirpath resolve() handling
|
|
400
|
+
# -------------------------------------------------------------------------
|
|
401
|
+
|
|
402
|
+
def resolve(reference)
|
|
403
|
+
return nil unless reference.present?
|
|
404
|
+
|
|
405
|
+
key = absolute_reference(reference)
|
|
406
|
+
return nil unless key.present?
|
|
407
|
+
|
|
408
|
+
unless prefetched_resources[key].present?
|
|
409
|
+
errors << "#{error_prefix} resource '#{key}' needed to instantiate the query " \
|
|
410
|
+
'was not provided in the prefetched values.'
|
|
411
|
+
|
|
412
|
+
return nil
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
@current_base_fhir_server = base_fhir_server_for_identity(key)
|
|
416
|
+
prefetched_resources[key]
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def absolute_reference(reference)
|
|
420
|
+
reference = reference['reference'] if reference.is_a?(Hash)
|
|
421
|
+
return nil unless reference.present?
|
|
422
|
+
|
|
423
|
+
if URI.parse(reference).absolute?
|
|
424
|
+
reference
|
|
425
|
+
else
|
|
426
|
+
relative_to_absolute_reference(reference)
|
|
427
|
+
end
|
|
428
|
+
rescue URI::InvalidURIError => e
|
|
429
|
+
errors << "#{error_prefix} '#{reference}' needed to instantiate the query " \
|
|
430
|
+
"is invalid: #{e.message}."
|
|
431
|
+
nil
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def relative_to_absolute_reference(relative_reference)
|
|
435
|
+
return nil unless relative_reference_valid?(relative_reference)
|
|
436
|
+
|
|
437
|
+
if @current_base_fhir_server.nil?
|
|
438
|
+
errors << "#{error_prefix} '#{relative_reference}' needed to instantiate the query " \
|
|
439
|
+
'is a relative reference, but the base FHIR Server is not known.'
|
|
440
|
+
return nil
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
"#{@current_base_fhir_server}/#{relative_reference}"
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def relative_reference_valid?(relative_reference)
|
|
447
|
+
if relative_reference.split('/').length > 2
|
|
448
|
+
errors << "#{error_prefix} '#{relative_reference}' needed to instantiate the query " \
|
|
449
|
+
'is not an absolute reference but has too many segments to be a relative reference.'
|
|
450
|
+
return false
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
resource_type, id = relative_reference.split('/')
|
|
454
|
+
if resource_type.blank? || id.blank?
|
|
455
|
+
errors << "#{error_prefix} '#{relative_reference}' needed to instantiate the query " \
|
|
456
|
+
'is not a valid relative reference of the form <resource type>/<id>.'
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
true
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# -------------------------------------------------------------------------
|
|
463
|
+
# Observe a Collection represented as a comma-delimited string in instantiated search
|
|
464
|
+
# -------------------------------------------------------------------------
|
|
465
|
+
|
|
466
|
+
# client will have demonstrated turning a collection into a comma-delimited string if both
|
|
467
|
+
# - the prefetch request follows the RESOURCE?_id={{TOKEN}} form when TOKEN has a | indicating 'and', and
|
|
468
|
+
# - the instantiated query actually has multiple unique ids
|
|
469
|
+
def demonstrates_collection_as_comma_delimited_string?(prefetch_request, instantiated_request)
|
|
470
|
+
token = prefetch_request.match(/[a-zA-Z]*\?_id=\{\{(.+?)\}\}/)&.[](1)
|
|
471
|
+
return false unless token.present? && token.include?('|')
|
|
472
|
+
|
|
473
|
+
instantiated_request.split('?_id=').last.split(',').uniq.size > 1
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require_relative 'replace_tokens'
|
|
2
|
+
require_relative 'fhirpath_on_cds_request'
|
|
3
|
+
|
|
4
|
+
module DaVinciCRDTestKit
|
|
5
|
+
module PrefetchContentsValidation
|
|
6
|
+
include ReplaceTokens
|
|
7
|
+
include FhirpathOnCDSRequest
|
|
8
|
+
|
|
9
|
+
def request_number
|
|
10
|
+
if @request_number.blank?
|
|
11
|
+
''
|
|
12
|
+
else
|
|
13
|
+
"Request #{@request_number}: "
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def prefetched_data?(requests)
|
|
18
|
+
requests.any? do |request|
|
|
19
|
+
JSON.parse(request.request_body)['prefetch']&.keys.present?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def check_prefetch_data_against_query(hook_request, advertized_prefetch_queries)
|
|
24
|
+
request_body = JSON.parse(hook_request.request_body)
|
|
25
|
+
request_body['prefetch']&.each do |key, value|
|
|
26
|
+
next unless advertized_prefetch_queries[key].present?
|
|
27
|
+
|
|
28
|
+
instantiated_query = replace_tokens_in_string(advertized_prefetch_queries[key], request_body)
|
|
29
|
+
|
|
30
|
+
queried_resource_list = query_for_data(instantiated_query)
|
|
31
|
+
prefetched_resource_list = prefetched_data_to_resource_list(value)
|
|
32
|
+
|
|
33
|
+
next if prefetched_data_equals_queried_data?(prefetched_resource_list, queried_resource_list)
|
|
34
|
+
|
|
35
|
+
add_message('error', "#{request_number}Prefetched data `#{key}` was different than " \
|
|
36
|
+
"data returned from requested query `#{instantiated_query}`.")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def query_for_data(prefetch_query)
|
|
41
|
+
is_search = prefetch_query.include?('?')
|
|
42
|
+
|
|
43
|
+
split_query = is_search ? prefetch_query.split('?') : prefetch_query.split('/')
|
|
44
|
+
resource_type = split_query.first
|
|
45
|
+
|
|
46
|
+
query_result =
|
|
47
|
+
if is_search
|
|
48
|
+
fhir_search(resource_type, params: Rack::Utils.parse_nested_query(split_query.last))
|
|
49
|
+
else
|
|
50
|
+
fhir_read(resource_type, split_query.last)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
return [] unless query_result.status.to_s.starts_with?('2')
|
|
54
|
+
return [] unless query_result.resource.present?
|
|
55
|
+
|
|
56
|
+
if is_search
|
|
57
|
+
fetch_all_bundled_resources(resource_type:, bundle: query_result.resource)
|
|
58
|
+
else
|
|
59
|
+
[query_result.resource]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def prefetched_data_equals_queried_data?(prefetched_data, queried_data)
|
|
64
|
+
prefetched_id_list = prefetched_data.map { |resource| "#{resource.resourceType}/#{resource.id}" }.sort
|
|
65
|
+
queried_id_list = queried_data.map { |resource| "#{resource.resourceType}/#{resource.id}" }.sort
|
|
66
|
+
|
|
67
|
+
prefetched_id_list == queried_id_list
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def prefetched_data_to_resource_list(prefetched_data)
|
|
71
|
+
return [] unless prefetched_data.present?
|
|
72
|
+
|
|
73
|
+
fhir_data = FHIR.from_contents(prefetched_data.to_json)
|
|
74
|
+
if fhir_data.is_a?(FHIR::Bundle)
|
|
75
|
+
fhir_data.entry.map(&:resource)
|
|
76
|
+
else
|
|
77
|
+
[fhir_data]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require_relative 'hook_request_field_validation'
|
|
2
|
+
|
|
3
|
+
module DaVinciCRDTestKit
|
|
4
|
+
module PrefetchProfileValidation
|
|
5
|
+
include HookRequestFieldValidation
|
|
6
|
+
|
|
7
|
+
def check_prefetch_profiles(prefetch, request_index)
|
|
8
|
+
prefetch.each do |key, prefetched_resource|
|
|
9
|
+
next unless prefetched_resource.present? # prefetch must be null if no data matches the template
|
|
10
|
+
|
|
11
|
+
@prefetch_template = key
|
|
12
|
+
check_resource_profile(prefetched_resource, request_index, nil)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def check_resource_profile(prefetched_resource, request_index, bundle_entry_index)
|
|
19
|
+
if prefetched_resource['resourceType'] == 'Bundle'
|
|
20
|
+
prefetched_resource['entry']&.each_with_index do |entry, entry_index|
|
|
21
|
+
check_resource_profile(entry['resource'], request_index, entry_index) if entry['resource'].present?
|
|
22
|
+
end
|
|
23
|
+
elsif prefetched_resource['resourceType'].present?
|
|
24
|
+
check_non_bundle_resource_profile(prefetched_resource, request_index, bundle_entry_index)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def check_non_bundle_resource_profile(prefetched_resource, request_index, bundle_entry_index)
|
|
29
|
+
target_crd_profile = structure_definition_map('v221')[prefetched_resource['resourceType']]
|
|
30
|
+
return unless target_crd_profile.present?
|
|
31
|
+
|
|
32
|
+
validation_details = []
|
|
33
|
+
resource_is_valid?(resource: FHIR.from_contents(prefetched_resource.to_json),
|
|
34
|
+
profile_url: target_crd_profile,
|
|
35
|
+
validator_response_details: validation_details, add_messages_to_runnable: false)
|
|
36
|
+
validation_details.each do |issue|
|
|
37
|
+
prefix = prefetch_profile_error_prefix(request_index, bundle_entry_index)
|
|
38
|
+
add_message(issue.severity, "#{prefix}#{issue.message}")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def prefetch_profile_error_prefix(request_index, bundle_entry_index)
|
|
43
|
+
prefix = "(Request #{request_index + 1}) Prefetch Template '#{@prefetch_template}'"
|
|
44
|
+
prefix = "#{prefix} Bundle entry #{bundle_entry_index + 1}" if bundle_entry_index.present?
|
|
45
|
+
"#{prefix} validation issue - "
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module DaVinciCRDTestKit
|
|
2
|
+
module ProfilesAndResourceTypes
|
|
3
|
+
ORDER_RESOURCE_CLASSES = [
|
|
4
|
+
FHIR::CommunicationRequest, FHIR::DeviceRequest, FHIR::MedicationRequest,
|
|
5
|
+
FHIR::NutritionOrder, FHIR::ServiceRequest, FHIR::VisionPrescription
|
|
6
|
+
].freeze
|
|
7
|
+
ORDER_OR_ENCOUNTER_RESOURCE_CLASSES = (ORDER_RESOURCE_CLASSES + [FHIR::Encounter]).freeze
|
|
8
|
+
ORDER_RESOURCE_TYPES = ORDER_RESOURCE_CLASSES.map { |c| c.name.split('::').last }.freeze
|
|
9
|
+
|
|
10
|
+
def structure_definition_map(ig_version)
|
|
11
|
+
case ig_version
|
|
12
|
+
when 'v221', '2.2.1'
|
|
13
|
+
structure_definition_map_v221
|
|
14
|
+
when 'v201', '2.0.1'
|
|
15
|
+
structure_definition_map_v201
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def structure_definition_map_v201
|
|
20
|
+
{
|
|
21
|
+
'Practitioner' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-practitioner|2.0.1',
|
|
22
|
+
'PractitionerRole' => 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitionerrole|3.1.1',
|
|
23
|
+
'Patient' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-patient|2.0.1',
|
|
24
|
+
'Encounter' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-encounter|2.0.1',
|
|
25
|
+
'Appointment' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-appointment|2.0.1',
|
|
26
|
+
'DeviceRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-devicerequest|2.0.1',
|
|
27
|
+
'MedicationRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-medicationrequest|2.0.1',
|
|
28
|
+
'NutritionOrder' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-nutritionorder|2.0.1',
|
|
29
|
+
'ServiceRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-servicerequest|2.0.1',
|
|
30
|
+
'VisionPrescription' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-visionprescription|2.0.1',
|
|
31
|
+
'Medication' => 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-medication|3.1.1',
|
|
32
|
+
'Device' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-device|2.0.1',
|
|
33
|
+
'CommunicationRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-communicationrequest|2.0.1',
|
|
34
|
+
'Task' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-taskquestionnaire|2.0.1',
|
|
35
|
+
'Coverage' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-coverage|2.0.1',
|
|
36
|
+
'Location' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-location|2.0.1',
|
|
37
|
+
'Organization' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-organization|2.0.1'
|
|
38
|
+
}.freeze
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def structure_definition_map_v221
|
|
42
|
+
{
|
|
43
|
+
'Practitioner' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-practitioner|2.2.1',
|
|
44
|
+
'PractitionerRole' => 'http://hl7.org/fhir/us/davinci-hrex/StructureDefinition/hrex-practitionerrole|1.2.0',
|
|
45
|
+
'Patient' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-patient|2.2.1',
|
|
46
|
+
'Encounter' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-encounter|2.2.1',
|
|
47
|
+
'Appointment' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-appointment-no-order|2.2.1',
|
|
48
|
+
'DeviceRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-devicerequest|2.2.1',
|
|
49
|
+
'MedicationRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-medicationrequest|2.2.1',
|
|
50
|
+
'NutritionOrder' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-nutritionorder|2.2.1',
|
|
51
|
+
'ServiceRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-servicerequest|2.2.1',
|
|
52
|
+
'VisionPrescription' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-visionprescription|2.2.1',
|
|
53
|
+
'Medication' => 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-medication|3.1.1',
|
|
54
|
+
'Device' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-device|2.2.1',
|
|
55
|
+
'CommunicationRequest' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-communicationrequest|2.2.1',
|
|
56
|
+
'Task' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-taskquestionnaire|2.2.1',
|
|
57
|
+
'Coverage' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-coverage|2.2.1',
|
|
58
|
+
'Location' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-location|2.2.1',
|
|
59
|
+
'Organization' => 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-organization|2.2.1'
|
|
60
|
+
}.freeze
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|