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,130 @@
1
+ require_relative '../../server_hook_request_validation'
2
+ require_relative '../../server_test_helper'
3
+ require_relative '../../server_hook_helper'
4
+ require_relative '../../../cross_suite/cards_identification'
5
+ require_relative '../../../cross_suite/response_logical_model_validation'
6
+ require_relative 'hook_request_resource_resolution'
7
+
8
+ module DaVinciCRDTestKit
9
+ module V221
10
+ class CoverageInformationSystemActionValidationTest < Inferno::Test
11
+ include DaVinciCRDTestKit::ServerHookRequestValidation
12
+ include DaVinciCRDTestKit::ServerTestHelper
13
+ include DaVinciCRDTestKit::ServerHookHelper
14
+ include HookRequestResourceResolution
15
+ include DaVinciCRDTestKit::CardsIdentification
16
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
17
+
18
+ COVERAGE_INFO_EXT_URL = 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'.freeze
19
+
20
+ title 'Coverage Information system actions are valid'
21
+ id :crd_v221_coverage_info_system_action_validation
22
+ description %(
23
+ This test validates all [Coverage
24
+ Information](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#coverage-information-response-type)
25
+ system actions received. It verifies the following for each action:
26
+ - The action type is `update`.
27
+ - The resource within the action conforms its respective FHIR profile.
28
+ - The resource does not change any data elements other than adding or
29
+ modifying the `coverage-information` extension.
30
+
31
+ Additionally, the test examines the `coverage-info` extensions within
32
+ the resource to ensure that:
33
+ - Entries referencing differing coverage have distinct
34
+ `coverage-assertion-ids` and `satisfied-pa-ids` (if present).
35
+ - Entries referencing the same coverage have the same
36
+ `coverage-assertion-ids` and `satisfied-pa-ids` (if present).
37
+ )
38
+
39
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-26',
40
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-32',
41
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-37',
42
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-47',
43
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-48',
44
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-52'
45
+
46
+ input :invoked_hook
47
+ input :mock_ehr_bundle, optional: true
48
+ output :coverage_info
49
+
50
+ def verify_only_coverage_info_changed(action, request)
51
+ source_resource = find_action_source_resource(action, request)
52
+ updated_resource_hash = action['resource']
53
+ resource_ref = "#{updated_resource_hash['resourceType']}/#{updated_resource_hash['id']}"
54
+ unless source_resource
55
+ messages << {
56
+ type: 'warning',
57
+ message: 'Inferno could not resolve the original source resource for Coverage Information systemAction ' \
58
+ "targeting #{resource_ref}, so it could not verify that only coverage-information extensions " \
59
+ 'were changed.'
60
+ }
61
+ return
62
+ end
63
+
64
+ return if only_coverage_information_changed?(source_resource.to_hash, updated_resource_hash)
65
+
66
+ add_message(
67
+ 'error',
68
+ "#{resource_ref}: resource content changed outside the coverage-information extension."
69
+ )
70
+ end
71
+
72
+ def body_has_no_system_actions?(body)
73
+ !body.is_a?(Hash) ||
74
+ body['systemActions'].blank? ||
75
+ !body['systemActions'].is_a?(Array) ||
76
+ !body['systemActions'].all?(Hash)
77
+ end
78
+
79
+ def coverage_info_actions(request)
80
+ return [] if request.status != 200
81
+
82
+ response_body = JSON.parse(request.response_body)
83
+
84
+ return [] if body_has_no_system_actions?(response_body)
85
+
86
+ response_body['systemActions'].select { |action| coverage_information_response_type? action }
87
+ rescue JSON::ParserError
88
+ []
89
+ end
90
+
91
+ run do
92
+ load_tagged_requests(tested_hook_name)
93
+
94
+ all_coverage_info_actions = []
95
+ coverage_info_count = 0
96
+
97
+ successful_requests = requests.select { |request| request.status == 200 }
98
+
99
+ skip_if successful_requests.blank?,
100
+ 'No successful hook responses were received'
101
+
102
+ requests.each_with_index do |request, index|
103
+ actions = coverage_info_actions(request)
104
+
105
+ coverage_info_count += actions.length
106
+
107
+ perform_response_logical_model_validation(
108
+ nil,
109
+ actions,
110
+ request.request_body,
111
+ index,
112
+ '2.2.1'
113
+ )
114
+ actions.each { |action| verify_only_coverage_info_changed(action, request) }
115
+
116
+ all_coverage_info_actions.concat(actions)
117
+ end
118
+
119
+ skip_if coverage_info_count.zero?,
120
+ "#{tested_hook_name} hook responses do not contain any Coverage Information system actions."
121
+
122
+ output coverage_info: all_coverage_info_actions.to_json
123
+
124
+ no_error_validation(
125
+ 'Not all Coverage Information system actions were valid. See messages for more information.'
126
+ )
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,119 @@
1
+ require_relative '../../server_test_helper'
2
+ require_relative '../../server_hook_helper'
3
+ require_relative '../../../cross_suite/cards_identification'
4
+ require_relative '../../../cross_suite/response_logical_model_validation'
5
+
6
+ module DaVinciCRDTestKit
7
+ module V221
8
+ class CreateOrUpdateCoverageInfoResponseValidationTest < Inferno::Test
9
+ include DaVinciCRDTestKit::ServerTestHelper
10
+ include DaVinciCRDTestKit::ServerHookHelper
11
+ include DaVinciCRDTestKit::CardsIdentification
12
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
13
+
14
+ title 'Create or Update Coverage Information cards and system actions are valid'
15
+ id :crd_v221_create_or_update_coverage_info_response_validation
16
+ description %(
17
+ This test validates the Create or Update Coverage Information cards or
18
+ system actions received from the CRD service, as per the specifications
19
+ outlined in the [Da Vinci CRD Implementation
20
+ Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#update-coverage-records-response-type).
21
+
22
+ - **Checking for Presence:**
23
+ The test first checks if any Create or Update Coverage Information
24
+ cards or system actions are present in the returned valid cards or
25
+ valid system actions.
26
+ - **For cards**: it ensures there are cards with a `suggestions` array
27
+ containing a single suggestion, and the `actions` array of that
28
+ suggestion has one `create` or `update` action for the `Coverage`
29
+ resource.
30
+ - **For system actions**: it checks for the presence of `create` or
31
+ `update` actions for the `Coverage` resource.
32
+
33
+ - **Validating:**
34
+ If any Create or Update Coverage Information cards or system actions
35
+ are found, each `Coverage` resource is validated against the base FHIR
36
+ Coverage resource.
37
+
38
+ If no Create or Update Coverage Information cards or system actions
39
+ are received, the test is skipped.
40
+ )
41
+
42
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
43
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-71'
44
+
45
+ input :invoked_hook
46
+
47
+ optional
48
+
49
+ def body_has_no_cards?(body)
50
+ !body.is_a?(Hash) ||
51
+ body['cards'].blank? ||
52
+ !body['cards'].is_a?(Array) ||
53
+ !body['cards'].all?(Hash)
54
+ end
55
+
56
+ def update_coverage_cards(request)
57
+ return [] if request.status != 200
58
+
59
+ response_body = JSON.parse(request.response_body)
60
+
61
+ return [] if body_has_no_cards?(response_body)
62
+
63
+ response_body['cards'].select { |card| create_or_update_coverage_card_response_type? card }
64
+ rescue JSON::ParserError
65
+ []
66
+ end
67
+
68
+ def body_has_no_system_actions?(body)
69
+ !body.is_a?(Hash) ||
70
+ body['systemActions'].blank? ||
71
+ !body['systemActions'].is_a?(Array) ||
72
+ !body['systemActions'].all?(Hash)
73
+ end
74
+
75
+ def update_coverage_actions(request)
76
+ return [] if request.status != 200
77
+
78
+ response_body = JSON.parse(request.response_body)
79
+
80
+ return [] if body_has_no_system_actions?(response_body)
81
+
82
+ response_body['systemActions'].select { |action| create_or_update_coverage_action_response_type? action }
83
+ rescue JSON::ParserError
84
+ []
85
+ end
86
+
87
+ run do
88
+ load_tagged_requests(tested_hook_name)
89
+
90
+ update_coverage_count = 0
91
+
92
+ successful_requests = requests.select { |request| request.status == 200 }
93
+
94
+ skip_if successful_requests.blank?,
95
+ 'No successful hook responses were received'
96
+
97
+ requests.each_with_index do |request, index|
98
+ cards = update_coverage_cards(request)
99
+ actions = update_coverage_actions(request)
100
+
101
+ update_coverage_count += cards.length + actions.length
102
+
103
+ perform_response_logical_model_validation(
104
+ cards,
105
+ actions,
106
+ request.request_body,
107
+ index,
108
+ '2.2.1'
109
+ )
110
+ end
111
+
112
+ skip_if update_coverage_count.zero?,
113
+ "#{tested_hook_name} hook responses do not contain any Update Coverage Records cards or system actions."
114
+
115
+ no_error_validation('Not all Update Coverage Records responses were valid. See messages for more information.')
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,89 @@
1
+ require_relative '../../server_test_helper'
2
+ require_relative '../../server_hook_helper'
3
+ require_relative '../../../cross_suite/cards_identification'
4
+ require_relative '../../../cross_suite/response_logical_model_validation'
5
+
6
+ module DaVinciCRDTestKit
7
+ module V221
8
+ class ExternalReferenceCardValidationTest < Inferno::Test
9
+ include DaVinciCRDTestKit::ServerTestHelper
10
+ include DaVinciCRDTestKit::ServerHookHelper
11
+ include DaVinciCRDTestKit::CardsIdentification
12
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
13
+
14
+ title 'External Reference cards are valid'
15
+ id :crd_v221_external_reference_card_validation
16
+ description %(
17
+ This test verifies the presence of valid External Reference cards within
18
+ the CRD service responses.
19
+
20
+ As per the [Da Vinci CRD Implementation
21
+ Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#external-reference-response-type),
22
+ External Reference cards must contain links with the type set to
23
+ `absolute`. This test checks for the presence of any External Reference
24
+ cards by verifying:
25
+ - The presence of a `links` array within each card.
26
+ - That every link in the `links` array of a card is of type `absolute`.
27
+
28
+ The test will be skipped if no External Reference cards are found within
29
+ the returned valid cards.
30
+ )
31
+
32
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-19',
33
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-22'
34
+
35
+ input :invoked_hook
36
+
37
+ optional
38
+
39
+ def body_has_no_cards?(body)
40
+ !body.is_a?(Hash) ||
41
+ body['cards'].blank? ||
42
+ !body['cards'].is_a?(Array) ||
43
+ !body['cards'].all?(Hash)
44
+ end
45
+
46
+ def external_reference_cards(request)
47
+ return [] if request.status != 200
48
+
49
+ response_body = JSON.parse(request.response_body)
50
+
51
+ return [] if body_has_no_cards?(response_body)
52
+
53
+ response_body['cards'].select { |card| external_reference_response_type? card }
54
+ rescue JSON::ParserError
55
+ []
56
+ end
57
+
58
+ run do
59
+ load_tagged_requests(tested_hook_name)
60
+
61
+ external_reference_count = 0
62
+
63
+ successful_requests = requests.select { |request| request.status == 200 }
64
+
65
+ skip_if successful_requests.blank?,
66
+ 'No successful hook responses were received'
67
+
68
+ requests.each_with_index do |request, index|
69
+ cards = external_reference_cards(request)
70
+
71
+ external_reference_count += cards.length
72
+
73
+ perform_response_logical_model_validation(
74
+ cards,
75
+ nil,
76
+ request.request_body,
77
+ index,
78
+ '2.2.1'
79
+ )
80
+ end
81
+
82
+ skip_if external_reference_count.zero?,
83
+ "#{tested_hook_name} hook responses do not contain any External Reference cards."
84
+
85
+ no_error_validation('Not all External Reference cards were valid. See messages for more information.')
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,126 @@
1
+ require_relative '../../server_test_helper'
2
+ require_relative '../../server_hook_helper'
3
+ require_relative '../../../cross_suite/cards_identification'
4
+ require_relative '../../../cross_suite/response_logical_model_validation'
5
+
6
+ module DaVinciCRDTestKit
7
+ module V221
8
+ class FormCompletionResponseValidationTest < Inferno::Test
9
+ include DaVinciCRDTestKit::ServerTestHelper
10
+ include DaVinciCRDTestKit::ServerHookHelper
11
+ include DaVinciCRDTestKit::CardsIdentification
12
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
13
+
14
+ title 'Request Form Completion cards and system actions are valid'
15
+ id :crd_v221_request_form_completion_response_validation
16
+ description %(
17
+ This test validates the Request Form Completion cards or system actions
18
+ received from the CRD service, as per the specifications outlined in the
19
+ [Da Vinci CRD Implementation
20
+ Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#request-form-completion-response-type).
21
+
22
+ - **Checking for Presence:**
23
+ The test begins by verifying whether any Request Form Completion cards
24
+ or system actions are present.
25
+ - **For cards:** It ensures that there are cards with `suggestions`
26
+ containing `create` actions for the `Task` resource, specifically:
27
+ - The `Task` must have a `code` of `complete-questionnaire`.
28
+ - The `Task` should include an input of type `text`
29
+ (`Task.input.type.text`) labeled as `questionnaire` and associated
30
+ with a valid canonical URL (`Task.input.valueCanonical`).
31
+ - **For system actions:** It checks for the presence of `create`
32
+ actions for the `Task` resource with the characteristics described
33
+ above.
34
+
35
+ - **Validating:**
36
+ If any Request Form Completion cards or system actions are found, the
37
+ test proceeds to validate them. Each `Task` resource is validated
38
+ against the [CRD Questionnaire Task
39
+ profile](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-profile-taskquestionnaire.html).
40
+ Additionally, if any actions for the creation of a `Questionnaire` are
41
+ found, the test verifies that they include the
42
+ `davinci-crd.if-none-exist` extension.
43
+
44
+ If no Request Form Completion cards or system actions are received, the test is skipped.
45
+ )
46
+
47
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@dev-20',
48
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
49
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-62',
50
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-65'
51
+
52
+ input :invoked_hook
53
+
54
+ optional
55
+
56
+ def body_has_no_cards?(body)
57
+ !body.is_a?(Hash) ||
58
+ body['cards'].blank? ||
59
+ !body['cards'].is_a?(Array) ||
60
+ !body['cards'].all?(Hash)
61
+ end
62
+
63
+ def form_completion_cards(request)
64
+ return [] if request.status != 200
65
+
66
+ response_body = JSON.parse(request.response_body)
67
+
68
+ return [] if body_has_no_cards?(response_body)
69
+
70
+ response_body['cards'].select { |card| form_completion_card_response_type? card }
71
+ rescue JSON::ParserError
72
+ []
73
+ end
74
+
75
+ def body_has_no_system_actions?(body)
76
+ !body.is_a?(Hash) ||
77
+ body['systemActions'].blank? ||
78
+ !body['systemActions'].is_a?(Array) ||
79
+ !body['systemActions'].all?(Hash)
80
+ end
81
+
82
+ def form_completion_actions(request)
83
+ return [] if request.status != 200
84
+
85
+ response_body = JSON.parse(request.response_body)
86
+
87
+ return [] if body_has_no_system_actions?(response_body)
88
+
89
+ response_body['systemActions'].select { |action| form_completion_action_response_type? action }
90
+ rescue JSON::ParserError
91
+ []
92
+ end
93
+
94
+ run do
95
+ load_tagged_requests(tested_hook_name)
96
+
97
+ form_completion_count = 0
98
+
99
+ successful_requests = requests.select { |request| request.status == 200 }
100
+
101
+ skip_if successful_requests.blank?,
102
+ 'No successful hook responses were received'
103
+
104
+ requests.each_with_index do |request, index|
105
+ cards = form_completion_cards(request)
106
+ actions = form_completion_actions(request)
107
+
108
+ form_completion_count += cards.length + actions.length
109
+
110
+ perform_response_logical_model_validation(
111
+ cards,
112
+ actions,
113
+ request.request_body,
114
+ index,
115
+ '2.2.1'
116
+ )
117
+ end
118
+
119
+ skip_if form_completion_count.zero?,
120
+ "#{tested_hook_name} hook responses do not contain any Request Form Completion cards or system actions."
121
+
122
+ no_error_validation('Not all Request Form Completion responses were valid. See messages for more information.')
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,174 @@
1
+ module DaVinciCRDTestKit
2
+ module V221
3
+ module HookRequestResourceResolution
4
+ def mock_ehr_bundle_resource
5
+ @mock_ehr_bundle_resource ||= JSON.parse(mock_ehr_bundle) if mock_ehr_bundle.present?
6
+ rescue JSON::ParserError
7
+ nil
8
+ end
9
+
10
+ def matching_request_for_action(action)
11
+ requests.find do |request|
12
+ response = JSON.parse(request.response_body)
13
+ request.status == 200 && Array(response['systemActions']).any? { |candidate| candidate == action }
14
+ rescue JSON::ParserError
15
+ false
16
+ end
17
+ end
18
+
19
+ # Resolve the original resource being updated by a systemAction.
20
+ # - appointment-book: look in context.appointments; if the action targets a ServiceRequest,
21
+ # follow the Appointment basedOn reference and resolve that from prefetch or mock EHR data
22
+ # - order-sign/order-select: look in context.draftOrders
23
+ # - other hooks: resolve from prefetch or mock EHR data because context may carry only ids/references
24
+ def find_action_source_resource(action, request)
25
+ action_resource = action['resource']
26
+ return unless action_resource.is_a?(Hash)
27
+
28
+ target_type = action_resource['resourceType']
29
+ target_id = action_resource['id']
30
+ request_body = parse_request_body(request)
31
+ return unless target_type.present? && target_id.present? && request_body
32
+
33
+ hook_context_resource(request_body, target_type, target_id) ||
34
+ fallback_source_resource(request_body, target_type, target_id)
35
+ end
36
+
37
+ def only_coverage_information_changed?(source_resource_hash, updated_resource_hash)
38
+ return true if coverage_information_extension_only_payload?(updated_resource_hash)
39
+
40
+ source_without_coverage_info = normalize_value(strip_coverage_info_extensions(source_resource_hash))
41
+ updated_without_coverage_info = normalize_value(strip_coverage_info_extensions(updated_resource_hash))
42
+
43
+ source_without_coverage_info == updated_without_coverage_info
44
+ end
45
+
46
+ def coverage_information_extension_only_payload?(resource_hash)
47
+ return false unless resource_hash.is_a?(Hash)
48
+
49
+ strip_coverage_info_extensions(resource_hash).keys.all? { |key| ['resourceType', 'id', 'meta'].include?(key) }
50
+ end
51
+
52
+ def strip_coverage_info_extensions(resource_hash)
53
+ normalized_hash = resource_hash.deep_dup
54
+ return normalized_hash unless normalized_hash['extension'].is_a?(Array)
55
+
56
+ normalized_hash['extension'] = normalized_hash['extension'].reject do |extension|
57
+ extension['url'] == DaVinciCRDTestKit::CardsIdentification::COVERAGE_INFO_EXT_URL
58
+ end
59
+ normalized_hash.delete('extension') if normalized_hash['extension'].empty?
60
+ normalized_hash
61
+ end
62
+
63
+ def normalize_value(value)
64
+ case value
65
+ when Hash
66
+ value.transform_values { |child| normalize_value(child) }
67
+ when Array
68
+ value.map { |child| normalize_value(child) }.sort_by(&:to_json)
69
+ else
70
+ value
71
+ end
72
+ end
73
+
74
+ def find_appointment_book_resource(request_body, target_type, target_id)
75
+ appointments_bundle = request_body.dig('context', 'appointments')
76
+ find_resource_in_bundle(appointments_bundle, target_type, target_id) ||
77
+ appointment_book_service_request(request_body, appointments_bundle, target_id)
78
+ end
79
+
80
+ def find_draft_orders_resource(request_body, target_type, target_id)
81
+ draft_orders_bundle = request_body.dig('context', 'draftOrders')
82
+ find_resource_in_bundle(draft_orders_bundle, target_type, target_id)
83
+ end
84
+
85
+ def fallback_source_resource(request_body, target_type, target_id)
86
+ find_resource_in_prefetch(request_body, target_type, target_id) ||
87
+ find_resource_in_bundle(mock_ehr_bundle_resource, target_type, target_id)
88
+ end
89
+
90
+ def hook_context_resource(request_body, target_type, target_id)
91
+ case tested_hook_name
92
+ when 'appointment-book'
93
+ find_appointment_book_resource(request_body, target_type, target_id)
94
+ when 'order-sign', 'order-select'
95
+ find_draft_orders_resource(request_body, target_type, target_id)
96
+ end
97
+ end
98
+
99
+ def appointment_book_service_request(request_body, appointments_bundle_hash, target_id)
100
+ target_type = 'ServiceRequest'
101
+ appointments_bundle = parse_bundle(appointments_bundle_hash)
102
+ appointment = (appointments_bundle&.entry || [])
103
+ .filter_map(&:resource)
104
+ .find { |candidate| appointment_based_on_matches_target?(candidate, target_type, target_id) }
105
+ return unless appointment
106
+
107
+ find_resource_in_prefetch(request_body, target_type, target_id) ||
108
+ find_resource_in_bundle(mock_ehr_bundle_resource, target_type, target_id)
109
+ end
110
+
111
+ def appointment_based_on_matches_target?(appointment, target_type, target_id)
112
+ Array(appointment.basedOn).any? do |reference|
113
+ reference_parts(reference.reference) == [target_type, target_id]
114
+ end
115
+ end
116
+
117
+ def find_resource_in_prefetch(request_body, target_type, target_id)
118
+ Array(request_body['prefetch']&.values).each do |prefetched_value|
119
+ if prefetched_value.is_a?(Hash) &&
120
+ prefetched_value['resourceType'] == target_type &&
121
+ prefetched_value['id'] == target_id
122
+ return FHIR.from_contents(prefetched_value.to_json)
123
+ end
124
+
125
+ resource = find_resource_in_bundle(prefetched_value, target_type, target_id)
126
+ return resource if resource
127
+ end
128
+
129
+ nil
130
+ end
131
+
132
+ def find_resource_by_reference(request_body, reference)
133
+ target_type, target_id = reference_parts(reference)
134
+ return unless target_type.present? && target_id.present?
135
+
136
+ find_resource_in_prefetch(request_body, target_type, target_id) ||
137
+ find_resource_in_bundle(mock_ehr_bundle_resource, target_type, target_id)
138
+ end
139
+
140
+ def find_resource_in_bundle(bundle_hash, target_type, target_id)
141
+ bundle = parse_bundle(bundle_hash)
142
+ return unless bundle&.entry
143
+
144
+ bundle.entry
145
+ .filter_map(&:resource)
146
+ .find { |resource| resource.resourceType == target_type && resource.id == target_id }
147
+ end
148
+
149
+ def reference_parts(reference)
150
+ return if reference.blank?
151
+
152
+ parts = reference.split('/')
153
+ return unless parts.length >= 2
154
+
155
+ [parts[-2], parts[-1]]
156
+ end
157
+
158
+ def parse_bundle(bundle_hash)
159
+ bundle = FHIR.from_contents(bundle_hash.to_json)
160
+ bundle if bundle.is_a?(FHIR::Bundle)
161
+ rescue StandardError
162
+ nil
163
+ end
164
+
165
+ def parse_request_body(request)
166
+ return unless request&.request_body.present?
167
+
168
+ JSON.parse(request.request_body)
169
+ rescue JSON::ParserError
170
+ nil
171
+ end
172
+ end
173
+ end
174
+ end