davinci_crd_test_kit 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +58 -1
  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 +297 -93
  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 -74
  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 -42
  277. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_read_test.rb +0 -40
  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 -42
  280. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_validation_test.rb +0 -61
  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 -48
  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 -193
  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,107 @@
1
+ module DaVinciCRDTestKit
2
+ module V221
3
+ class CRDClientServiceRegistrationAttestation < Inferno::Test
4
+ include ClientURLs
5
+
6
+ id :crd_v221_client_service_registration_attestation
7
+ title 'CRD client registers Inferno (Attestation)'
8
+ description %(
9
+ Inferno simulates two CRD servers which can be discovered at the following endpoints:
10
+ - Complete Prefetch Service Discovery Endpoint: #{ClientURLs.discovery_url}
11
+ - Subset Prefetch Service Discovery Endpoint: #{ClientURLs.prefetch_subset_discovery_url}
12
+
13
+ During this test, the tester will confirm that these two endpoints
14
+ have been registered by the client as trusted CRD servers that can access the CRD client's
15
+ FHIR server and that they have each been
16
+ - Associated with a particular payer organization (used to check that the
17
+ hook requests are sent by the client system to the appropriate payers based on
18
+ the Patient's coverage).
19
+ - Granted patient- or user-level read and search access to all US Core resource
20
+ types in the selected US Core version (required to verify the client's support
21
+ of the US Core FHIR API and used to verify the `fhirAuthorization.scope`
22
+ hook request field).
23
+ )
24
+ verifies_requirements 'cds-hooks_3.0.0-ballot@174'
25
+
26
+ input :complete_prefetch_service_organization_id,
27
+ title: 'Complete Prefetch Service Organization id',
28
+ description: %(
29
+ The FHIR Organization id associated with Inferno's simulated
30
+ complete prefetch CRD server. This Organization must be referenced as the
31
+ payer on Coverages in hook requests made to services described by the
32
+ `#{ClientURLs.discovery_url}` discovery endpoint.
33
+ The client suite may be run without this input, but it is required
34
+ for the tests to pass.
35
+ ),
36
+ type: 'text',
37
+ optional: true
38
+ input :subset_prefetch_service_organization_id,
39
+ title: 'Subset Prefetch Service Organization id',
40
+ description: %(
41
+ The FHIR Organization id associated with Inferno's simulated
42
+ subset prefetch CRD server. This Organization must be referenced
43
+ payer on Coverages in hook requests made to services described by the
44
+ `#{ClientURLs.prefetch_subset_discovery_url}` discovery endpoint.
45
+ The client suite may be run without this input, but it is required
46
+ for the tests to pass.
47
+ ),
48
+ type: 'text',
49
+ optional: true
50
+ output :attest_true_url
51
+ output :attest_false_url
52
+
53
+ def us_core_version
54
+ case suite_options[:us_core_version]
55
+ when CRDClientOptions::US_CORE_3
56
+ 'v3.1.1'
57
+ when CRDClientOptions::US_CORE_6
58
+ 'v6.1.0'
59
+ when CRDClientOptions::US_CORE_7
60
+ 'v7.0.0'
61
+ end
62
+ end
63
+
64
+ def us_core_version_resource_types
65
+ case suite_options[:us_core_version]
66
+ when CRDClientOptions::US_CORE_3
67
+ CRDClientOptions::US_CORE_3_RESOURCE_TYPES
68
+ when CRDClientOptions::US_CORE_6, CRDClientOptions::US_CORE_7
69
+ CRDClientOptions::US_CORE_6_7_RESOURCE_TYPES
70
+ end.join('`, `')
71
+ end
72
+
73
+ run do
74
+ identifier = SecureRandom.hex(32)
75
+ attest_true_url = "#{resume_pass_url}?token=#{identifier}"
76
+ attest_false_url = "#{resume_fail_url}?token=#{identifier}"
77
+ output(attest_true_url:)
78
+ output(attest_false_url:)
79
+ wait(
80
+ identifier:,
81
+ message: <<~MESSAGE
82
+ **Registration of Inferno as a trusted CRD server**:
83
+
84
+ I attest that the following Inferno CRD servers have been registered as trusted
85
+ within the client system:
86
+
87
+ - Complete Prefetch Service Discovery Endpoint: `#{discovery_url}`
88
+ - Services on this CRD server will be invoked for patients with a primary coverage issued by the payer
89
+ represented by the Organization resource with id `#{complete_prefetch_service_organization_id}`.
90
+ - The CRD server has been granted patient- or user-level read and search access scopes for
91
+ all US Core #{us_core_version} profiled resource types (`#{us_core_version_resource_types}`).
92
+
93
+ - Subset Prefetch Service Discovery Endpoint: `#{prefetch_subset_discovery_url}`
94
+ - Services on this CRD server will be invoked for patients with a primary coverage issued by the payer
95
+ represented by the Organization resource with id `#{subset_prefetch_service_organization_id}`.
96
+ - The CRD server has been granted patient- or user-level read and search access scopes for
97
+ all US Core #{us_core_version} profiled resource types (`#{us_core_version_resource_types}`).
98
+
99
+ [Click here](#{attest_true_url}) if the above statement is **true**.
100
+
101
+ [Click here](#{attest_false_url}) if the above statement is **false**.
102
+ MESSAGE
103
+ )
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,47 @@
1
+ require_relative '../../../cross_suite/requests_logical_model_validation'
2
+ require_relative '../../tagged_request_load_helper'
3
+ require_relative '../../multi_request_message_helper'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class HookRequestConformanceTest < Inferno::Test
8
+ include RequestsLogicalModelValidation
9
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
10
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
11
+
12
+ id :crd_v221_hook_request_conformance
13
+ title 'Hook requests have the correct structure and contents'
14
+ description %(
15
+ During this test, Inferno will check each request body against the structural and content
16
+ requirements for the invoked hook.
17
+ )
18
+
19
+ output :url, :smart_auth_info
20
+
21
+ verifies_requirements 'cds-hooks_3.0.0-ballot@3', 'cds-hooks_3.0.0-ballot@222', 'cds-hooks_3.0.0-ballot@223',
22
+ 'cds-hooks_3.0.0-ballot@224',
23
+ 'hl7.fhir.us.davinci-crd_2.2.1@billopt-1', 'hl7.fhir.us.davinci-crd_2.2.1@found-36-A',
24
+ 'hl7.fhir.us.davinci-crd_2.2.1@hook-20', 'hl7.fhir.us.davinci-crd_2.2.1@hook-21'
25
+
26
+ run do
27
+ hook_requests = load_hook_requests
28
+
29
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
30
+
31
+ hook_requests.each_with_index do |request, request_index|
32
+ request_body = parse_json_request_entity(request.request_body, 'Request body', request_index)
33
+ next unless request_body.present?
34
+
35
+ validate_request_against_logical_model(request_body, request_index, '2.2.1')
36
+
37
+ output url: request_body['fhirServer'] if request_body['fhirServer'].present?
38
+ if request_body.dig('fhirAuthorization', 'access_token').present?
39
+ output smart_auth_info: { access_token: request_body['fhirAuthorization']['access_token'] }.to_json
40
+ end
41
+ end
42
+
43
+ assert_no_error_messages("#{requests_with_errors_prefix}Non-conformant hook request. See Messages for details.")
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,152 @@
1
+ require_relative '../../../cross_suite/tags'
2
+ require_relative '../../multi_request_message_helper'
3
+ require_relative '../../tagged_request_load_helper'
4
+ require_relative '../client_urls'
5
+
6
+ module DaVinciCRDTestKit
7
+ module V221
8
+ class HookRequestCoverageVerificationTest < Inferno::Test
9
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
10
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
11
+ include ClientURLs
12
+
13
+ id :crd_v221_hook_request_coverage_verification
14
+ title 'Prefetched coverages are valid'
15
+ description %(
16
+ During this test, Inferno will verify that the issuing payer Organization id from the `payor` element
17
+ of each hook request's prefetched coverage matches the Organization id associated with the
18
+ invoked simulated CRD server provided by the tester during the "Registration" group.
19
+ Inferno also checks that the Organization resources conform to the
20
+ [CRD Organization](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-profile-organization.html)
21
+ profile.
22
+ )
23
+
24
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@dev-29-A', 'hl7.fhir.us.davinci-crd_2.2.1@hook-1'
25
+
26
+ input :complete_prefetch_service_organization_id,
27
+ title: 'Complete Prefetch Service Organization id',
28
+ description: %(
29
+ The FHIR Organization id associated with Inferno's simulated
30
+ complete prefetch CRD server. This Organization must be referenced as the
31
+ payer on Coverages in hook requests made to services described by the `#{ClientURLs.discovery_url}`
32
+ discovery endpoint. The client suite may be run without this input, but it is required
33
+ for the tests to pass.
34
+ Re-run the "Registration" group to provide this detail.
35
+ ),
36
+ type: 'text',
37
+ optional: true,
38
+ locked: true
39
+ input :subset_prefetch_service_organization_id,
40
+ title: 'Subset Prefetch Service Organization id',
41
+ description: %(
42
+ The FHIR Organization id associated with Inferno's simulated
43
+ subset prefetch CRD server. This Organization must be referenced
44
+ payer on Coverages in hook requests made to services described by the
45
+ `#{ClientURLs.prefetch_subset_discovery_url}` discovery endpoint.
46
+ The client suite may be run without this input, but it is required
47
+ for the tests to pass.
48
+ Re-run the "Registration" group to provide this detail.
49
+ ),
50
+ type: 'text',
51
+ optional: true,
52
+ locked: true
53
+
54
+ def prefetch_target(request)
55
+ if request.url.include?(PREFETCH_SUBSET_PREFIX)
56
+ :subset
57
+ else
58
+ :complete
59
+ end
60
+ end
61
+
62
+ def payer_org_id_for_request(request)
63
+ if prefetch_target(request) == :subset
64
+ subset_prefetch_service_organization_id
65
+ else
66
+ complete_prefetch_service_organization_id
67
+ end
68
+ end
69
+
70
+ def load_payer_request_for_hook_request(request_body)
71
+ hook_data_fetch_tag = TagMethods.hook_instance_data_fetch_tag(request_body['hookInstance'])
72
+ load_tagged_requests(PAYER_ORG_FETCH_TAG, hook_data_fetch_tag, DATA_FETCH_TAG).first
73
+ end
74
+
75
+ def check_payer_request(request_body, request_index, expected_payer_org_id)
76
+ payer_request = load_payer_request_for_hook_request(request_body)
77
+ unless payer_request.present? && payer_request.status.to_s.starts_with?('2')
78
+ add_request_message('error',
79
+ "Inferno failed to retrieve the Coverage's payer during hook processing.",
80
+ request_index)
81
+ return
82
+ end
83
+
84
+ payer_resource = FHIR.from_contents(payer_request.response_body)
85
+ unless payer_resource.present?
86
+ add_request_message('error', 'Request for payer resource returned invalid FHIR data.', request_index)
87
+ return
88
+ end
89
+
90
+ if payer_resource.resourceType != 'Organization'
91
+ add_request_message('error', 'Payer for the Coverage is not an Organization: ' \
92
+ "got '#{payer_resource.resourceType}'", request_index)
93
+ end
94
+ if payer_resource.id != expected_payer_org_id
95
+ add_request_message('error', 'Payer for the Coverage has the wrong id: ' \
96
+ "expected '#{expected_payer_org_id}', got '#{payer_resource.id}'.",
97
+ request_index)
98
+ end
99
+
100
+ validator_response_details = []
101
+ resource_is_valid?(resource: payer_resource, profile_url: 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/profile-organization|2.2.1',
102
+ add_messages_to_runnable: false, validator_response_details:)
103
+
104
+ validator_response_details.each { |issue| add_request_message(issue.severity, issue.message, request_index) }
105
+ end
106
+
107
+ run do
108
+ hook_requests = load_hook_requests
109
+
110
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
111
+
112
+ hook_requests.each_with_index do |request, request_index|
113
+ request_body = parse_json_request_entity(request.request_body, 'Request body', request_index)
114
+ next unless request_body.present?
115
+
116
+ expected_payer_org_id = payer_org_id_for_request(request)
117
+ if expected_payer_org_id.blank?
118
+ add_request_message(
119
+ 'error',
120
+ 'No Inferno Payer Organization id configured for this endpoint; skipping required coverage check.',
121
+ request_index
122
+ )
123
+ next
124
+ end
125
+
126
+ coverage = prefetched_coverage(request_body)
127
+ unless coverage.present?
128
+ add_request_message('warning', 'Request has no coverage.', request_index)
129
+ next
130
+ end
131
+
132
+ payer_organization_reference = coverage.dig('payor', 0, 'reference')
133
+ if payer_organization_reference.blank?
134
+ add_request_message('error', 'Coverage has no payer reference.', request_index)
135
+ next
136
+ end
137
+
138
+ check_payer_request(request_body, request_index, expected_payer_org_id)
139
+ end
140
+
141
+ assert_no_error_messages("#{requests_with_errors_prefix}Invalid coverage. " \
142
+ 'See Messages for details.')
143
+ end
144
+
145
+ def prefetched_coverage(request_body)
146
+ coverage = request_body.dig('prefetch', 'coverage', 'entry', 0, 'resource')
147
+ coverage = request_body.dig('prefetch', 'cov', 'entry', 0, 'resource') unless coverage.present?
148
+ coverage
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,55 @@
1
+ require_relative '../../../cross_suite/tags'
2
+ require_relative '../../tagged_request_load_helper'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class HookRequestDataFetchVerificationTest < Inferno::Test
7
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
8
+
9
+ id :crd_v221_hook_data_fetch_verification
10
+ title 'Client made additional FHIR data available during hook request processing'
11
+ description %(
12
+ During this test, Inferno will verify that for at least one hook request it was successfully
13
+ able to use the FHIR API and access token indicated in that hook request to gather additional data during
14
+ hook invocation. For this test to pass, at least one additional data request across
15
+ all hook invocations must succeed and return a FHIR resource.
16
+ )
17
+
18
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@found-20'
19
+
20
+ def fhir_data_returned?(request)
21
+ return false unless request.status.to_s.starts_with?('2')
22
+
23
+ fhir_response = FHIR.from_contents(request.response_body)
24
+ return false unless fhir_response.present?
25
+
26
+ if fhir_response.is_a?(FHIR::Bundle)
27
+ fhir_response.entry.any? { |entry| entry.resource.present? }
28
+ else
29
+ true
30
+ end
31
+ rescue JSON::ParserError
32
+ false
33
+ end
34
+
35
+ run do
36
+ hook_requests = load_hook_requests
37
+
38
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
39
+
40
+ data_returned = hook_requests.any? do |request|
41
+ request_body = JSON.parse(request.request_body)
42
+ additional_data_requests =
43
+ load_tagged_requests(TagMethods.hook_instance_data_fetch_tag(request_body['hookInstance']), DATA_FETCH_TAG)
44
+
45
+ additional_data_requests.any? { |data_request| fhir_data_returned?(data_request) }
46
+ rescue JSON::ParserError
47
+ false
48
+ end
49
+
50
+ assert data_returned,
51
+ 'Inferno was never able to successfully obtain additional FHIR data during hook processing.'
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,123 @@
1
+ require_relative '../../multi_request_message_helper'
2
+ require_relative '../../crd_client_options'
3
+ require_relative '../../tagged_request_load_helper'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class HookRequestGrantedScopesTest < Inferno::Test
8
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
9
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
10
+
11
+ id :crd_v221_hook_request_granted_scopes
12
+ title 'Hook requests grant the requested scopes'
13
+ description %(
14
+ As a part of registration, CRD clients and servers agree on a set of scopes that the server needs
15
+ to obtain all data that goes into creating hook responses. For the purposes of simulating a
16
+ payer CRD server acting as a part of these tests that evaluate conformance to the CRD specification,
17
+ Inferno requires access to all US Core resource types. While in a real exchange scenario, a CRD client
18
+ organization might well reject such a set of scopes as too large, for the purposes of testing, the client
19
+ must grant these scopes in order for Inferno to verify its conformance.
20
+
21
+ During this test, Inferno will verify that the requested scopes covering all resource types profiled in
22
+ the selected version of the US Core IG are granted and no more. Clients may choose to grant either user scopes
23
+ or patient scopes. If choosing patient scopes, note that the token is used by default for complete testing
24
+ of the client's US Core FHIR API, so either that single patient would need to
25
+ demonstrate all US Core resources and must support elements or another access token would need
26
+ to be provided when testing the client's FHIR API.
27
+ )
28
+
29
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@found-21'
30
+
31
+ run do
32
+ hook_requests = load_hook_requests
33
+
34
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
35
+
36
+ hook_requests.each_with_index do |request, request_index|
37
+ request_body = parse_json_request_entity(request.request_body, 'Request body', request_index)
38
+ next unless request_body.present?
39
+
40
+ # check that the resource scopes match what Inferno requested
41
+ granted_resource_scopes = granted_resource_scopes(request_body)
42
+ check_granted_resources(granted_resource_scopes, request_index)
43
+ check_granted_scopes_level(granted_resource_scopes, request_index)
44
+ check_granted_interactions(granted_resource_scopes, request_index)
45
+ end
46
+
47
+ assert_no_error_messages("#{requests_with_errors_prefix}Granted scopes do not match the requested scopes. " \
48
+ 'See Messages for details.')
49
+ end
50
+
51
+ def requested_scope_resources
52
+ case suite_options[:us_core_version]
53
+ when CRDClientOptions::US_CORE_3
54
+ CRDClientOptions::US_CORE_3_RESOURCE_TYPES
55
+ when CRDClientOptions::US_CORE_6, CRDClientOptions::US_CORE_7
56
+ CRDClientOptions::US_CORE_6_7_RESOURCE_TYPES
57
+ end
58
+ end
59
+
60
+ def granted_resource_scopes(request_body)
61
+ granted_scopes = request_body.dig('fhirAuthorization', 'scope')
62
+ return [] unless granted_scopes.present?
63
+
64
+ granted_scopes.split(' ').grep(%r{\A\S+/\S+\.\S+\z}) # rubocop:disable Style/RedundantArgument
65
+ end
66
+
67
+ def check_granted_resources(granted_resource_scopes, request_index)
68
+ granted_scope_resources = granted_resource_scopes.map { |scope| scope.split('/').last.split('.').first }
69
+
70
+ missing_resources = requested_scope_resources - granted_scope_resources
71
+ extra_resources = granted_scope_resources - requested_scope_resources
72
+ if missing_resources.present?
73
+ add_request_message('error', 'Granted scopes missing the following ' \
74
+ "requested resource types: #{missing_resources.join(', ')}", request_index)
75
+ end
76
+ return unless extra_resources.present?
77
+
78
+ add_request_message('error', 'Granted scopes included the following resource types ' \
79
+ "beyond what was requested: #{extra_resources.join(', ')}", request_index)
80
+ end
81
+
82
+ def check_granted_interactions(granted_resource_scopes, request_index)
83
+ return if granted_resource_scopes.all? { |scope| scope.split('.').last == 'rs' }
84
+
85
+ if granted_resource_scopes.all? { |scope| scope.split('.').last == 'read' }
86
+ add_request_message('warning',
87
+ 'SMART v1 `read` scope used. Use of SMART v2 `rs` scope recommended.',
88
+ request_index)
89
+ return
90
+ end
91
+
92
+ add_request_message('error', 'Some granted resource scopes do not provide ' \
93
+ "requested 'rs' (read and search) interactions.", request_index)
94
+ end
95
+
96
+ def check_granted_scopes_level(granted_resource_scopes, request_index)
97
+ level = scopes_level(granted_resource_scopes)
98
+ if level.blank?
99
+ add_request_message('error',
100
+ 'Requested scopes did not use a consistent level of scope (patient or user).',
101
+ request_index)
102
+ return
103
+ end
104
+
105
+ return if ['user', 'patient'].include?(level)
106
+
107
+ add_request_message('error',
108
+ "Unexpected level for granted scopes: expected 'user' or 'patient', got '#{level}'.",
109
+ request_index)
110
+ end
111
+
112
+ def scopes_level(granted_resource_scopes)
113
+ return nil unless granted_resource_scopes.present? && all_scopes_same_level?(granted_resource_scopes)
114
+
115
+ granted_resource_scopes.first.split('/').first
116
+ end
117
+
118
+ def all_scopes_same_level?(granted_resource_scopes)
119
+ granted_resource_scopes.map { |s| s.split('/').first }.uniq.size <= 1
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,127 @@
1
+ require_relative '../../../cross_suite/prefetch_completeness_checker'
2
+ require_relative '../../tagged_request_load_helper'
3
+ require_relative '../../multi_request_message_helper'
4
+ require_relative '../client_urls'
5
+
6
+ module DaVinciCRDTestKit
7
+ module V221
8
+ class HookRequestPrefetchCompleteTest < Inferno::Test
9
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
10
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
11
+
12
+ id :crd_v221_hook_request_prefetch_complete
13
+ title 'Hook requests include the requested prefetch data'
14
+ description %(
15
+ The [CDS service discovery response `prefetch` field](https://cds-hooks.hl7.org/2026Jan/en/#response)
16
+ contains key/value pairs describing additional information needed to render a response. Each key is a
17
+ string that describes the type of data being requested and the corresponding
18
+ value is a FHIR query (read or search) that will return the desired scope.
19
+ See the [Prefetch Template](https://cds-hooks.hl7.org/2026Jan/en/#prefetch-template)
20
+ section for more information about the format of `prefetch` templates.
21
+
22
+ [The CRD IG requires client support for prefetch](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/foundation.html#prefetch)
23
+ including the ability to provide all data in and subsets of the [standard prefetch templates](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/foundation.html#standard-prefetch),
24
+ when they are requested by the invoked CRD server. Inferno simulates two CRD servers,
25
+ one at `#{ClientURLs.discovery_url}` requiring the [complete set of standard prefetches](https://github.com/inferno-framework/davinci-crd-test-kit/blob/main/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json)
26
+ and the other at `#{ClientURLs.prefetch_subset_discovery_url}`
27
+ [requesting a subset of the standard prefetch data set](https://github.com/inferno-framework/davinci-crd-test-kit/blob/main/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json).
28
+
29
+ During this test, Inferno will verify that each hook request body includes a `prefetch` field populated with
30
+ valid JSON that contains exactly the requested prefetch keys and data sets described in the service description
31
+ for the invoked service as calculated by Inferno based on the resources provided in the request.
32
+ )
33
+ verifies_requirements 'cds-hooks_3.0.0-ballot@30', 'cds-hooks_3.0.0-ballot@231', 'cds-hooks_3.0.0-ballot@45',
34
+ 'cds-hooks_3.0.0-ballot@46', 'cds-hooks_3.0.0-ballot@47', 'cds-hooks_3.0.0-ballot@232',
35
+ 'cds-hooks_3.0.0-ballot@53', 'cds-hooks_3.0.0-ballot@240',
36
+ 'hl7.fhir.us.davinci-crd_2.2.1@dev-29-A', 'hl7.fhir.us.davinci-crd_2.2.1@found-23',
37
+ 'hl7.fhir.us.davinci-crd_2.2.1@found-24', 'hl7.fhir.us.davinci-crd_2.2.1@found-25-A',
38
+ 'hl7.fhir.us.davinci-crd_2.2.1@found-25-B', 'hl7.fhir.us.davinci-crd_2.2.1@found-31'
39
+
40
+ # output emitted only if the behavior is detected
41
+ output :demonstrates_fhirpath_collection_as_comma_delimited_string,
42
+ :demonstrates_prefetch_subset_distinct_from_complete,
43
+ :demonstrates_prefetch_complete_distinct_from_subset
44
+
45
+ SERVICE_FILENAMES = {
46
+ complete: 'cds-services-v221.json',
47
+ subset: 'cds-services-prefetch-subset-v221.json'
48
+ }.freeze
49
+
50
+ def service_path_for_target(target)
51
+ File.join(__dir__, '..', SERVICE_FILENAMES[target])
52
+ end
53
+
54
+ def service_path_for_opposite(target)
55
+ opposite = target == :complete ? :subset : :complete
56
+ service_path_for_target(opposite)
57
+ end
58
+
59
+ PREFETCH_KEY_COMPARISON_MAP = {
60
+ 'patient' => 'pat',
61
+ 'encounter' => 'enc',
62
+ 'coverage' => 'cov',
63
+ 'communicationRequests' => 'comReqs',
64
+ 'deviceRequests' => 'devReqs',
65
+ 'medicationRequests' => 'medReqs',
66
+ 'nutritionOrders' => 'nutOrds',
67
+ 'serviceRequests' => 'servReqs',
68
+ 'visionPrescriptions' => 'visRxs',
69
+ 'devices' => 'devs',
70
+ 'medications' => 'meds',
71
+ 'practitionerRoles' => 'roles',
72
+ 'practitioners' => 'pracs',
73
+ 'organizations' => 'orgs',
74
+ 'locations' => 'locs'
75
+ }.freeze
76
+
77
+ def key_comparison_map_for_target(target)
78
+ if target == :complete
79
+ PREFETCH_KEY_COMPARISON_MAP.invert
80
+ else
81
+ PREFETCH_KEY_COMPARISON_MAP
82
+ end
83
+ end
84
+
85
+ run do
86
+ hook_requests = load_hook_requests
87
+
88
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
89
+
90
+ hook_requests.each_with_index do |request, request_index|
91
+ hook_request = parse_json_request_entity(request.request_body, 'Request body', request_index)
92
+ next unless hook_request.present?
93
+
94
+ prefetch_target = if request.url.include?(PREFETCH_SUBSET_PREFIX)
95
+ :subset
96
+ else
97
+ :complete
98
+ end
99
+
100
+ services_path = service_path_for_target(prefetch_target)
101
+ checker = PrefetchCompletenessChecker.new(hook_request, request_index, services_path)
102
+ completeness_errors = checker.check_prefetched_data
103
+ completeness_errors.each do |error|
104
+ add_message('error', error) # NOTE: PrefetchCompletenessChecker adds the (Request #) prefix
105
+ end
106
+ if checker.observed_fhirpath_collection_as_comma_delimited_string
107
+ output demonstrates_fhirpath_collection_as_comma_delimited_string: true
108
+ end
109
+ if completeness_errors.blank? &&
110
+ checker.data_set_different_with_alternate_service?(
111
+ service_path_for_opposite(prefetch_target),
112
+ key_comparison_map_for_target(prefetch_target)
113
+ )
114
+ if prefetch_target == :subset
115
+ output demonstrates_prefetch_subset_distinct_from_complete: true
116
+ else
117
+ output demonstrates_prefetch_complete_distinct_from_subset: true
118
+ end
119
+ end
120
+ end
121
+
122
+ assert_no_error_messages("#{requests_with_errors_prefix}Incomplete or invalid prefetched data. " \
123
+ 'See Messages for details.')
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,55 @@
1
+ require_relative '../../../cross_suite/prefetch_profile_validation'
2
+ require_relative '../../tagged_request_load_helper'
3
+ require_relative '../../multi_request_message_helper'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class HookRequestPrefetchProfilesTest < Inferno::Test
8
+ include PrefetchProfileValidation
9
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
10
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
11
+
12
+ id :crd_v221_hook_request_prefetch_profiles
13
+ title 'Prefetched resources conform to the required CRD profiles'
14
+ description %(
15
+ The [CDS service discovery response `prefetch` field](https://cds-hooks.hl7.org/2026Jan/en/#response)
16
+ contains key/value pairs describing additional information needed to render a response. Each key is a
17
+ string that describes the type of data being requested and the corresponding
18
+ value is a FHIR query (read or search) that will return the desired scope.
19
+ See the [Prefetch Template](https://cds-hooks.hl7.org/2026Jan/en/#prefetch-template)
20
+ section for more information about the format of `prefetch` templates.
21
+
22
+ [The CRD IG requires client support for prefetch](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/foundation.html#prefetch)
23
+ including that the provided resources, which are part of the data included in the hook invocation,
24
+ [conform to the appropriate CRD profile](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/hooks.html#ci-c-hook-21).
25
+
26
+ During this test, Inferno will verify that each FHIR resources found under the `prefetch`
27
+ field of each request body conforms to the appropriate CRD profile.
28
+ )
29
+
30
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@hook-21', 'hl7.fhir.us.davinci-crd_2.2.1@prof-3',
31
+ 'hl7.fhir.us.davinci-crd_2.2.1@prof-4', 'hl7.fhir.us.davinci-crd_2.2.1@prof-5',
32
+ 'hl7.fhir.us.davinci-crd_2.2.1@prof-6', 'hl7.fhir.us.davinci-crd_2.2.1@prof-7',
33
+ 'hl7.fhir.us.davinci-crd_2.2.1@prof-8', 'hl7.fhir.us.davinci-crd_2.2.1@prof-9',
34
+ 'hl7.fhir.us.davinci-crd_2.2.1@prof-10', 'hl7.fhir.us.davinci-crd_2.2.1@prof-11',
35
+ 'hl7.fhir.us.davinci-crd_2.2.1@prof-12'
36
+ run do
37
+ hook_requests = load_hook_requests
38
+
39
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
40
+
41
+ hook_requests.each_with_index do |request, request_index|
42
+ hook_request = parse_json_request_entity(request.request_body, 'Request body',
43
+ request_index)
44
+ next unless hook_request.present?
45
+ next unless hook_request.key?('prefetch')
46
+
47
+ check_prefetch_profiles(hook_request['prefetch'], request_index)
48
+ end
49
+
50
+ assert_no_error_messages("#{requests_with_errors_prefix}Prefetched data not conformant to CRD profiles. " \
51
+ 'See Messages for details.')
52
+ end
53
+ end
54
+ end
55
+ end