davinci_crd_test_kit 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) 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 +188 -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 +239 -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}/external_reference.json +1 -1
  20. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/launch_smart_app.json +1 -1
  21. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/propose_alternate_request.json +1 -0
  22. data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/request_form_completion.json +17 -16
  23. data/lib/davinci_crd_test_kit/client/multi_request_message_helper.rb +35 -0
  24. data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +38 -0
  25. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_create_test.rb +43 -0
  26. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_read_test.rb +43 -0
  27. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_search_test.rb +234 -0
  28. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_update_test.rb +43 -0
  29. data/lib/davinci_crd_test_kit/client/v2.0.1/api/client_fhir_api_validation_test.rb +63 -0
  30. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/decode_auth_token_test.rb +65 -0
  31. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +109 -0
  32. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_header_test.rb +70 -0
  33. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +85 -0
  34. data/lib/davinci_crd_test_kit/{routes/cds-services.json → client/v2.0.1/cds-services-v201.json} +1 -1
  35. data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +108 -0
  36. data/lib/davinci_crd_test_kit/client/v2.0.1/client_card_must_support_group.rb +31 -0
  37. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +105 -0
  38. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +105 -0
  39. data/lib/davinci_crd_test_kit/client/v2.0.1/client_fhir_api_group.rb +790 -0
  40. data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +74 -0
  41. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +111 -0
  42. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +116 -0
  43. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +113 -0
  44. data/lib/davinci_crd_test_kit/{client_registration_group.rb → client/v2.0.1/client_registration_group.rb} +12 -8
  45. data/lib/davinci_crd_test_kit/client/v2.0.1/client_urls.rb +13 -0
  46. data/lib/davinci_crd_test_kit/client/v2.0.1/crd_client_suite.rb +134 -0
  47. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/appointment_book_receive_request_test.rb +129 -0
  48. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_discharge_receive_request_test.rb +126 -0
  49. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/encounter_start_receive_request_test.rb +126 -0
  50. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_dispatch_receive_request_test.rb +138 -0
  51. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_select_receive_request_test.rb +134 -0
  52. data/lib/davinci_crd_test_kit/client/v2.0.1/invocation/order_sign_receive_request_test.rb +136 -0
  53. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +93 -0
  54. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +62 -0
  55. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +62 -0
  56. data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_registration_verification_test.rb +94 -0
  57. data/lib/davinci_crd_test_kit/client/v2.0.1/registration/client_service_registration_attestation_test.rb +40 -0
  58. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +86 -0
  59. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_optional_fields_test.rb +63 -0
  60. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +96 -0
  61. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_required_fields_test.rb +55 -0
  62. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_context_test.rb +70 -0
  63. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_valid_prefetch_test.rb +62 -0
  64. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +83 -0
  65. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +79 -0
  66. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +212 -0
  67. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_crd_update_verification_group.rb +18 -0
  68. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +69 -0
  69. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +120 -0
  70. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_header_test.rb +92 -0
  71. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +93 -0
  72. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +198 -0
  73. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +202 -0
  74. data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +109 -0
  75. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +28 -0
  76. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +102 -0
  77. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +101 -0
  78. data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +88 -0
  79. data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +84 -0
  80. data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +32 -0
  81. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +107 -0
  82. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +108 -0
  83. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +113 -0
  84. data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +33 -0
  85. data/lib/davinci_crd_test_kit/client/v2.2.1/client_urls.rb +27 -0
  86. data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +234 -0
  87. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +63 -0
  88. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +60 -0
  89. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +45 -0
  90. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +135 -0
  91. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +103 -0
  92. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +156 -0
  93. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +157 -0
  94. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +157 -0
  95. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +165 -0
  96. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +165 -0
  97. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +165 -0
  98. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +64 -0
  99. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +54 -0
  100. data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_registration_verification_test.rb +161 -0
  101. data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +108 -0
  102. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +47 -0
  103. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +152 -0
  104. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +55 -0
  105. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +123 -0
  106. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +133 -0
  107. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +55 -0
  108. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +54 -0
  109. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +48 -0
  110. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +75 -0
  111. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +30 -0
  112. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +77 -0
  113. data/lib/davinci_crd_test_kit/cross_suite/base_urls.rb +20 -0
  114. data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +321 -0
  115. data/lib/davinci_crd_test_kit/{cards_validation.rb → cross_suite/cards_validation.rb} +104 -47
  116. data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu201_metadata.yml +27 -0
  117. data/lib/davinci_crd_test_kit/cross_suite/coverage-information_stu221_metadata.yml +60 -0
  118. data/lib/davinci_crd_test_kit/cross_suite/fhirpath_on_cds_request.rb +177 -0
  119. data/lib/davinci_crd_test_kit/{hook_request_field_validation.rb → cross_suite/hook_request_field_validation.rb} +282 -203
  120. data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +220 -0
  121. data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +476 -0
  122. data/lib/davinci_crd_test_kit/cross_suite/prefetch_contents_validation.rb +81 -0
  123. data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +48 -0
  124. data/lib/davinci_crd_test_kit/cross_suite/profiles_and_resource_types.rb +63 -0
  125. data/lib/davinci_crd_test_kit/cross_suite/replace_tokens.rb +38 -0
  126. data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +203 -0
  127. data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +435 -0
  128. data/lib/davinci_crd_test_kit/{suggestion_actions_validation.rb → cross_suite/suggestion_actions_validation.rb} +70 -50
  129. data/lib/davinci_crd_test_kit/cross_suite/tags.rb +46 -0
  130. data/lib/davinci_crd_test_kit/metadata.rb +10 -44
  131. data/lib/davinci_crd_test_kit/requirements/cds-hooks-library_1.0.1_requirements.xlsx +0 -0
  132. data/lib/davinci_crd_test_kit/requirements/cds-hooks_2.0_requirements.xlsx +0 -0
  133. data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
  134. data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +742 -65
  135. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +279 -54
  136. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +1430 -0
  137. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +36 -45
  138. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +143 -0
  139. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.0.1_requirements.xlsx +0 -0
  140. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
  141. data/lib/davinci_crd_test_kit/server/endpoints/jwk_set_endpoint_handler.rb +13 -0
  142. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_create_endpoint.rb +23 -0
  143. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_delete_endpoint.rb +30 -0
  144. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_metadata_endpoint.rb +112 -0
  145. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_read_endpoint.rb +21 -0
  146. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_request_handler.rb +261 -0
  147. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_search_endpoint.rb +561 -0
  148. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/fhir_update_endpoint.rb +24 -0
  149. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr/stress-test-Bundle.json +54687 -0
  150. data/lib/davinci_crd_test_kit/server/endpoints/mock_ehr_endpoints.rb +95 -0
  151. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +225 -0
  152. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_no_special_requests.rb +17 -0
  153. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_with_bad_auth.rb +14 -0
  154. data/lib/davinci_crd_test_kit/{jwt_helper.rb → server/jwt_helper.rb} +1 -12
  155. data/lib/davinci_crd_test_kit/server/resource_extractor.rb +68 -0
  156. data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +183 -0
  157. data/lib/davinci_crd_test_kit/server/server_base_urls.rb +30 -0
  158. data/lib/davinci_crd_test_kit/{server_hook_helper.rb → server/server_hook_helper.rb} +3 -3
  159. data/lib/davinci_crd_test_kit/{server_hook_request_validation.rb → server/server_hook_request_validation.rb} +1 -1
  160. data/lib/davinci_crd_test_kit/{test_helper.rb → server/server_test_helper.rb} +7 -3
  161. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Appointment.yml +5 -0
  162. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ClaimResponse.yml +5 -0
  163. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/CommunicationRequest.yml +5 -0
  164. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Coverage.yml +21 -0
  165. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Device.yml +5 -0
  166. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/DeviceRequest.yml +5 -0
  167. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Encounter.yml +7 -0
  168. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Location.yml +5 -0
  169. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/MedicationRequest.yml +5 -0
  170. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/NutritionOrder.yml +5 -0
  171. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Organization.yml +5 -0
  172. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Patient.yml +5 -0
  173. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Practitioner.yml +5 -0
  174. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/PractitionerRole.yml +40 -0
  175. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/ServiceRequest.yml +5 -0
  176. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/Task.yml +5 -0
  177. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_metadata/VisionPrescription.yml +5 -0
  178. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +99 -0
  179. data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_endpoint_test.rb +90 -0
  180. data/lib/davinci_crd_test_kit/server/v2.0.1/discovery/discovery_services_validation_test.rb +67 -0
  181. data/lib/davinci_crd_test_kit/server/v2.0.1/interaction/server_invoke_hook_test.rb +12 -0
  182. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +34 -0
  183. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/external_reference_card_across_hooks_validation_test.rb +30 -0
  184. data/lib/davinci_crd_test_kit/server/v2.0.1/must_support/instructions_card_received_across_hooks_test.rb +27 -0
  185. data/lib/davinci_crd_test_kit/server/v2.0.1/server_appointment_book_group.rb +191 -0
  186. data/lib/davinci_crd_test_kit/server/v2.0.1/server_demonstrate_hook_response_group.rb +93 -0
  187. data/lib/davinci_crd_test_kit/server/v2.0.1/server_discovery_group.rb +62 -0
  188. data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_discharge_group.rb +186 -0
  189. data/lib/davinci_crd_test_kit/server/v2.0.1/server_encounter_start_group.rb +186 -0
  190. data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +73 -0
  191. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_dispatch_group.rb +191 -0
  192. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_select_group.rb +211 -0
  193. data/lib/davinci_crd_test_kit/server/v2.0.1/server_order_sign_group.rb +216 -0
  194. data/lib/davinci_crd_test_kit/server/v2.0.1/server_required_card_response_validation_group.rb +28 -0
  195. data/lib/davinci_crd_test_kit/server/v2.0.1/server_urls.rb +13 -0
  196. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_context_validation_test.rb +30 -0
  197. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_optional_fields_validation_test.rb +39 -0
  198. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_request/service_request_required_fields_validation_test.rb +40 -0
  199. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/additional_orders_validation_test.rb +59 -0
  200. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/card_optional_fields_validation_test.rb +51 -0
  201. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_received_test.rb +65 -0
  202. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/coverage_information_system_action_validation_test.rb +120 -0
  203. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +70 -0
  204. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/external_reference_card_validation_test.rb +37 -0
  205. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/form_completion_response_validation_test.rb +67 -0
  206. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/instructions_card_received_test.rb +30 -0
  207. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/launch_smart_app_card_validation_test.rb +39 -0
  208. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/propose_alternate_request_card_validation_test.rb +46 -0
  209. data/lib/davinci_crd_test_kit/server/v2.0.1/verify_response/service_response_validation_test.rb +83 -0
  210. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withorder.yml +5 -0
  211. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Appointment_withoutorder.yml +5 -0
  212. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/CommunicationRequest.yml +5 -0
  213. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Coverage.yml +5 -0
  214. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Device.yml +5 -0
  215. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/DeviceRequest.yml +5 -0
  216. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Encounter.yml +5 -0
  217. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Location.yml +5 -0
  218. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/MedicationRequest.yml +5 -0
  219. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/NutritionOrder.yml +5 -0
  220. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Organization.yml +5 -0
  221. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/Patient.yml +5 -0
  222. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/PractitionerRole.yml +5 -0
  223. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/ServiceRequest.yml +5 -0
  224. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_metadata/VisionPrescription.yml +5 -0
  225. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +118 -0
  226. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_configuration_test.rb +159 -0
  227. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_endpoint_test.rb +90 -0
  228. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_prefetch_support_test.rb +43 -0
  229. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_services_validation_test.rb +121 -0
  230. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_standard_prefetch_expressions_test.rb +166 -0
  231. data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_single_request_test.rb +22 -0
  232. data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_test.rb +17 -0
  233. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_must_support_test.rb +71 -0
  234. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/coverage_information_system_action_across_hooks_validation_test.rb +36 -0
  235. data/lib/davinci_crd_test_kit/server/v2.2.1/must_support/supported_us_core_versions_test.rb +118 -0
  236. data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +121 -0
  237. data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +94 -0
  238. data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +71 -0
  239. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +107 -0
  240. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +107 -0
  241. data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +73 -0
  242. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +121 -0
  243. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +115 -0
  244. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +132 -0
  245. data/lib/davinci_crd_test_kit/server/v2.2.1/server_required_card_response_validation_group.rb +30 -0
  246. data/lib/davinci_crd_test_kit/server/v2.2.1/server_urls.rb +13 -0
  247. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_response_group.rb +23 -0
  248. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_info_reason_test.rb +108 -0
  249. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_not_found_group.rb +116 -0
  250. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_active_coverage_group.rb +115 -0
  251. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_member_found_group.rb +117 -0
  252. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_group.rb +121 -0
  253. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_invoke_test.rb +22 -0
  254. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +31 -0
  255. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_no_custom_extensions_test.rb +120 -0
  256. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +40 -0
  257. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +41 -0
  258. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +109 -0
  259. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/all_responses_include_coverage_information_test.rb +123 -0
  260. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_info_configuration_test.rb +83 -0
  261. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_card_absence_test.rb +76 -0
  262. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +130 -0
  263. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +119 -0
  264. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +89 -0
  265. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +126 -0
  266. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +174 -0
  267. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +83 -0
  268. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +88 -0
  269. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/order_dispatch_coverage_information_test.rb +38 -0
  270. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +81 -0
  271. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +63 -0
  272. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +78 -0
  273. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +78 -0
  274. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +78 -0
  275. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_billing_options_test.rb +43 -0
  276. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/verify_response_without_configuration_test.rb +44 -0
  277. data/lib/davinci_crd_test_kit/version.rb +2 -2
  278. data/lib/davinci_crd_test_kit.rb +4 -2
  279. metadata +307 -93
  280. data/lib/davinci_crd_test_kit/client_fhir_api_group.rb +0 -785
  281. data/lib/davinci_crd_test_kit/client_hooks_group.rb +0 -74
  282. data/lib/davinci_crd_test_kit/client_tests/appointment_book_receive_request_test.rb +0 -93
  283. data/lib/davinci_crd_test_kit/client_tests/client_appointment_book_group.rb +0 -75
  284. data/lib/davinci_crd_test_kit/client_tests/client_display_cards_attest.rb +0 -48
  285. data/lib/davinci_crd_test_kit/client_tests/client_encounter_discharge_group.rb +0 -73
  286. data/lib/davinci_crd_test_kit/client_tests/client_encounter_start_group.rb +0 -73
  287. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_create_test.rb +0 -42
  288. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_read_test.rb +0 -40
  289. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_search_test.rb +0 -232
  290. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_update_test.rb +0 -42
  291. data/lib/davinci_crd_test_kit/client_tests/client_fhir_api_validation_test.rb +0 -61
  292. data/lib/davinci_crd_test_kit/client_tests/client_order_dispatch_group.rb +0 -79
  293. data/lib/davinci_crd_test_kit/client_tests/client_order_select_group.rb +0 -82
  294. data/lib/davinci_crd_test_kit/client_tests/client_order_sign_group.rb +0 -81
  295. data/lib/davinci_crd_test_kit/client_tests/client_registration_verification_test.rb +0 -88
  296. data/lib/davinci_crd_test_kit/client_tests/decode_auth_token_test.rb +0 -60
  297. data/lib/davinci_crd_test_kit/client_tests/encounter_discharge_receive_request_test.rb +0 -90
  298. data/lib/davinci_crd_test_kit/client_tests/encounter_start_receive_request_test.rb +0 -90
  299. data/lib/davinci_crd_test_kit/client_tests/hook_request_optional_fields_test.rb +0 -57
  300. data/lib/davinci_crd_test_kit/client_tests/hook_request_required_fields_test.rb +0 -49
  301. data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_context_test.rb +0 -68
  302. data/lib/davinci_crd_test_kit/client_tests/hook_request_valid_prefetch_test.rb +0 -69
  303. data/lib/davinci_crd_test_kit/client_tests/order_dispatch_receive_request_test.rb +0 -102
  304. data/lib/davinci_crd_test_kit/client_tests/order_select_receive_request_test.rb +0 -98
  305. data/lib/davinci_crd_test_kit/client_tests/order_sign_receive_request_test.rb +0 -101
  306. data/lib/davinci_crd_test_kit/client_tests/retrieve_jwks_test.rb +0 -105
  307. data/lib/davinci_crd_test_kit/client_tests/submitted_response_validation.rb +0 -48
  308. data/lib/davinci_crd_test_kit/client_tests/token_header_test.rb +0 -65
  309. data/lib/davinci_crd_test_kit/client_tests/token_payload_test.rb +0 -78
  310. data/lib/davinci_crd_test_kit/crd_client_suite.rb +0 -193
  311. data/lib/davinci_crd_test_kit/crd_options.rb +0 -9
  312. data/lib/davinci_crd_test_kit/crd_server_suite.rb +0 -125
  313. data/lib/davinci_crd_test_kit/igs/davinci-crd-2.0.1.tgz +0 -0
  314. data/lib/davinci_crd_test_kit/routes/cds_services_discovery_handler.rb +0 -18
  315. data/lib/davinci_crd_test_kit/routes/hook_request_endpoint.rb +0 -77
  316. data/lib/davinci_crd_test_kit/routes/jwk_set_endpoint_handler.rb +0 -15
  317. data/lib/davinci_crd_test_kit/server_appointment_book_group.rb +0 -176
  318. data/lib/davinci_crd_test_kit/server_demonstrate_hook_response_group.rb +0 -77
  319. data/lib/davinci_crd_test_kit/server_discovery_group.rb +0 -60
  320. data/lib/davinci_crd_test_kit/server_encounter_discharge_group.rb +0 -170
  321. data/lib/davinci_crd_test_kit/server_encounter_start_group.rb +0 -170
  322. data/lib/davinci_crd_test_kit/server_hooks_group.rb +0 -71
  323. data/lib/davinci_crd_test_kit/server_order_dispatch_group.rb +0 -176
  324. data/lib/davinci_crd_test_kit/server_order_select_group.rb +0 -195
  325. data/lib/davinci_crd_test_kit/server_order_sign_group.rb +0 -201
  326. data/lib/davinci_crd_test_kit/server_required_card_response_validation_group.rb +0 -26
  327. data/lib/davinci_crd_test_kit/server_tests/additional_orders_validation_test.rb +0 -68
  328. data/lib/davinci_crd_test_kit/server_tests/card_optional_fields_validation_test.rb +0 -47
  329. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_across_hooks_validation_test.rb +0 -32
  330. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_received_test.rb +0 -63
  331. data/lib/davinci_crd_test_kit/server_tests/coverage_information_system_action_validation_test.rb +0 -118
  332. data/lib/davinci_crd_test_kit/server_tests/create_or_update_coverage_info_response_validation_test.rb +0 -71
  333. data/lib/davinci_crd_test_kit/server_tests/discovery_endpoint_test.rb +0 -88
  334. data/lib/davinci_crd_test_kit/server_tests/discovery_services_validation_test.rb +0 -65
  335. data/lib/davinci_crd_test_kit/server_tests/external_reference_card_across_hooks_validation_test.rb +0 -28
  336. data/lib/davinci_crd_test_kit/server_tests/external_reference_card_validation_test.rb +0 -36
  337. data/lib/davinci_crd_test_kit/server_tests/form_completion_response_validation_test.rb +0 -78
  338. data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_across_hooks_test.rb +0 -25
  339. data/lib/davinci_crd_test_kit/server_tests/instructions_card_received_test.rb +0 -26
  340. data/lib/davinci_crd_test_kit/server_tests/launch_smart_app_card_validation_test.rb +0 -38
  341. data/lib/davinci_crd_test_kit/server_tests/propose_alternate_request_card_validation_test.rb +0 -63
  342. data/lib/davinci_crd_test_kit/server_tests/service_call_test.rb +0 -101
  343. data/lib/davinci_crd_test_kit/server_tests/service_request_context_validation_test.rb +0 -28
  344. data/lib/davinci_crd_test_kit/server_tests/service_request_optional_fields_validation_test.rb +0 -37
  345. data/lib/davinci_crd_test_kit/server_tests/service_request_required_fields_validation_test.rb +0 -38
  346. data/lib/davinci_crd_test_kit/server_tests/service_response_validation_test.rb +0 -81
  347. data/lib/davinci_crd_test_kit/tags.rb +0 -10
  348. data/lib/davinci_crd_test_kit/urls.rb +0 -52
  349. /data/lib/davinci_crd_test_kit/{card_responses → client/endpoints/mocked_card_responses}/instructions.json +0 -0
  350. /data/lib/davinci_crd_test_kit/{crd_jwks.json → server/endpoints/crd_jwks.json} +0 -0
  351. /data/lib/davinci_crd_test_kit/{jwks.rb → server/endpoints/jwks.rb} +0 -0
@@ -0,0 +1,159 @@
1
+ module DaVinciCRDTestKit
2
+ module V221
3
+ class DiscoveryConfigurationTest < Inferno::Test
4
+ title 'Server makes configuration options available'
5
+ id :crd_v221_discovery_configuration
6
+ description %(
7
+ According to the spec:
8
+
9
+ > CRD servers SHALL, at minimum, offer configuration options for each
10
+ type of card they support
11
+
12
+ This test verifies that all primary hook services contain at least one
13
+ valid configuration option for `coverage-info`. Secondary hooks are not
14
+ expected to return cards, so they are ignored in this test.
15
+ )
16
+
17
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@dev-4',
18
+ 'hl7.fhir.us.davinci-crd_2.2.1@dev-5',
19
+ 'hl7.fhir.us.davinci-crd_2.2.1@dev-7',
20
+ 'hl7.fhir.us.davinci-crd_2.2.1@dev-8'
21
+
22
+ input :cds_services
23
+ input :crd_discovery_service_ignore_list,
24
+ optional: true
25
+
26
+ def primary_hooks
27
+ ['appointment-book', 'order-sign', 'order-dispatch']
28
+ end
29
+
30
+ def primary_hook?(hook)
31
+ primary_hooks.include? hook
32
+ end
33
+
34
+ def required_fields
35
+ ['code', 'type', 'name', 'description', 'default']
36
+ end
37
+
38
+ def verify_unique_values(hook, service)
39
+ unique_fields = ['code', 'name', 'description']
40
+
41
+ config_options =
42
+ service
43
+ .dig('extension', 'davinci-crd.configuration-options')
44
+
45
+ return if config_options.blank?
46
+
47
+ unique_fields.each do |unique_field|
48
+ value_counts =
49
+ config_options
50
+ .map { |config_option| config_option[unique_field] }
51
+ .tally
52
+
53
+ duplicate_values =
54
+ value_counts
55
+ .select { |_value, count| count > 1 }
56
+ .keys
57
+
58
+ next if duplicate_values.blank?
59
+
60
+ duplicate_values_string = duplicate_values.map { |value| "\n- `#{value}`" }.join
61
+
62
+ add_message(
63
+ 'error',
64
+ "Services for hook `#{hook}` contain duplicate values for `#{unique_field}`:" \
65
+ "#{duplicate_values_string}"
66
+ )
67
+ end
68
+ end
69
+
70
+ def verify_required_fields(hook, service)
71
+ service.dig('extension', 'davinci-crd.configuration-options')&.each do |config_option|
72
+ required_fields.each do |field_name|
73
+ unless config_option.key?(field_name)
74
+ add_message(
75
+ 'error',
76
+ "Hook `#{hook}` service `#{service['id']}` configuration option `#{config_option['code']}` " \
77
+ "does not contain `#{field_name}` field"
78
+ )
79
+ next
80
+ end
81
+
82
+ next if field_name == 'default'
83
+
84
+ next if config_option[field_name].is_a? String
85
+
86
+ type = config_option[field_name].class
87
+ add_message(
88
+ 'error',
89
+ "Expected hook `#{hook}` service `#{service['id']}` configuration option `#{config_option['code']}` " \
90
+ "field `#{field_name}` to be a String, but found #{type}"
91
+ )
92
+ end
93
+ end
94
+ end
95
+
96
+ run do
97
+ ignore_list = crd_discovery_service_ignore_list.to_s.split(',').map(&:strip).reject(&:blank?)
98
+ services =
99
+ JSON.parse(cds_services)['services']
100
+ .reject { |service| ignore_list.include? service['id'] }
101
+
102
+ services_by_hook = services.group_by { |service| service['hook'] }
103
+
104
+ services_by_hook.each do |hook, hook_services|
105
+ hook_services.each do |service|
106
+ verify_required_fields(hook, service)
107
+ verify_unique_values(hook, service)
108
+ end
109
+ end
110
+
111
+ primary_hook_services = services_by_hook.slice(*primary_hooks).values.flatten
112
+
113
+ assert messages.none? { |message| message[:type] == 'error' },
114
+ 'Some services contain invalid configuration options.'
115
+
116
+ omit_if primary_hook_services.blank?, 'No services for primary hooks found'
117
+
118
+ services_without_configuration_options =
119
+ primary_hook_services.reject do |service|
120
+ service['extension'].present? && service['extension']['davinci-crd.configuration-options'].present?
121
+ end
122
+
123
+ if services_without_configuration_options.present?
124
+ add_message(
125
+ 'error',
126
+ 'The following services do not contain any configuration options: ' \
127
+ "#{services_without_configuration_options.map { |service| service['code'] }.join(', ')}"
128
+ )
129
+ end
130
+
131
+ primary_hook_services.each do |service|
132
+ coverage_info_config =
133
+ service.dig('extension', 'davinci-crd.configuration-options')&.find do |config_option|
134
+ config_option['code'] == 'coverage-info'
135
+ end
136
+
137
+ if coverage_info_config.present?
138
+ if coverage_info_config['type'] != 'boolean'
139
+ add_message(
140
+ 'error',
141
+ "Service `#{service['id']}` `coverage-info` configuration option is not of type boolean"
142
+ )
143
+ end
144
+
145
+ next
146
+ end
147
+
148
+ add_message(
149
+ 'error',
150
+ "Service `#{service['id']}` does not contain a `coverage-info` configuration option"
151
+ )
152
+ end
153
+
154
+ assert messages.none? { |message| message[:type] == 'error' },
155
+ 'Not all primary hook services contain valid configuration options.'
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,90 @@
1
+ module DaVinciCRDTestKit
2
+ module V221
3
+ class DiscoveryEndpointTest < Inferno::Test
4
+ title 'Server returns a discovery response'
5
+ id :crd_v221_discovery_endpoint_test
6
+ description %(
7
+ A CDS Service provider must expose its discovery endpoint at `{baseURL}/cds-services`
8
+ as specified in the [CDS Hooks Specification](https://cds-hooks.hl7.org/2.0/#discovery).
9
+
10
+ This test checks that the server responds to a GET request at the following endpoint:
11
+
12
+ `GET {baseURL}/cds-services`
13
+
14
+ It does this by checking that the server responds with an HTTP OK 200 status code
15
+ and that the body of the response is a valid JSON object. This test does not
16
+ inspect the structure and content of the response body to see if it contains the required information.
17
+ It only checks to see if the RESTful interaction is supported and returns a valid JSON object.
18
+ )
19
+
20
+ input_order :base_url, :authentication_required, :encryption_method, :jwks_kid
21
+ input :base_url
22
+ input :authentication_required,
23
+ title: 'Discovery endpoint requires authentication?',
24
+ type: 'radio',
25
+ default: 'no',
26
+ options: {
27
+ list_options: [
28
+ {
29
+ label: 'No',
30
+ value: 'no'
31
+ },
32
+ {
33
+ label: 'Yes',
34
+ value: 'yes'
35
+ }
36
+ ]
37
+ }
38
+ input :encryption_method,
39
+ title: 'JWT Signing Algorithm',
40
+ description: <<~DESCRIPTION,
41
+ CDS Hooks recommends ES384 and RS384 for JWT signature verification.
42
+ Select which method to use.
43
+ DESCRIPTION
44
+ type: 'radio',
45
+ default: 'ES384',
46
+ options: {
47
+ list_options: [
48
+ {
49
+ label: 'ES384',
50
+ value: 'ES384'
51
+ },
52
+ {
53
+ label: 'RS384',
54
+ value: 'RS384'
55
+ }
56
+ ]
57
+ }
58
+ input :jwks_kid,
59
+ title: 'CDS Services JWKS kid',
60
+ description: <<~DESCRIPTION,
61
+ The key ID of the JWKS private key to use for signing the JWTs when invoking a CDS service endpoint
62
+ requiring authentication.
63
+ Defaults to the first JWK in the list if no kid is supplied.
64
+ DESCRIPTION
65
+ optional: true
66
+ output :cds_services
67
+
68
+ run do
69
+ discovery_url = "#{base_url.chomp('/')}/cds-services"
70
+ headers = { 'Accept' => 'application/json' }
71
+
72
+ if authentication_required == 'yes'
73
+ token = JwtHelper.build(
74
+ aud: discovery_url,
75
+ iss: inferno_base_url,
76
+ jku: "#{inferno_base_url}/jwks.json",
77
+ kid: jwks_kid,
78
+ encryption_method:
79
+ )
80
+ headers['Authorization'] = "Bearer #{token}"
81
+ end
82
+ get(discovery_url, headers:, tags: [DISCOVERY_TAG])
83
+ assert_response_status(200)
84
+ assert_valid_json(request.response_body)
85
+
86
+ output cds_services: request.response_body
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../../server_test_helper'
2
+
3
+ module DaVinciCRDTestKit
4
+ module V221
5
+ class DiscoveryPrefetchSupportTest < Inferno::Test
6
+ include DaVinciCRDTestKit::ServerTestHelper
7
+
8
+ title 'Server advertises prefetch support'
9
+ id :crd_v221_discovery_prefetch_support
10
+ description %(
11
+ This test expects the server to demonstrate support for prefetch queries
12
+ by providing a prefetch query in at least one of the advertised service
13
+ in the discovery response.
14
+ )
15
+
16
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@found-24'
17
+
18
+ input :cds_services
19
+ input :crd_discovery_service_ignore_list,
20
+ optional: true
21
+
22
+ run do
23
+ object = parse_json(cds_services)
24
+ assert object['services'], 'Discovery response did not contain `services`'
25
+
26
+ services = object['services']
27
+ assert services.is_a?(Array), 'Services field of the CDS Discovery response object is not an array.'
28
+
29
+ ignored_service_ids = crd_discovery_service_ignore_list.to_s.split(',').map(&:strip).reject(&:blank?)
30
+ services
31
+ .select { |service| ignored_service_ids.include?(service['id']) }
32
+ .each do |service|
33
+ info "Ignoring service `#{service['id']}` because it is in the ignore list."
34
+ end
35
+ services_for_crd_validation = services.reject { |service| ignored_service_ids.include?(service['id']) }
36
+
37
+ prefetch_supported = services_for_crd_validation.any? { |service| service['prefetch'].present? }
38
+
39
+ skip_if !prefetch_supported, 'No CRD services advertised prefetch support'
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,121 @@
1
+ require_relative '../../server_test_helper'
2
+
3
+ module DaVinciCRDTestKit
4
+ module V221
5
+ class DiscoveryServicesValidationTest < Inferno::Test
6
+ include DaVinciCRDTestKit::ServerTestHelper
7
+
8
+ title 'Discovery response contains valid services'
9
+ id :crd_v221_discovery_services_validation
10
+ description %(
11
+ As per the [CDS Hooks Spec](https://cds-hooks.hl7.org/2.0/#response),
12
+ the response to the discovery endpoint SHALL be an object containing
13
+ a list of CDS services. If your CDS server hosts no CDS services,
14
+ the discovery endpoint should return a 200 HTTP response with
15
+ an empty array of services.
16
+
17
+ Each CDS service must contain the following required fields:
18
+ `hook`, `description`, and `id`.
19
+
20
+ Additionally, the [CRD
21
+ Spec](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/deviations.html#crd-version-declaration)
22
+ states that "CRD servers SHALL declare at least one supported CRD
23
+ version for each supported hook" using the `davinci-crd.version`
24
+ extension.
25
+
26
+ This test checks for the presence of the required fields and
27
+ validates that they are of the correct type.
28
+
29
+ CDS services provided by the server to support use cases outside the
30
+ scope of the CRD specification can be provided in an ignore list input to
31
+ opt-out of CRD validation.
32
+
33
+ The test will be skipped if the server hosts no CRD CDS services.
34
+ )
35
+
36
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@dev-1'
37
+
38
+ input :cds_services
39
+ input :crd_discovery_service_ignore_list,
40
+ title: 'Service ID Ignore List',
41
+ description: %(
42
+ In the case that CDS services advertised on this server support
43
+ use cases outside the scope of the CRD specification, provide a
44
+ comma-separated list of service IDs to opt-out of CRD validation.
45
+ Ignored services will not be stored for use in later tests. If
46
+ blank, all services are checked and saved.
47
+ ),
48
+ optional: true
49
+ output :appointment_book_service_ids, :encounter_start_service_ids, :encounter_discharge_service_ids,
50
+ :order_dispatch_service_ids, :order_select_service_ids, :order_sign_service_ids
51
+
52
+ EXTENSION_KEY = 'davinci-crd.version'.freeze
53
+
54
+ def required_fields
55
+ {
56
+ 'hook' => String,
57
+ 'description' => String,
58
+ 'id' => String,
59
+ 'extension' => Hash
60
+ }
61
+ end
62
+
63
+ run do
64
+ object = parse_json(cds_services)
65
+ assert object['services'], 'Discovery response did not contain `services`'
66
+
67
+ services = object['services']
68
+ assert services.is_a?(Array), 'Services field of the CDS Discovery response object is not an array.'
69
+
70
+ ignored_service_ids = crd_discovery_service_ignore_list.to_s.split(',').map(&:strip).reject(&:blank?)
71
+ services
72
+ .select { |service| ignored_service_ids.include?(service['id']) }
73
+ .each do |service|
74
+ info "Ignoring service `#{service['id']}` because it is in the ignore list."
75
+ end
76
+ services_for_crd_validation = services.reject { |service| ignored_service_ids.include?(service['id']) }
77
+
78
+ service_hooks_to_ids = services_for_crd_validation.each_with_object({}) do |service, hash|
79
+ hash[service['hook']] ||= []
80
+ hash[service['hook']] << service['id'] if service['id']
81
+ end
82
+
83
+ output appointment_book_service_ids: service_hooks_to_ids['appointment-book']&.join(', '),
84
+ encounter_start_service_ids: service_hooks_to_ids['encounter-start']&.join(', '),
85
+ encounter_discharge_service_ids: service_hooks_to_ids['encounter-discharge']&.join(', '),
86
+ order_dispatch_service_ids: service_hooks_to_ids['order-dispatch']&.join(', '),
87
+ order_select_service_ids: service_hooks_to_ids['order-select']&.join(', '),
88
+ order_sign_service_ids: service_hooks_to_ids['order-sign']&.join(', ')
89
+
90
+ skip_if services.empty?, 'Server hosts no CDS Services.'
91
+ skip_if services_for_crd_validation.empty?, 'Ignore list excludes all CDS Services from validation.'
92
+
93
+ services_for_crd_validation.each do |service|
94
+ required_fields.each do |field, type|
95
+ assert(service[field], "Service `#{service['id']}` did not contain required field: `#{field}`")
96
+ assert(service[field].is_a?(type), "Service `#{service['id']}`: field `#{field}` is not of type #{type}")
97
+ end
98
+
99
+ assert service['extension'].key?(EXTENSION_KEY),
100
+ "Service `#{service['id']}`: does not contain a `#{EXTENSION_KEY}` extension"
101
+ assert service['extension'][EXTENSION_KEY].is_a?(Array),
102
+ "Service `#{service['id']}`: `#{EXTENSION_KEY}` extension is not of type Array"
103
+ assert service['extension'][EXTENSION_KEY].present?,
104
+ "Service `#{service['id']}`: `#{EXTENSION_KEY}` extension is empty"
105
+ non_string_values = service['extension'][EXTENSION_KEY].reject { |value| value.is_a? String }
106
+ assert non_string_values.blank?,
107
+ "Service `#{service['id']}`: `#{EXTENSION_KEY}` extension contains non-string values: " \
108
+ "#{non_string_values.join(', ')}"
109
+
110
+ invalid_versions =
111
+ service['extension'][EXTENSION_KEY]
112
+ .reject { |version| version.match?(/\A[1-9]\d*\.\d+\Z/) }
113
+
114
+ assert invalid_versions.blank?,
115
+ "Service `#{service['id']}`: `#{EXTENSION_KEY}` extension contains invalid " \
116
+ "version strings: #{invalid_versions.join(', ')}"
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,166 @@
1
+ require_relative '../../server_test_helper'
2
+
3
+ module DaVinciCRDTestKit
4
+ module V221
5
+ class DiscoveryStandardPrefetchExpressionsTest < Inferno::Test
6
+ include DaVinciCRDTestKit::ServerTestHelper
7
+
8
+ title 'Server uses standard prefetch expressions'
9
+ id :crd_v221_discovery_standard_prefetch_expressions
10
+ description %(
11
+ This test checks each prefetch expression value advertised by CRD services in the discovery
12
+ response against the standard prefetch expressions listed in the CRD IG for the service hook. If a prefetch
13
+ expression does not match one of the standard expressions for that hook, the test will add a warning.
14
+
15
+ These warnings should be checked individually, as the interpretation of the warning will depend on the server's
16
+ intent: For expressions that are intended to capture any of the data elements in that hook's set of
17
+ [standard prefetch queries](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/foundation.html#appointment-book-prefetch),
18
+ it must match the corresponding expression in the IG, and the warning should be considered an error. Note that
19
+ the expression keys do not need to match and are ignored by this test. FHIRPath alternative ordering is also
20
+ ignored by this test.
21
+ For expressions that are meant to capture other data in addition to what is captured by the standard prefetch
22
+ queries, the warning can be ignored.
23
+ )
24
+
25
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@found-29'
26
+
27
+ input :cds_services
28
+ input :crd_discovery_service_ignore_list,
29
+ optional: true
30
+
31
+ ALL_HOOKS = [
32
+ 'appointment-book',
33
+ 'encounter-start',
34
+ 'encounter-discharge',
35
+ 'order-dispatch',
36
+ 'order-select',
37
+ 'order-sign'
38
+ ].freeze
39
+
40
+ def ignored_service_ids
41
+ crd_discovery_service_ignore_list.to_s.split(',').map(&:strip).reject(&:blank?)
42
+ end
43
+
44
+ def services_for_crd_validation(services)
45
+ services
46
+ .select { |service| ignored_service_ids.include?(service['id']) }
47
+ .each do |service|
48
+ info "Ignoring service `#{service['id']}` because it is in the ignore list."
49
+ end
50
+
51
+ services.reject { |service| ignored_service_ids.include?(service['id']) }
52
+ end
53
+
54
+ # rubocop:disable Layout/LineLength
55
+ def standard_prefetch_expressions(hook)
56
+ case hook
57
+ when 'appointment-book'
58
+ {
59
+ 'patient' => 'Patient/{{context.patientId}}',
60
+ 'encounter' => 'Encounter/{{context.encounterId}}',
61
+ 'coverage' => 'Coverage?patient={{context.patientId}}&status=active',
62
+ 'deviceRequests' => "DeviceRequest?_id={{context.appointments.entry.resource.basedOn.extension('http://hl7.org/fhir/StructureDefinition/alternate-reference').value.resolve().ofType(DeviceRequest).id}}",
63
+ 'serviceRequests' => 'ServiceRequest?_id={{context.appointments.entry.resource.basedOn.resolve().ofType(ServiceRequest).id}}',
64
+ 'medicationRequests' => "MedicationRequest?_id={{context.appointments.entry.resource.basedOn.extension('http://hl7.org/fhir/StructureDefinition/alternate-reference').value.resolve().ofType(MedicationRequest).id}}",
65
+ 'devices' => 'Device?_id={{%deviceRequests.entry.resource.code.resolve().id}}',
66
+ 'medications' => 'Medication?_id={{%medicationRequests.entry.resource.medication.resolve().id}}',
67
+ 'practitionerRoles' => 'PractitionerRole?_id={{%encounter.participant.individual.resolve().ofType(PractitionerRole).id|context.appointments.entry.resource.participant.actor.resolve().ofType(PractitionerRole).id|%deviceRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%deviceRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%medicationRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%medicationRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%serviceRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%serviceRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id}}',
68
+ 'practitioners' => 'Practitioner?_id={{%practitionerRoles.entry.resource.practitioner.resolve().id|%encounter.participant.individual.resolve().ofType(Practitioner).id|context.appointments.entry.resource.participant.actor.resolve().ofType(Practitioner).id|%deviceRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%deviceRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%medicationRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%medicationRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%serviceRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%serviceRequests.entry.resource.requester.resolve().ofType(Practitioner).id}}',
69
+ 'organizations' => 'Organization?_id={{%practitionerRoles.entry.resource.organization.resolve().id|%encounter.serviceProvider.resolve().ofType(Organization).id|%medicationRequests.entry.resource.dispenseRequest.performer.resolve().ofType(Organization).id|%serviceRequests.entry.resource.performer.resolve().ofType(Organization).id}}',
70
+ 'locations' => 'Location?_id={{%practitionerRoles.entry.resource.location.resolve().id|%encounter.location.location.resolve().id|context.appointments.entry.resource.participant.actor.resolve().ofType(Location).id|%serviceRequests.entry.resource.locationReference.resolve().ofType(Location).id}}'
71
+ }
72
+ when 'encounter-start', 'encounter-discharge'
73
+ {
74
+ 'patient' => 'Patient/{{context.patientId}}',
75
+ 'encounter' => 'Encounter/{{context.encounterId}}',
76
+ 'coverage' => 'Coverage?patient={{context.patientId}}&status=active',
77
+ 'practitionerRoles' => 'PractitionerRole?_id={{%encounter.participant.individual.resolve().ofType(PractitionerRole).id}}',
78
+ 'practitioners' => 'Practitioner?_id={{%practitionerRoles.entry.resource.practitioner.resolve().id|%encounter.participant.individual.resolve().ofType(Practitioner).id}}',
79
+ 'organizations' => 'Organization?_id={{%practitionerRoles.entry.resource.organization.resolve().id|%encounter.serviceProvider.resolve().ofType(Organization).id}}',
80
+ 'locations' => 'Location?_id={{%practitionerRoles.entry.resource.location.resolve().id|%encounter.location.location.resolve().id}}'
81
+ }
82
+ when 'order-dispatch'
83
+ {
84
+ 'patient' => 'Patient/{{context.patientId}}',
85
+ 'encounter' => 'Encounter/{{context.encounterId}}',
86
+ 'coverage' => 'Coverage?patient={{context.patientId}}&status=active',
87
+ 'communicationRequests' => 'CommunicationRequest?_id={{context.dispatchedOrders.resolve().ofType(CommunicationRequest).id}}',
88
+ 'deviceRequests' => 'DeviceRequest?_id={{context.dispatchedOrders.resolve().ofType(DeviceRequest).id}}',
89
+ 'medicationRequests' => 'MedicationRequest?_id={{context.dispatchedOrders.resolve().ofType(MedicationRequest).id}}',
90
+ 'nutritionOrders' => 'NutritionOrder?_id={{context.dispatchedOrders.resolve().ofType(NutritionOrder).id}}',
91
+ 'serviceRequests' => 'ServiceRequest?_id={{context.dispatchedOrders.resolve().ofType(ServiceRequest).id}}',
92
+ 'visionPrescriptions' => 'VisionPrescription?_id={{context.dispatchedOrders.resolve().ofType(VisionPrescription).id}}',
93
+ 'devices' => 'Device?_id={{%deviceRequests.entry.resource.code.resolve().id}}',
94
+ 'medications' => 'Medication?_id={{%medicationRequests.entry.resource.medication.resolve().id}}',
95
+ 'practitionerRoles' => 'PractitionerRole?_id={{%encounter.participant.individual.resolve().ofType(PractitionerRole).id|%communicationRequests.entry.resource.sender.resolve().ofType(PractitionerRole).id|%communicationRequests.entry.resource.recipient.resolve().ofType(PractitionerRole).id|%communicationRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%deviceRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%deviceRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%medicationRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%medicationRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%serviceRequests.entry.resource.performer.resolve().ofType(PractitionerRole).id|%serviceRequests.entry.resource.requester.resolve().ofType(PractitionerRole).id|%nutritionOrders.entry.resource.orderer.resolve().ofType(PractitionerRole).id|%visionPrescriptions.entry.resource.prescriber.resolve().ofType(PractitionerRole).id}}',
96
+ 'practitioners' => 'Practitioner?_id={{%practitionerRoles.entry.resource.practitioner.resolve().id|%encounter.participant.individual.resolve().ofType(Practitioner).id|%communicationRequests.entry.resource.sender.resolve().ofType(Practitioner).id|%communicationRequests.entry.resource.recipient.resolve().ofType(Practitioner).id|%communicationRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%deviceRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%deviceRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%medicationRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%medicationRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%serviceRequests.entry.resource.performer.resolve().ofType(Practitioner).id|%serviceRequests.entry.resource.requester.resolve().ofType(Practitioner).id|%nutritionOrders.entry.resource.orderer.resolve().ofType(Practitioner).id|%visionPrescriptions.entry.resource.prescriber.resolve().ofType(Practitioner).id}}',
97
+ 'organizations' => 'Organization?_id={{%practitionerRoles.entry.resource.organization.resolve().id|%encounter.serviceProvider.resolve().ofType(Organization).id|%communicationRequests.entry.resource.recipient.resolve().ofType(Organization).id|%communicationRequests.entry.resource.sender.resolve().ofType(Organization).id|%medicationRequests.entry.resource.dispenseRequest.performer.resolve().id|%serviceRequests.entry.resource.performer.resolve().ofType(Organization).id}}',
98
+ 'locations' => 'Location?_id={{%practitionerRoles.entry.resource.location.resolve().id|%encounter.location.location.resolve().id|%serviceRequests.entry.resource.locationReference.resolve().id}}'
99
+ }
100
+ when 'order-select', 'order-sign'
101
+ {
102
+ 'patient' => 'Patient/{{context.patientId}}',
103
+ 'encounter' => 'Encounter/{{context.encounterId}}',
104
+ 'coverage' => 'Coverage?patient={{context.patientId}}&status=active',
105
+ 'devices' => 'Device?_id={{context.draftOrders.entry.resource.ofType(DeviceRequest).code.resolve().id}}',
106
+ 'medications' => 'Medication?_id={{context.draftOrders.entry.resource.ofType(MedicationRequest).medication.resolve().id}}',
107
+ 'practitionerRoles' => 'PractitionerRole?_id={{%encounter.participant.individual.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.sender.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.recipient.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.requester.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.performer.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.orderer.resolve().ofType(PractitionerRole).id|context.draftOrders.entry.resource.prescriber.resolve().ofType(PractitionerRole).id}}',
108
+ 'practitioners' => 'Practitioner?_id={{%practitionerRoles.entry.resource.practitioner.resolve().id|%encounter.participant.individual.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.sender.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.recipient.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.requester.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.performer.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.orderer.resolve().ofType(Practitioner).id|context.draftOrders.entry.resource.prescriber.resolve().ofType(Practitioner).id}}',
109
+ 'organizations' => 'Organization?_id={{%practitionerRoles.entry.resource.organization.resolve().id|%encounter.serviceProvider.resolve().ofType(Organization).id|context.draftOrders.entry.resource.dispenseRequest.performer.resolve().id|context.draftOrders.entry.resource.sender.resolve().ofType(Organization).id|context.draftOrders.entry.resource.recipient.resolve().ofType(Organization).id|context.draftOrders.entry.resource.performer.resolve().ofType(Organization).id}}',
110
+ 'locations' => 'Location?_id={{%practitionerRoles.entry.resource.location.resolve().id|%encounter.location.location.resolve().id|context.draftOrders.entry.resource.locationReference.resolve().id}}'
111
+ }
112
+ end
113
+ end
114
+ # rubocop:enable Layout/LineLength
115
+
116
+ # The IG examples contain FHIRPath alternatives separated by `|`, and CDS Hooks prefetch field names can vary.
117
+ # Build a canonical signature so alternative ordering and `%prefetchKey` names do not affect matching.
118
+ def expression_signature(expression)
119
+ expression = expression.to_s
120
+ # CRD's standard expressions use one `{{...}}` token; split that token into its surrounding request string.
121
+ match = expression.match(/\A(.*?)\{\{(.*)\}\}(.*)\z/)
122
+ return expression unless match
123
+
124
+ prefix, fhirpath_expression, suffix = match.captures
125
+ alternatives =
126
+ fhirpath_expression
127
+ .split('|')
128
+ .map { |alternative| alternative.gsub(/%[A-Za-z][A-Za-z0-9_-]*/, '%prefetch') }
129
+ .uniq
130
+ .sort
131
+
132
+ [prefix, alternatives, suffix]
133
+ end
134
+
135
+ run do
136
+ object = parse_json(cds_services)
137
+ assert object['services'], 'Discovery response did not contain `services`'
138
+
139
+ services = object['services']
140
+ assert services.is_a?(Array), 'Services field of the CDS Discovery response object is not an array.'
141
+
142
+ prefetch_services =
143
+ services_for_crd_validation(services)
144
+ .select { |service| service['prefetch'].is_a?(Hash) && service['prefetch'].present? }
145
+
146
+ skip_if prefetch_services.blank?, 'No CRD services advertised prefetch support'
147
+
148
+ prefetch_services.each do |service|
149
+ next unless ALL_HOOKS.include?(service['hook'])
150
+
151
+ standard_expression_signatures =
152
+ standard_prefetch_expressions(service['hook']).values.map { |expression| expression_signature(expression) }
153
+
154
+ service['prefetch'].each do |prefetch_key, prefetch_value|
155
+ next if standard_expression_signatures.include?(expression_signature(prefetch_value))
156
+
157
+ msg = "Service `#{service['id']}` advertises prefetch expression `#{prefetch_value}` " \
158
+ "for hook `#{service['hook']}` in prefetch field `#{prefetch_key}`, which does not match " \
159
+ 'one of the standard CRD prefetch expressions for that hook.'
160
+ add_message('warning', msg)
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../server_urls'
2
+ require_relative '../../jobs/invoke_hook_no_special_requests'
3
+ require_relative '../../server_abstract_invoke_hook_test'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class InvokeHookSingleTest < ServerAbstractInvokeHookTest
8
+ include ServerURLs
9
+
10
+ title 'Inferno invokes the selected hook with the provided request body'
11
+ id :crd_v221_server_invoke_hook_single_request_test
12
+
13
+ def perform_invoke_hook_job(*)
14
+ Inferno::Jobs.perform(DaVinciCRDTestKit::Jobs::InvokeHookNoSpecialRequests, *)
15
+ end
16
+
17
+ def check_request_length(payloads)
18
+ skip_if payloads.length != 1, 'This test supports only one request body.'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../server_urls'
2
+ require_relative '../../server_abstract_invoke_hook_test'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class ServerInvokeHookTest < ServerAbstractInvokeHookTest
7
+ include ServerURLs
8
+
9
+ title 'Inferno invokes the selected hook'
10
+ id :crd_v221_server_invoke_hook_test
11
+
12
+ def coverage_info_configuration_supported?
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end