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,54 @@
1
+ require_relative '../../multi_request_message_helper'
2
+ require_relative '../../tagged_request_load_helper'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class HookRequestRequestedVersionTest < Inferno::Test
7
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
8
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
9
+
10
+ id :crd_v221_hook_request_requested_version
11
+ title 'Hook requests contains the CRD version extension'
12
+ description %(
13
+ Inferno's CRD service supports multiple versions of CRD, so [clients are required](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/conformancedetails.html#ci-c-dev-3)
14
+ to specify the requested version using the `davinci-crd.requestedVersion` extension on each request.
15
+
16
+ During this test, Inferno will verify that the body of each hook request contains
17
+ the `davinci-crd.requestedVersion` extension with the correct value: "2.2".
18
+ )
19
+
20
+ verifies_requirements 'cds-hooks_3.0.0-ballot@214', 'hl7.fhir.us.davinci-crd_2.2.1@dev-3-A',
21
+ 'hl7.fhir.us.davinci-crd_2.2.1@dev-12'
22
+
23
+ run do
24
+ hook_requests = load_hook_requests
25
+
26
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
27
+
28
+ hook_requests.each_with_index do |request, request_index|
29
+ request_body = parse_json_request_entity(request.request_body, 'Request body', request_index)
30
+ next unless request_body.present?
31
+
32
+ requested_version = request_body.dig('extension', 'davinci-crd.requestedVersion')
33
+ if requested_version.blank?
34
+ add_request_message('error', "Required extension 'davinci-crd.requestedVersion' is not present.",
35
+ request_index)
36
+ elsif !requested_version.is_a?(String)
37
+ add_request_message('error',
38
+ "For extension 'davinci-crd.requestedVersion' expected a String, " \
39
+ "got #{requested_version.class}",
40
+ request_index)
41
+ elsif requested_version != '2.2'
42
+ add_request_message('error',
43
+ "For extension 'davinci-crd.requestedVersion' expected '2.2', " \
44
+ "got '#{requested_version}'",
45
+ request_index)
46
+ end
47
+ end
48
+
49
+ assert_no_error_messages("#{requests_with_errors_prefix}Requested version extension not populated properly. " \
50
+ 'See Messages for details.')
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,48 @@
1
+ require_relative '../../multi_request_message_helper'
2
+ require_relative '../../tagged_request_load_helper'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class HookRequestSecuredTransportTest < Inferno::Test
7
+ include DaVinciCRDTestKit::MultiRequestMessageHelper
8
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
9
+
10
+ id :crd_v221_hook_request_secured_transport
11
+ title 'Hook request interactions use TLS'
12
+ description %(
13
+ During this test, Inferno will verify that
14
+ requests made by both the client and Inferno's simulated CRD servers are made against
15
+ TLS-secured endpoints using the `https` protocol.
16
+ )
17
+ verifies_requirements 'cds-hooks_3.0.0-ballot@2', 'cds-hooks_3.0.0-ballot@168', 'cds-hooks_3.0.0-ballot@172',
18
+ 'hl7.fhir.us.davinci-crd_2.2.1@sec-2'
19
+
20
+ run do
21
+ hook_requests = load_hook_requests
22
+
23
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
24
+
25
+ hook_requests.each_with_index do |request, request_index|
26
+ unless request.url.starts_with?('https')
27
+ add_request_message('error',
28
+ "Inferno's simulated CRD server must use the https " \
29
+ 'protocol (TLS). Run this suite on a host that uses TLS.',
30
+ request_index)
31
+ end
32
+
33
+ # check that the fhirServer endpoint uses https
34
+ request_body = parse_json_request_entity(request.request_body, 'Request body', request_index)
35
+ next unless request_body.present?
36
+ next unless request_body['fhirServer'].present? && !request_body['fhirServer'].starts_with?('https')
37
+
38
+ add_request_message('error',
39
+ 'The `fhirServer` provided in the request must use the https protocol (TLS).',
40
+ request_index)
41
+ end
42
+
43
+ assert_no_error_messages("#{requests_with_errors_prefix}Interactions not secured using TLS. " \
44
+ 'See Messages for details.')
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../client_urls'
2
+ require_relative '../../../cross_suite/cards_identification'
3
+ require_relative '../../tagged_request_load_helper'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class ClientCardDisplayAttest < Inferno::Test
8
+ include ClientURLs
9
+ include CardsIdentification
10
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
11
+
12
+ id :crd_v221_card_display_attest_test
13
+ title 'Client displays returned decision support details to the user (Attestation)'
14
+ description %(
15
+ During this test, the tester will confirm that the received cards and actions in the
16
+ hook responses have been displayed or otherwise made available to users of the client system
17
+ in an appopriate way that allows for consideration and action if warranted.
18
+ )
19
+
20
+ def responded_card_types
21
+ list_card_types_in_requests(requests)
22
+ end
23
+
24
+ def format_responded_response_types
25
+ responded_card_types
26
+ .map do |response_type|
27
+ response_type_string =
28
+ response_type.split('_')
29
+ .map(&:capitalize)
30
+ .join(' ')
31
+ .prepend('- ')
32
+ .sub('Smart', 'SMART')
33
+ .sub('Create Update', 'Create/Update')
34
+ .sub('Companions Prerequisites', 'Companions/Prerequisites')
35
+ .sub('Card', '(card)')
36
+ .sub('Action', '(systemAction)')
37
+ response_type_string
38
+ end
39
+ .join("\n")
40
+ end
41
+
42
+ output :attest_true_url
43
+ output :attest_false_url
44
+
45
+ run do
46
+ load_hook_requests
47
+ skip_if responded_card_types.blank?, 'No responses sent to the client.'
48
+
49
+ identifier = SecureRandom.hex(32)
50
+ attest_true_url = "#{resume_pass_url}?token=#{identifier}"
51
+ attest_false_url = "#{resume_fail_url}?token=#{identifier}"
52
+ output(attest_true_url:)
53
+ output(attest_false_url:)
54
+ wait(
55
+ identifier:,
56
+ message: <<~MESSAGE
57
+ **Card Display Attestation**:
58
+
59
+ I attest that the following CRD response types returned by Inferno's simulated
60
+ CRD servers were processed by the client system and displayed or otherwise made
61
+ available to users of the client system in an appropriate way that allows for
62
+ consideration and action if warranted:
63
+
64
+ #{format_responded_response_types}
65
+
66
+ [Click here](#{attest_true_url}) if the above statement is **true**.
67
+
68
+ [Click here](#{attest_false_url}) if the above statement is **false**.
69
+ MESSAGE
70
+ )
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../../../cross_suite/cards_identification'
2
+ require_relative '../../tagged_request_load_helper'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class ClientHookResponseSupportCoverageInformationTest < Inferno::Test
7
+ include CardsIdentification
8
+ include TaggedRequestLoadHelper
9
+
10
+ title 'Client supports the Coverage Information response type on this hook'
11
+ id :crd_v221_client_hook_response_support_coverage_information
12
+ description <<~DESCRIPTION
13
+ During this test, Inferno will verify that the client demonstrated support for the [Coverage Information](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#coverage-information)
14
+ response type. At least one hook invocation performed during this group must have returned a Coverage Information action.
15
+
16
+ If this test fails, adjust the [cards returned by Inferno's simulated CRD server](https://github.com/inferno-framework/davinci-crd-test-kit/wiki/Controlling-Simulated-Responses)
17
+ and/or the hook requests made by the client during this group such that a Coverage Information action is returned.
18
+ DESCRIPTION
19
+
20
+ run do
21
+ hook_requests = load_hook_requests
22
+ skip_if hook_requests.blank?, "No #{hook_name} hook requests received."
23
+
24
+ sorted_cards = sorted_cards_from_requests(hook_requests)
25
+ assert sorted_cards['actions'][COVERAGE_INFORMATION_RESPONSE_TYPE].present?,
26
+ "Support for the Coverage Information response type not demonstrated for the #{hook_name} hook."
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,77 @@
1
+ require_relative '../../../cross_suite/cards_validation'
2
+ require_relative '../../../cross_suite/response_logical_model_validation'
3
+ require_relative '../../tagged_request_load_helper'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class InfernoResponseValidationTest < Inferno::Test
8
+ include CardsValidation
9
+ include ResponseLogicalModelValidation
10
+ include DaVinciCRDTestKit::TaggedRequestLoadHelper
11
+
12
+ title 'Hook responses have the correct structure and content'
13
+ description %(
14
+ During this test, Inferno will verify that each hook response built by Inferno's simulated CRD servers
15
+ and returned to the client conforms to CDS Hooks and CRD requirements. These responses must be conformant
16
+ for the client to demonstrate its ability to accept and process valid CRD responses.
17
+
18
+ If this test fails when the tester provided a custom response template, adjust the
19
+ provided template and the submitted requests so that the response built by Inferno
20
+ is conformant. If this test fails when Inferno mocked the response based on selected
21
+ card types, first ensure that the client's request is conformant. If the request is conformant
22
+ but Inferno's response(s) are still not conformant, please report this failure to the
23
+ Inferno team via [GitHub Issues](https://github.com/inferno-framework/davinci-crd-test-kit/issues).
24
+ For more details on how Inferno builds responses, see the
25
+ [Controlling Simulated Responses](https://github.com/inferno-framework/davinci-crd-test-kit/wiki/Controlling-Simulated-Responses)
26
+ section of the [CRD Test Kit Wiki](https://github.com/inferno-framework/davinci-crd-test-kit/wiki).
27
+ )
28
+ id :crd_v221_inferno_response_validation
29
+ simulation_verification
30
+
31
+ verifies_requirements 'cds-hooks_3.0.0-ballot@3', 'cds-hooks_3.0.0-ballot@222', 'cds-hooks_3.0.0-ballot@223',
32
+ 'cds-hooks_3.0.0-ballot@224'
33
+
34
+ input :custom_response_template, optional: true
35
+
36
+ def response_label(index = nil)
37
+ response_type = (custom_response_template.present? ? 'Custom built' : 'Mocked')
38
+ "#{response_type} response#{" #{index}" if index.present?}"
39
+ end
40
+
41
+ def validate_card_summaries(cards)
42
+ return unless cards.is_a?(Array)
43
+
44
+ cards.each { |card| card_summary_check(card) if card.is_a?(Hash) }
45
+ end
46
+
47
+ run do
48
+ load_hook_requests
49
+
50
+ skip_if request.blank?, "No #{response_label.downcase}s to verify."
51
+
52
+ entity_validated = false
53
+ requests.each_with_index do |request, index|
54
+ response_hash = JSON.parse(request.response_body)
55
+ request_hash = JSON.parse(request.request_body)
56
+
57
+ next unless response_hash['cards'].present? || response_hash['systemActions'].present?
58
+
59
+ entity_validated = true
60
+ validate_card_summaries(response_hash['cards'])
61
+ perform_response_logical_model_validation(response_hash['cards'],
62
+ response_hash['systemActions'],
63
+ request_hash,
64
+ index,
65
+ '2.2.1')
66
+ rescue JSON::ParserError
67
+ next
68
+ end
69
+
70
+ skip_if !entity_validated,
71
+ "No #{response_label.downcase} cards or system actions to verify returned by Inferno."
72
+
73
+ no_error_validation("Invalid Inferno #{response_label.downcase}(s). See Messages for details.")
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,20 @@
1
+ module DaVinciCRDTestKit
2
+ RESUME_PASS_PATH = '/resume_pass'.freeze
3
+ RESUME_FAIL_PATH = '/resume_fail'.freeze
4
+
5
+ # base url, plus other shared ones such as resume urls
6
+ # suite_id must be defined
7
+ module BaseURLs
8
+ def inferno_base_url
9
+ @inferno_base_url ||= "#{Inferno::Application['base_url']}/custom/#{suite_id}"
10
+ end
11
+
12
+ def resume_pass_url
13
+ @resume_pass_url ||= inferno_base_url + RESUME_PASS_PATH
14
+ end
15
+
16
+ def resume_fail_url
17
+ @resume_fail_url ||= inferno_base_url + RESUME_FAIL_PATH
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,312 @@
1
+ require_relative 'hook_request_field_validation'
2
+ require_relative 'suggestion_actions_validation'
3
+
4
+ module DaVinciCRDTestKit
5
+ module CardsIdentification
6
+ include DaVinciCRDTestKit::SuggestionActionsValidation
7
+ include DaVinciCRDTestKit::HookRequestFieldValidation
8
+
9
+ COVERAGE_INFO_EXT_URL = 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'.freeze
10
+
11
+ ADDITIONAL_ORDERS_RESPONSE_TYPE = 'companions_prerequisites'.freeze
12
+ COVERAGE_INFORMATION_RESPONSE_TYPE = 'coverage_information'.freeze
13
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE = 'create_update_coverage_info'.freeze
14
+ EXTERNAL_REFERENCE_RESPONSE_TYPE = 'external_reference'.freeze
15
+ FORM_COMPLETION_RESPONSE_TYPE = 'request_form_completion'.freeze
16
+ INSTRUCTIONS_RESPONSE_TYPE = 'instructions'.freeze
17
+ LAUNCH_SMART_APP_RESPONSE_TYPE = 'launch_smart_app'.freeze
18
+ PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE = 'propose_alternate_request'.freeze
19
+ COVERAGE_INFO_CONFIGURATION_CODE = 'coverage-info'.freeze
20
+
21
+ ADDITIONAL_ORDERS_EXPECTED_RESOURCE_TYPES = %w[
22
+ CommunicationRequest Device DeviceRequest Medication
23
+ MedicationRequest NutritionOrder ServiceRequest
24
+ VisionPrescription
25
+ ].freeze
26
+
27
+ PROPOSE_ALTERNATIVE_REQUEST_EXPECTED_RESOURCE_TYPES = %w[
28
+ CommunicationRequest Device DeviceRequest Encounter Medication
29
+ MedicationRequest NutritionOrder ServiceRequest
30
+ VisionPrescription
31
+ ].freeze
32
+
33
+ COVERAGE_INFO_EXPECTED_RESOURCE_TYPES = %w[
34
+ Appointment CommunicationRequest DeviceRequest Encounter MedicationRequest
35
+ NutritionOrder ServiceRequest VisionPrescription
36
+ ].freeze
37
+
38
+ def identify_card_type(card) # rubocop:disable Metrics/CyclomaticComplexity
39
+ return nil if card['type'].present? # action, not a card
40
+ return ADDITIONAL_ORDERS_RESPONSE_TYPE if additional_orders_response_type?(card)
41
+ return CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE if create_or_update_coverage_card_response_type?(card)
42
+ return EXTERNAL_REFERENCE_RESPONSE_TYPE if external_reference_response_type?(card)
43
+ return FORM_COMPLETION_RESPONSE_TYPE if form_completion_card_response_type?(card)
44
+ return INSTRUCTIONS_RESPONSE_TYPE if instructions_response_type?(card)
45
+ return LAUNCH_SMART_APP_RESPONSE_TYPE if launch_smart_app_response_type?(card)
46
+ return PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE if propose_alternative_request_response_type?(card)
47
+
48
+ nil
49
+ end
50
+
51
+ def identify_action_type(action)
52
+ return nil unless action['type'].present? # card, not an action
53
+ return COVERAGE_INFORMATION_RESPONSE_TYPE if coverage_information_response_type?(action)
54
+ return CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE if create_or_update_coverage_action_response_type?(action)
55
+ return FORM_COMPLETION_RESPONSE_TYPE if form_completion_action_response_type?(action)
56
+
57
+ nil
58
+ end
59
+
60
+ def coverage_info_card_type?(card)
61
+ return false unless card.respond_to?(:dig)
62
+
63
+ card.dig('source', 'topic', 'code') == COVERAGE_INFO_CONFIGURATION_CODE
64
+ end
65
+
66
+ def coverage_info_system_action_type?(action)
67
+ return false unless action.respond_to?(:[])
68
+
69
+ [COVERAGE_INFORMATION_RESPONSE_TYPE, FORM_COMPLETION_RESPONSE_TYPE].include?(identify_action_type(action))
70
+ end
71
+
72
+ def coverage_info_content(response_body)
73
+ return [[], []] unless response_body.is_a?(Hash)
74
+
75
+ cards =
76
+ if response_body['cards'].is_a?(Array)
77
+ response_body['cards'].select { |card| coverage_info_card_type?(card) }
78
+ else
79
+ []
80
+ end
81
+ actions =
82
+ if response_body['systemActions'].is_a?(Array)
83
+ response_body['systemActions'].select { |action| coverage_info_system_action_type?(action) }
84
+ else
85
+ []
86
+ end
87
+
88
+ [cards, actions]
89
+ end
90
+
91
+ def coverage_info_response?(response_body)
92
+ cards, actions = coverage_info_content(response_body)
93
+
94
+ cards.present? || actions.present?
95
+ end
96
+
97
+ def coverage_info_configuration_disabled?(request_body)
98
+ request_body.is_a?(Hash) &&
99
+ request_body.dig('extension', 'davinci-crd.configuration', COVERAGE_INFO_CONFIGURATION_CODE) == false
100
+ end
101
+
102
+ def disable_coverage_info_configuration!(request_body)
103
+ request_body['extension'] = {} unless request_body['extension'].is_a?(Hash)
104
+ unless request_body['extension']['davinci-crd.configuration'].is_a?(Hash)
105
+ request_body['extension']['davinci-crd.configuration'] = {}
106
+ end
107
+ request_body['extension']['davinci-crd.configuration'][COVERAGE_INFO_CONFIGURATION_CODE] = false
108
+
109
+ request_body
110
+ end
111
+
112
+ def additional_orders_response_type?(card, expected_resource_types: ADDITIONAL_ORDERS_EXPECTED_RESOURCE_TYPES)
113
+ return false if card['suggestions'].blank?
114
+
115
+ card['suggestions'].all? do |suggestion|
116
+ actions = suggestion['actions']
117
+ actions&.all? do |action|
118
+ action['type'] == 'create' &&
119
+ (expected_resource_types.blank? || action_resource_type_check(action, expected_resource_types))
120
+ end
121
+ end
122
+ end
123
+
124
+ def coverage_information_response_type?(action) # rubocop:disable Metrics/CyclomaticComplexity
125
+ return false unless action.respond_to?(:[])
126
+
127
+ resource = action['resource']&.to_hash
128
+ return false unless COVERAGE_INFO_EXPECTED_RESOURCE_TYPES.include? resource&.dig('resourceType')
129
+
130
+ unless resource&.dig('extension')&.any? { |extension| extension_url(extension) == COVERAGE_INFO_EXT_URL }
131
+ return false
132
+ end
133
+
134
+ true
135
+ end
136
+
137
+ def extension_url(extension)
138
+ return extension.url if extension.respond_to?(:url)
139
+ return extension['url'] if extension.respond_to?(:[])
140
+
141
+ nil
142
+ end
143
+
144
+ def create_or_update_coverage_card_response_type?(card)
145
+ card['suggestions']&.one? && card['suggestions'].first['actions']&.one? do |action|
146
+ create_or_update_coverage_action_response_type?(action)
147
+ end
148
+ end
149
+
150
+ def create_or_update_coverage_action_response_type?(action)
151
+ ['create', 'update'].include?(action['type']) && action_resource_type_check(action, ['Coverage'])
152
+ end
153
+
154
+ def create_questionnaire_action_response_type?(action)
155
+ action['type'] == 'create' && action_resource_type_check(action, ['Questionnaire'])
156
+ end
157
+
158
+ def external_reference_response_type?(card)
159
+ links = card['links']
160
+ return false if links.blank?
161
+
162
+ links.all? { |link| link['type'] == 'absolute' }
163
+ end
164
+
165
+ def form_completion_card_response_type?(card)
166
+ card['suggestions']&.all? do |suggestion|
167
+ suggestion['actions']&.one? { |action| form_completion_action_response_type?(action) }
168
+ end
169
+ end
170
+
171
+ def form_completion_action_response_type?(action)
172
+ action['type'] == 'create' &&
173
+ action_resource_type_check(action, ['Task']) &&
174
+ form_completion_task_questionnaire?(action['resource'])
175
+ end
176
+
177
+ def form_completion_task_questionnaire?(task_action)
178
+ task_action.dig('code', 'coding')&.any? { |code| code['code'] == 'complete-questionnaire' } &&
179
+ task_action['input']&.any? do |input|
180
+ input.dig('type', 'text') == 'questionnaire' && valid_url?(input['valueCanonical'])
181
+ end
182
+ end
183
+
184
+ def instructions_response_type?(card)
185
+ card['links'].blank? && card['suggestions'].blank?
186
+ end
187
+
188
+ def launch_smart_app_response_type?(card)
189
+ links = card['links']
190
+ return false if links.blank?
191
+
192
+ links.all? { |link| link['type'] == 'smart' }
193
+ end
194
+
195
+ def propose_alternative_request_response_type?(
196
+ card,
197
+ expected_resource_types: PROPOSE_ALTERNATIVE_REQUEST_EXPECTED_RESOURCE_TYPES
198
+ )
199
+ card['suggestions']&.any? do |suggestion|
200
+ actions = suggestion['actions']
201
+ has_update = check_action_type(actions, 'update', expected_resource_types)
202
+ has_delete = check_action_type(actions, 'delete', expected_resource_types)
203
+ has_create = check_action_type(actions, 'create', expected_resource_types)
204
+
205
+ has_update || (has_delete && has_create)
206
+ end
207
+ end
208
+
209
+ def check_action_type(actions, action_type, expected_resource_types)
210
+ actions&.any? do |action|
211
+ action['type'] == action_type &&
212
+ (expected_resource_types.blank? || action_resource_type_check(action, expected_resource_types))
213
+ end
214
+ end
215
+
216
+ def list_card_types_in_requests(hooks_requests)
217
+ sorted_cards = sorted_cards_from_requests(hooks_requests)
218
+
219
+ present_card_types = sorted_cards['cards'].select { |key, value| key.present? && value.present? }.keys
220
+ present_action_types = sorted_cards['actions'].select { |key, value| key.present? && value.present? }.keys
221
+
222
+ present_card_types.map { |type| "#{type}_card" } + present_action_types.map { |type| "#{type}_action" }
223
+ end
224
+
225
+ def sorted_cards_from_requests(hooks_requests)
226
+ return sorted_cards_from_cache if sorted_cards_cached?(hooks_requests)
227
+
228
+ sorted_cards = initialize_sorted_cards_hash
229
+
230
+ hooks_requests.each do |request|
231
+ sort_card_types_from_request(request, sorted_cards)
232
+ rescue JSON::ParserError
233
+ next
234
+ end
235
+
236
+ cache_sorted_cards(hooks_requests, sorted_cards)
237
+ sorted_cards
238
+ end
239
+
240
+ def sort_card_types_from_request(request, sorted_cards)
241
+ response_body = JSON.parse(request.response_body)
242
+ response_body['cards']&.each do |card|
243
+ sorted_cards['cards'][identify_card_type(card)] << card
244
+ end
245
+
246
+ response_body['systemActions']&.each do |action|
247
+ sorted_cards['actions'][identify_action_type(action)] << action
248
+ end
249
+ end
250
+
251
+ def initialize_sorted_cards_hash
252
+ {
253
+ 'cards' => {
254
+ ADDITIONAL_ORDERS_RESPONSE_TYPE => [],
255
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE => [],
256
+ EXTERNAL_REFERENCE_RESPONSE_TYPE => [],
257
+ FORM_COMPLETION_RESPONSE_TYPE => [],
258
+ INSTRUCTIONS_RESPONSE_TYPE => [],
259
+ LAUNCH_SMART_APP_RESPONSE_TYPE => [],
260
+ PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE => [],
261
+ nil => [] # unknown type
262
+ },
263
+ 'actions' => {
264
+ COVERAGE_INFORMATION_RESPONSE_TYPE => [],
265
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE => [],
266
+ FORM_COMPLETION_RESPONSE_TYPE => [],
267
+ nil => [] # unknown type
268
+ }
269
+ }
270
+ end
271
+
272
+ def extract_coverage_information_extensions(sorted_cards)
273
+ coverage_information_extensions = []
274
+
275
+ sorted_cards['actions'][COVERAGE_INFORMATION_RESPONSE_TYPE].each do |coverage_information_action|
276
+ coverage_information_action['resource']['extension'].each do |extension|
277
+ coverage_information_extensions << extension if extension['url'] == COVERAGE_INFO_EXT_URL
278
+ end
279
+ end
280
+
281
+ coverage_information_extensions.map { |ext| FHIR::Extension.new(ext) }
282
+ end
283
+
284
+ def sorted_cards_cached?(requests)
285
+ return false unless scratch['sorted_cards'].present?
286
+ return false unless scratch['sorted_cards']['hook_instances'].length == requests.length
287
+
288
+ requests.all? do |request|
289
+ scratch['sorted_cards']['hook_instances'].include?(JSON.parse(request.request_body)&.dig('hookInstance'))
290
+ rescue JSON::ParserError
291
+ false
292
+ end
293
+ end
294
+
295
+ def cache_sorted_cards(requests, sorted_cards)
296
+ scratch['sorted_cards'] = {
297
+ 'hook_instances' => hook_instances_from_requests(requests),
298
+ 'data' => sorted_cards
299
+ }
300
+ rescue JSON::ParserError
301
+ nil
302
+ end
303
+
304
+ def sorted_cards_from_cache
305
+ scratch['sorted_cards']['data']
306
+ end
307
+
308
+ def hook_instances_from_requests(requests)
309
+ requests.map { |request| JSON.parse(request.request_body)&.dig('hookInstance') }.compact
310
+ end
311
+ end
312
+ end