davinci_crd_test_kit 0.12.2 → 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.
Files changed (341) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/inferno_crd_client_suite.json.erb +20 -14
  3. data/config/presets/inferno_crd_client_suite_prefetch_subset_v221.json.erb +125 -0
  4. data/config/presets/inferno_crd_client_suite_v221.json.erb +124 -0
  5. data/config/presets/inferno_crd_server_suite.json.erb +59 -2
  6. data/config/presets/inferno_crd_server_suite_v221.json.erb +94 -0
  7. data/config/presets/ri_crd_request_generator.json_v221.json.erb +13 -0
  8. data/config/presets/ri_crd_server.json.erb +19 -19
  9. data/lib/davinci_crd_test_kit/client/client_base_urls.rb +80 -0
  10. data/lib/davinci_crd_test_kit/{client_hook_request_validation.rb → client/client_hook_request_validation.rb} +1 -1
  11. data/lib/davinci_crd_test_kit/client/crd_client_options.rb +30 -0
  12. data/lib/davinci_crd_test_kit/client/endpoints/cds_services_discovery_handler.rb +34 -0
  13. data/lib/davinci_crd_test_kit/client/endpoints/custom_service_response.rb +342 -0
  14. data/lib/davinci_crd_test_kit/client/endpoints/gather_response_generation_data.rb +410 -0
  15. data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +233 -0
  16. data/lib/davinci_crd_test_kit/{mock_service_response.rb → client/endpoints/mock_service_response.rb} +165 -59
  17. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/companions_prerequisites.json +1 -0
  18. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/create_update_coverage_information.json +3 -2
  19. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/launch_smart_app.json +8 -1
  20. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/propose_alternate_request.json +1 -0
  21. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/request_form_completion.json +17 -16
  22. data/lib/davinci_crd_test_kit/client/multi_request_message_helper.rb +35 -0
  23. data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +38 -0
  24. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_create_test.rb +43 -0
  25. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_read_test.rb +43 -0
  26. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_search_test.rb +234 -0
  27. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_update_test.rb +43 -0
  28. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_validation_test.rb +63 -0
  29. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/decode_auth_token_test.rb +65 -0
  30. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +109 -0
  31. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_header_test.rb +70 -0
  32. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +85 -0
  33. data/lib/davinci_crd_test_kit/{routes/cds-services.json → client/v2.0.1/cds-services-v201.json} +1 -1
  34. data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +108 -0
  35. data/lib/davinci_crd_test_kit/client/v2.0.1/client_card_must_support_group.rb +31 -0
  36. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +105 -0
  37. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +105 -0
  38. data/lib/davinci_crd_test_kit/client/v2.0.1/client_fhir_api_group.rb +790 -0
  39. data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +74 -0
  40. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +111 -0
  41. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +116 -0
  42. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +113 -0
  43. data/lib/davinci_crd_test_kit/{client_registration_group.rb → client/v2.0.1/client_registration_group.rb} +12 -8
  44. data/lib/davinci_crd_test_kit/client/v2.0.1/client_urls.rb +13 -0
  45. data/lib/davinci_crd_test_kit/client/v2.0.1/crd_client_suite.rb +134 -0
  46. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/appointment_book_receive_request_test.rb +129 -0
  47. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_discharge_receive_request_test.rb +126 -0
  48. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_start_receive_request_test.rb +126 -0
  49. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_dispatch_receive_request_test.rb +138 -0
  50. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_select_receive_request_test.rb +134 -0
  51. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_sign_receive_request_test.rb +136 -0
  52. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +93 -0
  53. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +62 -0
  54. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +62 -0
  55. data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_registration_verification_test.rb +94 -0
  56. data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_service_registration_attestation_test.rb +40 -0
  57. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +86 -0
  58. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_optional_fields_test.rb +63 -0
  59. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +96 -0
  60. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_required_fields_test.rb +55 -0
  61. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_context_test.rb +70 -0
  62. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_prefetch_test.rb +62 -0
  63. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +83 -0
  64. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +79 -0
  65. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +212 -0
  66. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_crd_update_verification_group.rb +18 -0
  67. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +69 -0
  68. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +120 -0
  69. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_header_test.rb +92 -0
  70. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +93 -0
  71. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +198 -0
  72. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +202 -0
  73. data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +102 -0
  74. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +28 -0
  75. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +96 -0
  76. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +95 -0
  77. data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +88 -0
  78. data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +64 -0
  79. data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +32 -0
  80. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +101 -0
  81. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +102 -0
  82. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +107 -0
  83. data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +27 -0
  84. data/lib/davinci_crd_test_kit/client/v2.2.1/client_urls.rb +27 -0
  85. data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +229 -0
  86. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +63 -0
  87. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +60 -0
  88. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +45 -0
  89. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +135 -0
  90. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +103 -0
  91. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +156 -0
  92. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +157 -0
  93. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +157 -0
  94. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +165 -0
  95. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +165 -0
  96. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +165 -0
  97. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +64 -0
  98. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +49 -0
  99. data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_registration_verification_test.rb +161 -0
  100. data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +107 -0
  101. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +47 -0
  102. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +152 -0
  103. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +55 -0
  104. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +123 -0
  105. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +127 -0
  106. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +55 -0
  107. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +54 -0
  108. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +48 -0
  109. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +74 -0
  110. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +30 -0
  111. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +77 -0
  112. data/lib/davinci_crd_test_kit/cross_suite/base_urls.rb +20 -0
  113. data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +312 -0
  114. data/lib/davinci_crd_test_kit/{cards_validation.rb → cross_suite/cards_validation.rb} +104 -47
  115. data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu201_metadata.yml +27 -0
  116. data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu221_metadata.yml +60 -0
  117. data/lib/davinci_crd_test_kit/cross_suite/fhirpath_on_cds_request.rb +177 -0
  118. data/lib/davinci_crd_test_kit/{hook_request_field_validation.rb → cross_suite/hook_request_field_validation.rb} +282 -203
  119. data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +220 -0
  120. data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +462 -0
  121. data/lib/davinci_crd_test_kit/cross_suite/prefetch_contents_validation.rb +81 -0
  122. data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +48 -0
  123. data/lib/davinci_crd_test_kit/cross_suite/profiles_and_resource_types.rb +63 -0
  124. data/lib/davinci_crd_test_kit/cross_suite/replace_tokens.rb +38 -0
  125. data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +202 -0
  126. data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +274 -0
  127. data/lib/davinci_crd_test_kit/{suggestion_actions_validation.rb → cross_suite/suggestion_actions_validation.rb} +70 -50
  128. data/lib/davinci_crd_test_kit/cross_suite/tags.rb +42 -0
  129. data/lib/davinci_crd_test_kit/metadata.rb +10 -44
  130. data/lib/davinci_crd_test_kit/requirements/cds-hooks-library_1.0.1_requirements.xlsx +0 -0
  131. data/lib/davinci_crd_test_kit/requirements/cds-hooks_2.0_requirements.xlsx +0 -0
  132. data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
  133. data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +742 -65
  134. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +279 -54
  135. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +1430 -0
  136. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +36 -45
  137. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +143 -0
  138. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.0.1_requirements.xlsx +0 -0
  139. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
  140. data/lib/davinci_crd_test_kit/server/endpoints/jwk_set_endpoint_handler.rb +13 -0
  141. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_create_endpoint.rb +23 -0
  142. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_delete_endpoint.rb +30 -0
  143. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_metadata_endpoint.rb +112 -0
  144. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_read_endpoint.rb +21 -0
  145. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_request_handler.rb +261 -0
  146. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_search_endpoint.rb +561 -0
  147. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_update_endpoint.rb +24 -0
  148. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/stress-test-Bundle.json +54687 -0
  149. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr_endpoints.rb +95 -0
  150. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +225 -0
  151. data/lib/davinci_crd_test_kit/{jwt_helper.rb → server/jwt_helper.rb} +1 -12
  152. data/lib/davinci_crd_test_kit/server/resource_extractor.rb +68 -0
  153. data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +165 -0
  154. data/lib/davinci_crd_test_kit/server/server_base_urls.rb +30 -0
  155. data/lib/davinci_crd_test_kit/{server_hook_helper.rb → server/server_hook_helper.rb} +1 -1
  156. data/lib/davinci_crd_test_kit/{server_hook_request_validation.rb → server/server_hook_request_validation.rb} +1 -1
  157. data/lib/davinci_crd_test_kit/{test_helper.rb → server/server_test_helper.rb} +7 -3
  158. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Appointment.yml +5 -0
  159. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ClaimResponse.yml +5 -0
  160. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/CommunicationRequest.yml +5 -0
  161. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Coverage.yml +21 -0
  162. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Device.yml +5 -0
  163. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/DeviceRequest.yml +5 -0
  164. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Encounter.yml +7 -0
  165. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Location.yml +5 -0
  166. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/MedicationRequest.yml +5 -0
  167. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/NutritionOrder.yml +5 -0
  168. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Organization.yml +5 -0
  169. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Patient.yml +5 -0
  170. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Practitioner.yml +5 -0
  171. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/PractitionerRole.yml +40 -0
  172. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ServiceRequest.yml +5 -0
  173. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Task.yml +5 -0
  174. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/VisionPrescription.yml +5 -0
  175. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +99 -0
  176. data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_endpoint_test.rb +90 -0
  177. data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_services_validation_test.rb +67 -0
  178. data/lib/davinci_crd_test_kit/server/v2.0.1/interaction/server_invoke_hook_test.rb +12 -0
  179. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +34 -0
  180. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/external_reference_card_across_hooks_validation_test.rb +30 -0
  181. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/instructions_card_received_across_hooks_test.rb +27 -0
  182. data/lib/davinci_crd_test_kit/server/v2.0.1/server_appointment_book_group.rb +191 -0
  183. data/lib/davinci_crd_test_kit/server/v2.0.1/server_demonstrate_hook_response_group.rb +93 -0
  184. data/lib/davinci_crd_test_kit/server/v2.0.1/server_discovery_group.rb +62 -0
  185. data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_discharge_group.rb +186 -0
  186. data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_start_group.rb +186 -0
  187. data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +73 -0
  188. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_dispatch_group.rb +191 -0
  189. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_select_group.rb +211 -0
  190. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_sign_group.rb +216 -0
  191. data/lib/davinci_crd_test_kit/server/v2.0.1/server_required_card_response_validation_group.rb +28 -0
  192. data/lib/davinci_crd_test_kit/server/v2.0.1/server_urls.rb +13 -0
  193. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_context_validation_test.rb +30 -0
  194. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_optional_fields_validation_test.rb +39 -0
  195. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_required_fields_validation_test.rb +40 -0
  196. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/additional_orders_validation_test.rb +59 -0
  197. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/card_optional_fields_validation_test.rb +51 -0
  198. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_received_test.rb +65 -0
  199. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_validation_test.rb +120 -0
  200. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +70 -0
  201. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/external_reference_card_validation_test.rb +37 -0
  202. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/form_completion_response_validation_test.rb +67 -0
  203. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/instructions_card_received_test.rb +30 -0
  204. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/launch_smart_app_card_validation_test.rb +39 -0
  205. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/propose_alternate_request_card_validation_test.rb +46 -0
  206. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/service_response_validation_test.rb +83 -0
  207. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withorder.yml +5 -0
  208. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withoutorder.yml +5 -0
  209. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/CommunicationRequest.yml +5 -0
  210. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Coverage.yml +5 -0
  211. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Device.yml +5 -0
  212. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/DeviceRequest.yml +5 -0
  213. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Encounter.yml +5 -0
  214. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Location.yml +5 -0
  215. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/MedicationRequest.yml +5 -0
  216. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/NutritionOrder.yml +5 -0
  217. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Organization.yml +5 -0
  218. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Patient.yml +5 -0
  219. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/PractitionerRole.yml +5 -0
  220. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/ServiceRequest.yml +5 -0
  221. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/VisionPrescription.yml +5 -0
  222. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +115 -0
  223. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_configuration_test.rb +159 -0
  224. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_endpoint_test.rb +90 -0
  225. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_prefetch_support_test.rb +43 -0
  226. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_services_validation_test.rb +121 -0
  227. data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_test.rb +17 -0
  228. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_must_support_test.rb +71 -0
  229. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +36 -0
  230. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/supported_us_core_versions_test.rb +118 -0
  231. data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +213 -0
  232. data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +93 -0
  233. data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +69 -0
  234. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +194 -0
  235. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +194 -0
  236. data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +73 -0
  237. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +214 -0
  238. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +219 -0
  239. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +241 -0
  240. data/lib/davinci_crd_test_kit/server/v2.2.1/server_required_card_response_validation_group.rb +30 -0
  241. data/lib/davinci_crd_test_kit/server/v2.2.1/server_urls.rb +13 -0
  242. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +30 -0
  243. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_no_custom_extensions_test.rb +120 -0
  244. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +39 -0
  245. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +40 -0
  246. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +66 -0
  247. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/all_responses_include_coverage_information_test.rb +123 -0
  248. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/card_optional_fields_validation_test.rb +57 -0
  249. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_info_configuration_test.rb +83 -0
  250. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_received_test.rb +65 -0
  251. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +184 -0
  252. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +75 -0
  253. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +47 -0
  254. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +91 -0
  255. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +137 -0
  256. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +32 -0
  257. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +49 -0
  258. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/order_dispatch_coverage_information_test.rb +38 -0
  259. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +54 -0
  260. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +97 -0
  261. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +78 -0
  262. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +78 -0
  263. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +78 -0
  264. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_billing_options_test.rb +43 -0
  265. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_configuration_test.rb +44 -0
  266. data/lib/davinci_crd_test_kit/version.rb +2 -2
  267. data/lib/davinci_crd_test_kit.rb +4 -2
  268. metadata +308 -101
  269. data/lib/davinci_crd_test_kit/client_fhir_api_group.rb +0 -785
  270. data/lib/davinci_crd_test_kit/client_hooks_group.rb +0 -75
  271. data/lib/davinci_crd_test_kit/client_tests/appointment_book_receive_request_test.rb +0 -93
  272. data/lib/davinci_crd_test_kit/client_tests/client_appointment_book_group.rb +0 -75
  273. data/lib/davinci_crd_test_kit/client_tests/client_display_cards_attest.rb +0 -48
  274. data/lib/davinci_crd_test_kit/client_tests/client_encounter_discharge_group.rb +0 -73
  275. data/lib/davinci_crd_test_kit/client_tests/client_encounter_start_group.rb +0 -73
  276. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_create_test.rb +0 -41
  277. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_read_test.rb +0 -39
  278. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_search_test.rb +0 -232
  279. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_update_test.rb +0 -41
  280. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_validation_test.rb +0 -60
  281. data/lib/davinci_crd_test_kit/client_tests/client_order_dispatch_group.rb +0 -79
  282. data/lib/davinci_crd_test_kit/client_tests/client_order_select_group.rb +0 -82
  283. data/lib/davinci_crd_test_kit/client_tests/client_order_sign_group.rb +0 -81
  284. data/lib/davinci_crd_test_kit/client_tests/client_registration_verification_test.rb +0 -88
  285. data/lib/davinci_crd_test_kit/client_tests/decode_auth_token_test.rb +0 -60
  286. data/lib/davinci_crd_test_kit/client_tests/encounter_discharge_receive_request_test.rb +0 -90
  287. data/lib/davinci_crd_test_kit/client_tests/encounter_start_receive_request_test.rb +0 -90
  288. data/lib/davinci_crd_test_kit/client_tests/hook_request_optional_fields_test.rb +0 -57
  289. data/lib/davinci_crd_test_kit/client_tests/hook_request_required_fields_test.rb +0 -49
  290. data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_context_test.rb +0 -68
  291. data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_prefetch_test.rb +0 -69
  292. data/lib/davinci_crd_test_kit/client_tests/order_dispatch_receive_request_test.rb +0 -102
  293. data/lib/davinci_crd_test_kit/client_tests/order_select_receive_request_test.rb +0 -98
  294. data/lib/davinci_crd_test_kit/client_tests/order_sign_receive_request_test.rb +0 -101
  295. data/lib/davinci_crd_test_kit/client_tests/retrieve_jwks_test.rb +0 -105
  296. data/lib/davinci_crd_test_kit/client_tests/submitted_response_validation.rb +0 -44
  297. data/lib/davinci_crd_test_kit/client_tests/token_header_test.rb +0 -65
  298. data/lib/davinci_crd_test_kit/client_tests/token_payload_test.rb +0 -78
  299. data/lib/davinci_crd_test_kit/crd_client_suite.rb +0 -185
  300. data/lib/davinci_crd_test_kit/crd_options.rb +0 -9
  301. data/lib/davinci_crd_test_kit/crd_server_suite.rb +0 -125
  302. data/lib/davinci_crd_test_kit/igs/davinci-crd-2.0.1.tgz +0 -0
  303. data/lib/davinci_crd_test_kit/routes/cds_services_discovery_handler.rb +0 -18
  304. data/lib/davinci_crd_test_kit/routes/hook_request_endpoint.rb +0 -77
  305. data/lib/davinci_crd_test_kit/routes/jwk_set_endpoint_handler.rb +0 -15
  306. data/lib/davinci_crd_test_kit/server_appointment_book_group.rb +0 -176
  307. data/lib/davinci_crd_test_kit/server_demonstrate_hook_response_group.rb +0 -77
  308. data/lib/davinci_crd_test_kit/server_discovery_group.rb +0 -60
  309. data/lib/davinci_crd_test_kit/server_encounter_discharge_group.rb +0 -170
  310. data/lib/davinci_crd_test_kit/server_encounter_start_group.rb +0 -170
  311. data/lib/davinci_crd_test_kit/server_hooks_group.rb +0 -71
  312. data/lib/davinci_crd_test_kit/server_order_dispatch_group.rb +0 -176
  313. data/lib/davinci_crd_test_kit/server_order_select_group.rb +0 -195
  314. data/lib/davinci_crd_test_kit/server_order_sign_group.rb +0 -201
  315. data/lib/davinci_crd_test_kit/server_required_card_response_validation_group.rb +0 -26
  316. data/lib/davinci_crd_test_kit/server_tests/additional_orders_validation_test.rb +0 -68
  317. data/lib/davinci_crd_test_kit/server_tests/card_optional_fields_validation_test.rb +0 -47
  318. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_across_hooks_validation_test.rb +0 -32
  319. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_received_test.rb +0 -63
  320. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_validation_test.rb +0 -118
  321. data/lib/davinci_crd_test_kit/server_tests/create_or_update_coverage_info_response_validation_test.rb +0 -71
  322. data/lib/davinci_crd_test_kit/server_tests/discovery_endpoint_test.rb +0 -88
  323. data/lib/davinci_crd_test_kit/server_tests/discovery_services_validation_test.rb +0 -65
  324. data/lib/davinci_crd_test_kit/server_tests/external_reference_card_across_hooks_validation_test.rb +0 -28
  325. data/lib/davinci_crd_test_kit/server_tests/external_reference_card_validation_test.rb +0 -36
  326. data/lib/davinci_crd_test_kit/server_tests/form_completion_response_validation_test.rb +0 -78
  327. data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_across_hooks_test.rb +0 -25
  328. data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_test.rb +0 -26
  329. data/lib/davinci_crd_test_kit/server_tests/launch_smart_app_card_validation_test.rb +0 -38
  330. data/lib/davinci_crd_test_kit/server_tests/propose_alternate_request_card_validation_test.rb +0 -63
  331. data/lib/davinci_crd_test_kit/server_tests/service_call_test.rb +0 -101
  332. data/lib/davinci_crd_test_kit/server_tests/service_request_context_validation_test.rb +0 -28
  333. data/lib/davinci_crd_test_kit/server_tests/service_request_optional_fields_validation_test.rb +0 -37
  334. data/lib/davinci_crd_test_kit/server_tests/service_request_required_fields_validation_test.rb +0 -38
  335. data/lib/davinci_crd_test_kit/server_tests/service_response_validation_test.rb +0 -81
  336. data/lib/davinci_crd_test_kit/tags.rb +0 -10
  337. data/lib/davinci_crd_test_kit/urls.rb +0 -52
  338. /data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/external_reference.json +0 -0
  339. /data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/instructions.json +0 -0
  340. /data/lib/davinci_crd_test_kit/{crd_jwks.json → server/endpoints/crd_jwks.json} +0 -0
  341. /data/lib/davinci_crd_test_kit/{jwks.rb → server/endpoints/jwks.rb} +0 -0
@@ -0,0 +1,80 @@
1
+ require_relative '../cross_suite/base_urls'
2
+
3
+ module DaVinciCRDTestKit
4
+ DISCOVERY_PATH = '/cds-services'.freeze
5
+ APPOINTMENT_BOOK_PATH = "#{DISCOVERY_PATH}/appointment-book-service".freeze
6
+ ENCOUNTER_START_PATH = "#{DISCOVERY_PATH}/encounter-start-service".freeze
7
+ ENCOUNTER_DISCHARGE_PATH = "#{DISCOVERY_PATH}/encounter-discharge-service".freeze
8
+ ORDER_DISPATCH_PATH = "#{DISCOVERY_PATH}/order-dispatch-service".freeze
9
+ ORDER_SELECT_PATH = "#{DISCOVERY_PATH}/order-select-service".freeze
10
+ ORDER_SIGN_PATH = "#{DISCOVERY_PATH}/order-sign-service".freeze
11
+
12
+ PREFETCH_SUBSET_PREFIX = '/prefetch-subset'.freeze
13
+ PREFETCH_DISCOVERY_PATH = PREFETCH_SUBSET_PREFIX + DISCOVERY_PATH
14
+ APPOINTMENT_BOOK_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/appointment-book-subset".freeze
15
+ ENCOUNTER_START_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/encounter-start-subset".freeze
16
+ ENCOUNTER_DISCHARGE_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/encounter-discharge-subset".freeze
17
+ ORDER_DISPATCH_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/order-dispatch-subset".freeze
18
+ ORDER_SELECT_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/order-select-subset".freeze
19
+ ORDER_SIGN_PREFETCH_SUBSET_PATH = "#{PREFETCH_DISCOVERY_PATH}/order-sign-subset".freeze
20
+
21
+ module ClientBaseURLs
22
+ include BaseURLs
23
+
24
+ def discovery_url
25
+ @discovery_url ||= inferno_base_url + DISCOVERY_PATH
26
+ end
27
+
28
+ def appointment_book_url
29
+ @appointment_book_url ||= inferno_base_url + APPOINTMENT_BOOK_PATH
30
+ end
31
+
32
+ def encounter_start_url
33
+ @encounter_start_url ||= inferno_base_url + ENCOUNTER_START_PATH
34
+ end
35
+
36
+ def encounter_discharge_url
37
+ @encounter_discharge_url ||= inferno_base_url + ENCOUNTER_DISCHARGE_PATH
38
+ end
39
+
40
+ def order_dispatch_url
41
+ @order_dispatch_url ||= inferno_base_url + ORDER_DISPATCH_PATH
42
+ end
43
+
44
+ def order_select_url
45
+ @order_select_url ||= inferno_base_url + ORDER_SELECT_PATH
46
+ end
47
+
48
+ def order_sign_url
49
+ @order_sign_url ||= inferno_base_url + ORDER_SIGN_PATH
50
+ end
51
+
52
+ def prefetch_subset_discovery_url
53
+ @prefetch_subset_discovery_url ||= inferno_base_url + PREFETCH_SUBSET_PREFIX + DISCOVERY_PATH
54
+ end
55
+
56
+ def appointment_book_prefetch_subset_url
57
+ @appointment_book_prefetch_subset_url ||= inferno_base_url + APPOINTMENT_BOOK_PREFETCH_SUBSET_PATH
58
+ end
59
+
60
+ def encounter_start_prefetch_subset_url
61
+ @encounter_start_prefetch_subset_url ||= inferno_base_url + ENCOUNTER_START_PREFETCH_SUBSET_PATH
62
+ end
63
+
64
+ def encounter_discharge_prefetch_subset_url
65
+ @encounter_discharge_prefetch_subset_url ||= inferno_base_url + ENCOUNTER_DISCHARGE_PREFETCH_SUBSET_PATH
66
+ end
67
+
68
+ def order_dispatch_prefetch_subset_url
69
+ @order_dispatch_prefetch_subset_url ||= inferno_base_url + ORDER_DISPATCH_PREFETCH_SUBSET_PATH
70
+ end
71
+
72
+ def order_select_prefetch_subset_url
73
+ @order_select_prefetch_subset_url ||= inferno_base_url + ORDER_SELECT_PREFETCH_SUBSET_PATH
74
+ end
75
+
76
+ def order_sign_prefetch_subset_url
77
+ @order_sign_prefetch_subset_url ||= inferno_base_url + ORDER_SIGN_PREFETCH_SUBSET_PATH
78
+ end
79
+ end
80
+ end
@@ -1,4 +1,4 @@
1
- require_relative 'hook_request_field_validation'
1
+ require_relative '../cross_suite/hook_request_field_validation'
2
2
 
3
3
  module DaVinciCRDTestKit
4
4
  module ClientHookRequestValidation
@@ -0,0 +1,30 @@
1
+ module DaVinciCRDTestKit
2
+ module CRDClientOptions
3
+ SMART_1 = 'smart_app_launch_1'.freeze
4
+ SMART_2 = 'smart_app_launch_2'.freeze
5
+
6
+ SMART_1_REQUIREMENT = { smart_app_launch_version: SMART_1 }.freeze
7
+ SMART_2_REQUIREMENT = { smart_app_launch_version: SMART_2 }.freeze
8
+
9
+ US_CORE_3 = 'us_core_3'.freeze
10
+ US_CORE_6 = 'us_core_6'.freeze
11
+ US_CORE_7 = 'us_core_7'.freeze
12
+
13
+ US_CORE_3_REQUIREMENT = { us_core_version: US_CORE_3 }.freeze
14
+ US_CORE_6_REQUIREMENT = { us_core_version: US_CORE_6 }.freeze
15
+ US_CORE_7_REQUIREMENT = { us_core_version: US_CORE_7 }.freeze
16
+
17
+ US_CORE_3_RESOURCE_TYPES = %w[
18
+ AllergyIntolerance CarePlan CareTeam Condition Device DiagnosticReport DocumentReference Encounter Goal
19
+ Immunization Location Medication MedicationRequest Observation Organization Patient Practitioner
20
+ PractitionerRole Procedure Provenance
21
+ ].freeze
22
+
23
+ US_CORE_6_7_RESOURCE_TYPES = %w[
24
+ AllergyIntolerance CarePlan CareTeam Condition Coverage Device DiagnosticReport DocumentReference Encounter
25
+ Goal Immunization Location Medication MedicationDispense MedicationRequest Observation Organization Patient
26
+ Practitioner PractitionerRole Procedure Provenance QuestionnaireResponse RelatedPerson ServiceRequest
27
+ Specimen
28
+ ].freeze
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ module DaVinciCRDTestKit
2
+ class CDSServicesDiscoveryHandler
3
+ def self.call(...)
4
+ new.call(...)
5
+ end
6
+
7
+ def self.cds_services(version = 'v2.0.1', prefetch_subset: false)
8
+ key = "#{version}_#{prefetch_subset}"
9
+ cds_services_array[key] ||= begin
10
+ filename = if prefetch_subset
11
+ "cds-services-prefetch-subset-#{version.gsub('.', '')}.json"
12
+ else
13
+ "cds-services-#{version.gsub('.', '')}.json"
14
+ end
15
+ File.read(File.join(__dir__, '..', version, filename))
16
+ end
17
+ end
18
+
19
+ def self.cds_services_array
20
+ @cds_services_array ||= {}
21
+ end
22
+
23
+ def call(env)
24
+ path_parts = env['PATH_INFO'].split('/')
25
+ # /custom/<suite>/[prefetch-subset/]cds-services
26
+ prefetch_subset = path_parts.include?('prefetch-subset')
27
+ suite = path_parts.find { |p| p.start_with?('crd_client_') } || path_parts[-2]
28
+ version_no_dots = suite.split('_')[2].presence || 'v201' # crd_client_<version>
29
+ version = version_no_dots.sub(/\A(v\d)(\d)(\d)\z/, '\1.\2.\3')
30
+ [200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' },
31
+ [self.class.cds_services(version, prefetch_subset:)]]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,342 @@
1
+ require_relative '../../cross_suite/fhirpath_on_cds_request'
2
+ require_relative '../../cross_suite/replace_tokens'
3
+ require_relative 'gather_response_generation_data'
4
+
5
+ module DaVinciCRDTestKit
6
+ # Build responses using tester-provided template
7
+ module CustomServiceResponse
8
+ include DaVinciCRDTestKit::FhirpathOnCDSRequest
9
+ include DaVinciCRDTestKit::ReplaceTokens
10
+ include DaVinciCRDTestKit::GatherResponseGenerationData
11
+
12
+ def custom_response_template
13
+ @custom_response_template ||=
14
+ JSON.parse(result.input_json)
15
+ .find { |input| input['name'].include?('custom_response_template') }
16
+ &.dig('value')
17
+ end
18
+
19
+ def parsed_user_input
20
+ if custom_response_template.blank?
21
+ error_response('No custom template provided for custom Inferno CRD response',
22
+ code: 500,
23
+ outcome_code: 'processing')
24
+ nil
25
+ else
26
+ JSON.parse(custom_response_template)
27
+ end
28
+ rescue JSON::ParserError
29
+ error_response('Invalid template provided for custom Inferno CRD response: invalid JSON',
30
+ code: 500,
31
+ outcome_code: 'processing')
32
+ nil
33
+ end
34
+
35
+ def build_custom_hook_response
36
+ hook_response = parsed_user_input
37
+ return nil unless hook_response.present?
38
+
39
+ # filter cards and actions
40
+ filter_response(hook_response)
41
+
42
+ # update cards and actions
43
+ finalize_card_list(hook_response)
44
+ hook_response['systemActions'] = instantiate_actions(hook_response, 'systemActions')
45
+
46
+ hook_response
47
+ rescue FhirpathServiceError => e
48
+ error_response(
49
+ 'FHIRPath service error while generating custom response. ' \
50
+ 'Check the FHIRPath expressions and data in your response template and hook request. ' \
51
+ "Details: #{e.message}",
52
+ code: 500,
53
+ outcome_code: 'processing'
54
+ )
55
+ nil
56
+ end
57
+
58
+ def finalize_card_list(hook_response)
59
+ add_first_default(hook_response, 'cards') if hook_response['cards'].blank? && defaults_extension?(hook_response,
60
+ 'cards')
61
+ remove_defaults_extension(hook_response, 'cards')
62
+ hook_response['cards']&.each { |card| update_card(card) }
63
+ end
64
+
65
+ def update_card(card)
66
+ card['uuid'] = SecureRandom.uuid if card['uuid'].present?
67
+
68
+ return unless card['suggestions'].is_a?(Array)
69
+
70
+ card['suggestions'].each { |suggestion| update_suggestion(suggestion) }
71
+ end
72
+
73
+ def update_suggestion(suggestion)
74
+ suggestion['uuid'] = SecureRandom.uuid if suggestion['uuid'].present?
75
+
76
+ return unless suggestion['actions'].is_a?(Array)
77
+
78
+ suggestion['actions'] = instantiate_actions(suggestion, 'actions')
79
+ end
80
+
81
+ def instantiate_actions(parent, list_element)
82
+ actions = parent[list_element]
83
+ default_actions = get_defaults_extension_value(parent, list_element)
84
+ remove_defaults_extension(parent, list_element)
85
+
86
+ return [] unless actions.present? || default_actions.present?
87
+
88
+ instantiated_action_list = []
89
+ instantiated_resources_list = []
90
+ actions.each { |action| instantiate_an_action(action, instantiated_action_list, instantiated_resources_list) }
91
+ default_actions.each do |action|
92
+ instantiate_an_action(action, instantiated_action_list, instantiated_resources_list,
93
+ default_action: true)
94
+ end
95
+
96
+ instantiated_action_list
97
+ end
98
+
99
+ def instantiate_an_action(action, instantiated_action_list, instantiated_resources_list,
100
+ default_action: false)
101
+ replace_tokens(action, request_body)
102
+
103
+ if object_has_resource_selection_criteria?(action)
104
+ targets = get_target_resources_for_request(get_object_resource_selection_criteria_extension_value(action))
105
+ remove_resource_selection_criteria(action)
106
+ instantiate_action_using_targets(action, targets, instantiated_action_list, instantiated_resources_list,
107
+ default_action)
108
+ elsif !default_action || instantiated_action_list.blank?
109
+ instantiated_action_list << action
110
+ end
111
+ end
112
+
113
+ def instantiate_action_using_targets(action, targets, instantiated_action_list, instantiated_resources_list,
114
+ default_action)
115
+ targets.each do |target|
116
+ target_reference = "#{target['resourceType']}/#{target['id']}"
117
+ next if default_action && instantiated_resources_list.include?(target_reference)
118
+
119
+ instantiated_resources_list << target_reference unless instantiated_resources_list.include?(target_reference)
120
+ instantiated_action_list << create_instantiated_action_from_target(action, target)
121
+ end
122
+ end
123
+
124
+ def create_instantiated_action_from_target(action, target_resource)
125
+ instantiated_action = JSON.parse(action.to_json)
126
+ if instantiated_action['type'] == 'delete'
127
+ instantiated_action['resourceId'] = "#{target_resource['resourceType']}/#{target_resource['id']}"
128
+ elsif instantiated_action['resource'].is_a?(Hash)
129
+ # merge action's resource into the target resource.
130
+ # Merge extension lists, keeping duplicate url from action's resource,
131
+ # otherwise replace (top-level elements)
132
+ instantiated_action['resource'] =
133
+ merge_action_resource_into_target(instantiated_action['resource'], target_resource)
134
+
135
+ coverage_information_ext = instantiated_action['resource']['extension']&.find do |ext|
136
+ ext['url'] == 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'
137
+ end
138
+ default_coverage_information_elements(coverage_information_ext) if coverage_information_ext.present?
139
+ else
140
+ instantiated_action['resource'] = target_resource
141
+ end
142
+
143
+ instantiated_action
144
+ end
145
+
146
+ def merge_action_resource_into_target(action_resource, target_resource)
147
+ target_resource.merge(action_resource) do |key, old_value, new_value|
148
+ if key == 'extension'
149
+ old_value.select do |existing_extention|
150
+ new_value.find { |incoming_extension| existing_extention['url'] == incoming_extension['url'] }.blank?
151
+ end + new_value
152
+ else
153
+ new_value
154
+ end
155
+ end
156
+ end
157
+
158
+ def filter_response(hook_response)
159
+ filter_and_separate_defaults(hook_response, 'cards')
160
+ hook_response['cards']&.each do |card|
161
+ card['suggestions']&.each { |suggestion| filter_and_separate_defaults(suggestion, 'actions') }
162
+ end
163
+ filter_and_separate_defaults(hook_response, 'systemActions')
164
+ end
165
+
166
+ def filter_and_separate_defaults(parent, list_element)
167
+ defaults_ext = default_extension_name(list_element)
168
+ define_extension(parent, defaults_ext, [])
169
+ parent[list_element]&.select! do |object|
170
+ next false unless enabled_on_service?(object)
171
+
172
+ remove_extension(object, 'com.inferno.includeForServices')
173
+
174
+ if object_has_inclusion_criteria?(object)
175
+ if object_is_a_default?(object)
176
+ remove_inclusion_criteria(object)
177
+ parent['extension'][defaults_ext] << object
178
+
179
+ false
180
+ elsif object_included_for_this_request?(object)
181
+ remove_inclusion_criteria(object)
182
+ true
183
+ else
184
+ false
185
+ end
186
+ else
187
+ true
188
+ end
189
+ end
190
+ end
191
+
192
+ def enabled_on_service?(object)
193
+ services = get_extension_value(object, 'com.inferno.includeForServices')
194
+ return true unless services.present?
195
+
196
+ services.split(',').map(&:strip).any? { |url| request.env['PATH_INFO'].include?(url) }
197
+ end
198
+
199
+ def object_is_a_default?(object)
200
+ get_object_inclusion_criteria_extension_value(object) == 'default'
201
+ end
202
+
203
+ def default_extension_name(list_element)
204
+ "com.inferno.internal.default#{list_element.capitalize}"
205
+ end
206
+
207
+ def defaults_extension?(object, list_element)
208
+ get_defaults_extension_value(object, list_element).present?
209
+ end
210
+
211
+ def remove_defaults_extension(object, list_element)
212
+ remove_extension(object, default_extension_name(list_element))
213
+ end
214
+
215
+ def get_defaults_extension_value(object, list_element)
216
+ get_extension_value(object, default_extension_name(list_element))
217
+ end
218
+
219
+ def add_first_default(object, list_element)
220
+ object[list_element] << get_extension_value(object, default_extension_name(list_element)).first
221
+ end
222
+
223
+ def object_has_inclusion_criteria?(object)
224
+ get_object_inclusion_criteria_extension_value(object).present?
225
+ end
226
+
227
+ def get_object_inclusion_criteria_extension_value(object)
228
+ get_extension_value(object, 'com.inferno.inclusionCriteria')
229
+ end
230
+
231
+ def remove_inclusion_criteria(object)
232
+ remove_extension(object, 'com.inferno.inclusionCriteria')
233
+ end
234
+
235
+ def object_has_resource_selection_criteria?(object)
236
+ get_object_resource_selection_criteria_extension_value(object).present?
237
+ end
238
+
239
+ def get_object_resource_selection_criteria_extension_value(object)
240
+ get_extension_value(object, 'com.inferno.resourceSelectionCriteria')
241
+ end
242
+
243
+ def remove_resource_selection_criteria(object)
244
+ remove_extension(object, 'com.inferno.resourceSelectionCriteria')
245
+ end
246
+
247
+ def object_included_for_this_request?(object)
248
+ evaluate_inclusion_for_request(get_object_inclusion_criteria_extension_value(object))
249
+ end
250
+
251
+ def evaluate_inclusion_for_request(inclusion_criteria)
252
+ return false if inclusion_criteria == 'default'
253
+
254
+ result = execute_fhirpath_on_cds_request(request_body, inclusion_criteria)
255
+
256
+ if result.empty? || result.length > 1
257
+ false
258
+ elsif [true, false].include?(result[0])
259
+ result[0]
260
+ else
261
+ result[0] != 'false' # single non-false entry is always true for fhirpath
262
+ end
263
+ end
264
+
265
+ def get_target_resources_for_request(resource_selection_criteria)
266
+ execute_fhirpath_on_cds_request(request_body, resource_selection_criteria)
267
+ end
268
+
269
+ def define_extension(parent, extension, value)
270
+ parent['extension'] = {} if parent['extension'].nil?
271
+ return if parent['extension'][extension].present?
272
+
273
+ parent['extension'][extension] = value
274
+ end
275
+
276
+ def remove_extension(parent, extension)
277
+ parent['extension']&.delete(extension)
278
+ return unless parent['extension'].blank?
279
+
280
+ parent.delete('extension')
281
+ end
282
+
283
+ def get_extension_value(parent, extension)
284
+ parent.dig('extension', extension)
285
+ end
286
+
287
+ def default_coverage_information_elements(coverage_info_ext)
288
+ default_coverage_information_coverage(coverage_info_ext)
289
+ default_coverage_information_date(coverage_info_ext)
290
+ default_coverage_information_assertion_id(coverage_info_ext)
291
+ end
292
+
293
+ def default_coverage_information_coverage(coverage_info_ext)
294
+ existing_coverage_ext = coverage_info_ext['extension']&.find { |ext| ext['url'] == 'coverage' }
295
+ coverage_ext =
296
+ if existing_coverage_ext.blank?
297
+ new_coverage_ext = { url: 'coverage' }
298
+ coverage_info_ext['extension'] << new_coverage_ext
299
+ new_coverage_ext
300
+ else
301
+ existing_coverage_ext
302
+ end
303
+
304
+ return unless coverage_ext['valueReference'].blank? || coverage_ext['valueReference']['reference'].blank?
305
+
306
+ coverage_reference = "Coverage/#{request_coverage&.id}"
307
+ coverage_ext['valueReference'] = { reference: coverage_reference }
308
+ end
309
+
310
+ def default_coverage_information_date(coverage_info_ext)
311
+ existing_date_ext = coverage_info_ext['extension']&.find { |ext| ext['url'] == 'date' }
312
+ date_ext =
313
+ if existing_date_ext.blank?
314
+ new_date_ext = { url: 'date' }
315
+ coverage_info_ext['extension'] << new_date_ext
316
+ new_date_ext
317
+ else
318
+ existing_date_ext
319
+ end
320
+
321
+ return unless date_ext['valueDate'].blank?
322
+
323
+ date_ext['valueDate'] = Time.now.utc.strftime('%Y-%m-%d')
324
+ end
325
+
326
+ def default_coverage_information_assertion_id(coverage_info_ext)
327
+ existing_assertion_id_ext = coverage_info_ext['extension']&.find { |ext| ext['url'] == 'coverage-assertion-id' }
328
+ assertion_id_ext =
329
+ if existing_assertion_id_ext.blank?
330
+ new_assertion_id_ext = { url: 'coverage-assertion-id' }
331
+ coverage_info_ext['extension'] << new_assertion_id_ext
332
+ new_assertion_id_ext
333
+ else
334
+ existing_assertion_id_ext
335
+ end
336
+
337
+ return unless assertion_id_ext['valueString'].blank?
338
+
339
+ assertion_id_ext['valueString'] = SecureRandom.hex(32)
340
+ end
341
+ end
342
+ end