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,321 @@
1
+ require_relative 'hook_request_field_validation'
2
+ require_relative 'suggestion_actions_validation'
3
+
4
+ module DaVinciCRDTestKit
5
+ module CardsIdentification
6
+ include DaVinciCRDTestKit::SuggestionActionsValidation
7
+ include DaVinciCRDTestKit::HookRequestFieldValidation
8
+
9
+ COVERAGE_INFO_EXT_URL = 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'.freeze
10
+
11
+ ADDITIONAL_ORDERS_RESPONSE_TYPE = 'companions_prerequisites'.freeze
12
+ COVERAGE_INFORMATION_RESPONSE_TYPE = 'coverage_information'.freeze
13
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE = 'create_update_coverage_info'.freeze
14
+ EXTERNAL_REFERENCE_RESPONSE_TYPE = 'external_reference'.freeze
15
+ FORM_COMPLETION_RESPONSE_TYPE = 'request_form_completion'.freeze
16
+ INSTRUCTIONS_RESPONSE_TYPE = 'instructions'.freeze
17
+ LAUNCH_SMART_APP_RESPONSE_TYPE = 'launch_smart_app'.freeze
18
+ PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE = 'propose_alternate_request'.freeze
19
+ COVERAGE_INFO_CONFIGURATION_CODE = 'coverage-info'.freeze
20
+
21
+ ADDITIONAL_ORDERS_EXPECTED_RESOURCE_TYPES = %w[
22
+ CommunicationRequest Device DeviceRequest Medication
23
+ MedicationRequest NutritionOrder ServiceRequest
24
+ VisionPrescription
25
+ ].freeze
26
+
27
+ PROPOSE_ALTERNATIVE_REQUEST_EXPECTED_RESOURCE_TYPES = %w[
28
+ CommunicationRequest Device DeviceRequest Encounter Medication
29
+ MedicationRequest NutritionOrder ServiceRequest
30
+ VisionPrescription
31
+ ].freeze
32
+
33
+ COVERAGE_INFO_EXPECTED_RESOURCE_TYPES = %w[
34
+ Appointment CommunicationRequest DeviceRequest Encounter MedicationRequest
35
+ NutritionOrder ServiceRequest VisionPrescription
36
+ ].freeze
37
+
38
+ def identify_card_type(card) # rubocop:disable Metrics/CyclomaticComplexity
39
+ return nil if card['type'].present? # action, not a card
40
+ return ADDITIONAL_ORDERS_RESPONSE_TYPE if additional_orders_response_type?(card)
41
+ return CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE if create_or_update_coverage_card_response_type?(card)
42
+ return EXTERNAL_REFERENCE_RESPONSE_TYPE if external_reference_response_type?(card)
43
+ return FORM_COMPLETION_RESPONSE_TYPE if form_completion_card_response_type?(card)
44
+ return INSTRUCTIONS_RESPONSE_TYPE if instructions_response_type?(card)
45
+ return LAUNCH_SMART_APP_RESPONSE_TYPE if launch_smart_app_response_type?(card)
46
+ return PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE if propose_alternative_request_response_type?(card)
47
+
48
+ nil
49
+ end
50
+
51
+ def identify_action_type(action)
52
+ return nil unless action['type'].present? # card, not an action
53
+ return COVERAGE_INFORMATION_RESPONSE_TYPE if coverage_information_response_type?(action)
54
+ return CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE if create_or_update_coverage_action_response_type?(action)
55
+ return FORM_COMPLETION_RESPONSE_TYPE if form_completion_action_response_type?(action)
56
+
57
+ nil
58
+ end
59
+
60
+ def coverage_info_card_type?(card)
61
+ return false unless card.respond_to?(:dig)
62
+
63
+ card.dig('source', 'topic', 'code') == COVERAGE_INFO_CONFIGURATION_CODE
64
+ end
65
+
66
+ def coverage_info_system_action_type?(action)
67
+ return false unless action.respond_to?(:[])
68
+
69
+ [COVERAGE_INFORMATION_RESPONSE_TYPE, FORM_COMPLETION_RESPONSE_TYPE].include?(identify_action_type(action))
70
+ end
71
+
72
+ def coverage_info_content(response_body)
73
+ return [[], []] unless response_body.is_a?(Hash)
74
+
75
+ cards =
76
+ if response_body['cards'].is_a?(Array)
77
+ response_body['cards'].select { |card| coverage_info_card_type?(card) }
78
+ else
79
+ []
80
+ end
81
+ actions =
82
+ if response_body['systemActions'].is_a?(Array)
83
+ response_body['systemActions'].select { |action| coverage_info_system_action_type?(action) }
84
+ else
85
+ []
86
+ end
87
+
88
+ [cards, actions]
89
+ end
90
+
91
+ def coverage_info_system_action_response?(response_body)
92
+ return false unless response_body.is_a?(Hash)
93
+
94
+ return false unless response_body['systemActions'].is_a?(Array)
95
+
96
+ response_body['systemActions'].any? { |action| coverage_information_response_type?(action) }
97
+ end
98
+
99
+ def coverage_info_response?(response_body)
100
+ cards, actions = coverage_info_content(response_body)
101
+
102
+ cards.present? || actions.present?
103
+ end
104
+
105
+ def coverage_info_configuration_disabled?(request_body)
106
+ request_body.is_a?(Hash) &&
107
+ request_body.dig('extension', 'davinci-crd.configuration', COVERAGE_INFO_CONFIGURATION_CODE) == false
108
+ end
109
+
110
+ def disable_coverage_info_configuration!(request_body)
111
+ request_body['extension'] = {} unless request_body['extension'].is_a?(Hash)
112
+ unless request_body['extension']['davinci-crd.configuration'].is_a?(Hash)
113
+ request_body['extension']['davinci-crd.configuration'] = {}
114
+ end
115
+ request_body['extension']['davinci-crd.configuration'][COVERAGE_INFO_CONFIGURATION_CODE] = false
116
+
117
+ request_body
118
+ end
119
+
120
+ def additional_orders_response_type?(card, expected_resource_types: ADDITIONAL_ORDERS_EXPECTED_RESOURCE_TYPES)
121
+ return false if card['suggestions'].blank?
122
+
123
+ card['suggestions'].all? do |suggestion|
124
+ actions = suggestion['actions']
125
+ actions&.all? do |action|
126
+ action['type'] == 'create' &&
127
+ (expected_resource_types.blank? || action_resource_type_check(action, expected_resource_types))
128
+ end
129
+ end
130
+ end
131
+
132
+ def coverage_information_response_type?(action) # rubocop:disable Metrics/CyclomaticComplexity
133
+ return false unless action.respond_to?(:[])
134
+ return false unless action['type'] == 'update'
135
+
136
+ resource = action['resource']&.to_hash
137
+ return false unless COVERAGE_INFO_EXPECTED_RESOURCE_TYPES.include? resource&.dig('resourceType')
138
+
139
+ unless resource&.dig('extension')&.any? { |extension| extension_url(extension) == COVERAGE_INFO_EXT_URL }
140
+ return false
141
+ end
142
+
143
+ true
144
+ end
145
+
146
+ def extension_url(extension)
147
+ return extension.url if extension.respond_to?(:url)
148
+ return extension['url'] if extension.respond_to?(:[])
149
+
150
+ nil
151
+ end
152
+
153
+ def create_or_update_coverage_card_response_type?(card)
154
+ card['suggestions']&.one? && card['suggestions'].first['actions']&.one? do |action|
155
+ create_or_update_coverage_action_response_type?(action)
156
+ end
157
+ end
158
+
159
+ def create_or_update_coverage_action_response_type?(action)
160
+ ['create', 'update'].include?(action['type']) && action_resource_type_check(action, ['Coverage'])
161
+ end
162
+
163
+ def create_questionnaire_action_response_type?(action)
164
+ action['type'] == 'create' && action_resource_type_check(action, ['Questionnaire'])
165
+ end
166
+
167
+ def external_reference_response_type?(card)
168
+ links = card['links']
169
+ return false if links.blank?
170
+
171
+ links.all? { |link| link['type'] == 'absolute' }
172
+ end
173
+
174
+ def form_completion_card_response_type?(card)
175
+ card['suggestions']&.all? do |suggestion|
176
+ suggestion['actions']&.one? { |action| form_completion_action_response_type?(action) }
177
+ end
178
+ end
179
+
180
+ def form_completion_action_response_type?(action)
181
+ action['type'] == 'create' &&
182
+ action_resource_type_check(action, ['Task']) &&
183
+ form_completion_task_questionnaire?(action['resource'])
184
+ end
185
+
186
+ def form_completion_task_questionnaire?(task_action)
187
+ task_action.dig('code', 'coding')&.any? { |code| code['code'] == 'complete-questionnaire' } &&
188
+ task_action['input']&.any? do |input|
189
+ input.dig('type', 'text') == 'questionnaire' && valid_url?(input['valueCanonical'])
190
+ end
191
+ end
192
+
193
+ def instructions_response_type?(card)
194
+ card['links'].blank? && card['suggestions'].blank?
195
+ end
196
+
197
+ def launch_smart_app_response_type?(card)
198
+ links = card['links']
199
+ return false if links.blank?
200
+
201
+ links.all? { |link| link['type'] == 'smart' }
202
+ end
203
+
204
+ def propose_alternative_request_response_type?(
205
+ card,
206
+ expected_resource_types: PROPOSE_ALTERNATIVE_REQUEST_EXPECTED_RESOURCE_TYPES
207
+ )
208
+ card['suggestions']&.any? do |suggestion|
209
+ actions = suggestion['actions']
210
+ has_update = check_action_type(actions, 'update', expected_resource_types)
211
+ has_delete = check_action_type(actions, 'delete', expected_resource_types)
212
+ has_create = check_action_type(actions, 'create', expected_resource_types)
213
+
214
+ has_update || (has_delete && has_create)
215
+ end
216
+ end
217
+
218
+ def check_action_type(actions, action_type, expected_resource_types)
219
+ actions&.any? do |action|
220
+ action['type'] == action_type &&
221
+ (expected_resource_types.blank? || action_resource_type_check(action, expected_resource_types))
222
+ end
223
+ end
224
+
225
+ def list_card_types_in_requests(hooks_requests)
226
+ sorted_cards = sorted_cards_from_requests(hooks_requests)
227
+
228
+ present_card_types = sorted_cards['cards'].select { |key, value| key.present? && value.present? }.keys
229
+ present_action_types = sorted_cards['actions'].select { |key, value| key.present? && value.present? }.keys
230
+
231
+ present_card_types.map { |type| "#{type}_card" } + present_action_types.map { |type| "#{type}_action" }
232
+ end
233
+
234
+ def sorted_cards_from_requests(hooks_requests)
235
+ return sorted_cards_from_cache if sorted_cards_cached?(hooks_requests)
236
+
237
+ sorted_cards = initialize_sorted_cards_hash
238
+
239
+ hooks_requests.each do |request|
240
+ sort_card_types_from_request(request, sorted_cards)
241
+ rescue JSON::ParserError
242
+ next
243
+ end
244
+
245
+ cache_sorted_cards(hooks_requests, sorted_cards)
246
+ sorted_cards
247
+ end
248
+
249
+ def sort_card_types_from_request(request, sorted_cards)
250
+ response_body = JSON.parse(request.response_body)
251
+ response_body['cards']&.each do |card|
252
+ sorted_cards['cards'][identify_card_type(card)] << card
253
+ end
254
+
255
+ response_body['systemActions']&.each do |action|
256
+ sorted_cards['actions'][identify_action_type(action)] << action
257
+ end
258
+ end
259
+
260
+ def initialize_sorted_cards_hash
261
+ {
262
+ 'cards' => {
263
+ ADDITIONAL_ORDERS_RESPONSE_TYPE => [],
264
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE => [],
265
+ EXTERNAL_REFERENCE_RESPONSE_TYPE => [],
266
+ FORM_COMPLETION_RESPONSE_TYPE => [],
267
+ INSTRUCTIONS_RESPONSE_TYPE => [],
268
+ LAUNCH_SMART_APP_RESPONSE_TYPE => [],
269
+ PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE => [],
270
+ nil => [] # unknown type
271
+ },
272
+ 'actions' => {
273
+ COVERAGE_INFORMATION_RESPONSE_TYPE => [],
274
+ CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE => [],
275
+ FORM_COMPLETION_RESPONSE_TYPE => [],
276
+ nil => [] # unknown type
277
+ }
278
+ }
279
+ end
280
+
281
+ def extract_coverage_information_extensions(sorted_cards)
282
+ coverage_information_extensions = []
283
+
284
+ sorted_cards['actions'][COVERAGE_INFORMATION_RESPONSE_TYPE].each do |coverage_information_action|
285
+ coverage_information_action['resource']['extension'].each do |extension|
286
+ coverage_information_extensions << extension if extension['url'] == COVERAGE_INFO_EXT_URL
287
+ end
288
+ end
289
+
290
+ coverage_information_extensions.map { |ext| FHIR::Extension.new(ext) }
291
+ end
292
+
293
+ def sorted_cards_cached?(requests)
294
+ return false unless scratch['sorted_cards'].present?
295
+ return false unless scratch['sorted_cards']['hook_instances'].length == requests.length
296
+
297
+ requests.all? do |request|
298
+ scratch['sorted_cards']['hook_instances'].include?(JSON.parse(request.request_body)&.dig('hookInstance'))
299
+ rescue JSON::ParserError
300
+ false
301
+ end
302
+ end
303
+
304
+ def cache_sorted_cards(requests, sorted_cards)
305
+ scratch['sorted_cards'] = {
306
+ 'hook_instances' => hook_instances_from_requests(requests),
307
+ 'data' => sorted_cards
308
+ }
309
+ rescue JSON::ParserError
310
+ nil
311
+ end
312
+
313
+ def sorted_cards_from_cache
314
+ scratch['sorted_cards']['data']
315
+ end
316
+
317
+ def hook_instances_from_requests(requests)
318
+ requests.map { |request| JSON.parse(request.request_body)&.dig('hookInstance') }.compact
319
+ end
320
+ end
321
+ end
@@ -1,9 +1,9 @@
1
- require_relative 'server_hook_request_validation'
1
+ require_relative 'hook_request_field_validation'
2
2
  require_relative 'suggestion_actions_validation'
3
3
 
4
4
  module DaVinciCRDTestKit
5
5
  module CardsValidation
6
- include DaVinciCRDTestKit::ServerHookRequestValidation
6
+ include DaVinciCRDTestKit::HookRequestFieldValidation
7
7
  include DaVinciCRDTestKit::SuggestionActionsValidation
8
8
 
9
9
  HOOKS = [
@@ -12,7 +12,18 @@ module DaVinciCRDTestKit
12
12
  ].freeze
13
13
 
14
14
  def card_required_fields
15
- { 'summary' => String, 'indicator' => String, 'source' => Hash }
15
+ {
16
+ 'v221' => {
17
+ 'uuid' => String,
18
+ 'summary' => String,
19
+ 'source' => Hash
20
+ },
21
+ 'v201' => {
22
+ 'indicator' => String,
23
+ 'summary' => String,
24
+ 'source' => Hash
25
+ }
26
+ }
16
27
  end
17
28
 
18
29
  def source_required_fields
@@ -25,11 +36,22 @@ module DaVinciCRDTestKit
25
36
 
26
37
  def card_optional_fields
27
38
  {
28
- 'uuid' => String,
29
- 'detail' => String,
30
- 'suggestions' => Array,
31
- 'overrideReasons' => Array,
32
- 'links' => Array
39
+ 'v221' => {
40
+ 'detail' => String,
41
+ 'indicator' => String,
42
+ 'suggestions' => Array,
43
+ 'selectionBehavior' => String,
44
+ 'overrideReasons' => Array,
45
+ 'links' => Array
46
+ },
47
+ 'v201' => {
48
+ 'detail' => String,
49
+ 'uuid' => String,
50
+ 'suggestions' => Array,
51
+ 'selectionBehavior' => String,
52
+ 'overrideReasons' => Array,
53
+ 'links' => Array
54
+ }
33
55
  }
34
56
  end
35
57
 
@@ -41,12 +63,12 @@ module DaVinciCRDTestKit
41
63
  { 'label' => String, 'type' => String, 'url' => 'URL' }
42
64
  end
43
65
 
44
- def valid_card_with_optionals?(card)
66
+ def valid_card_with_optionals?(card, version)
45
67
  current_error_count = messages.count { |msg| msg[:type] == 'error' }
46
- card_optional_fields.each do |field, type|
68
+ card_optional_fields[version].each do |field, type|
47
69
  next unless card[field]
48
70
 
49
- validate_presence_and_type(card, field, type, 'Card')
71
+ validate_presence_and_type(card, field, type, 'Card', required: false)
50
72
  end
51
73
 
52
74
  card_selection_behavior_check(card)
@@ -84,32 +106,83 @@ module DaVinciCRDTestKit
84
106
  end
85
107
  end
86
108
 
87
- def card_links_check(card)
109
+ def card_links_check(card) # rubocop:disable Metrics/CyclomaticComplexity
88
110
  return unless card['links'].is_a?(Array) && card['links'].present?
89
111
 
90
112
  card['links'].each do |link|
91
113
  link_required_fields.each do |field, type|
92
114
  validate_presence_and_type(link, field, type, 'Link')
93
115
  end
116
+ end
94
117
 
95
- card_link_type_check(card, link)
118
+ if card['links'].all? { |link| link['type'] == 'absolute' }
119
+ external_reference_card_check(card)
120
+ elsif card['links'].all? { |link| link['type'] == 'smart' }
121
+ smart_app_card_check(card)
122
+ else
123
+ add_message(
124
+ 'error',
125
+ "All links must either be `absolute` or `smart` in card: #{card}"
126
+ )
96
127
  end
97
128
  end
98
129
 
99
- def card_link_type_check(card, link)
100
- return unless link['type']
130
+ def external_reference_card_check(card)
131
+ if card['suggestions'].present?
132
+ add_message(
133
+ 'error',
134
+ "Cards with `absolute` links must not contain suggestions. In card `#{card}`"
135
+ )
136
+ end
101
137
 
102
- unless ['absolute', 'smart'].include?(link['type'])
103
- add_message('error',
104
- "`Link.type` must be `absolute` or `smart`. Got `#{link['type']}`: `#{link}`. In Card `#{card}`")
105
- return
138
+ card['links'].each do |link|
139
+ next if link['appContext'].blank?
140
+
141
+ add_message(
142
+ 'error',
143
+ '`appContext` field must not be present if the link type is absolute: ' \
144
+ "`#{link}`. In Card `#{card}`"
145
+ )
106
146
  end
147
+ end
107
148
 
108
- return unless link['type'] == 'absolute' && link['appContext'].present?
149
+ def smart_app_card_check(card)
150
+ if card['suggestions'].blank?
151
+ add_message(
152
+ 'error',
153
+ "Cards with `smart` links must contain at least one suggestion. In card `#{card}`"
154
+ )
155
+ elsif card['suggestions'].any? { |suggestion| suggestion['actions'].present? }
156
+ add_message(
157
+ 'error',
158
+ "Cards with `smart` links must not contain any suggestion actions. In card `#{card}`"
159
+ )
160
+ end
161
+ end
109
162
 
110
- msg = '`appContext` field should only be valued if the link type is smart and is not valid for absolute links: ' \
111
- "`#{link}`. In Card `#{card}`"
112
- add_message('error', msg)
163
+ def no_links_check(card, card_type)
164
+ return unless card['links'].present?
165
+
166
+ add_message(
167
+ 'error',
168
+ "#{card_type} response must not contain links. In card: `#{card}`"
169
+ )
170
+ end
171
+
172
+ def additional_orders_check(card)
173
+ no_links_check(card, 'Additional Orders')
174
+ end
175
+
176
+ def create_or_update_coverage_check(card)
177
+ no_links_check(card, 'Update Coverage Records')
178
+ end
179
+
180
+ def form_completion_check(card)
181
+ no_links_check(card, 'Form Completion')
182
+ end
183
+
184
+ def propose_alternate_request_check(card)
185
+ no_links_check(card, 'Propose Alternate Request')
113
186
  end
114
187
 
115
188
  def card_suggestions_check(card)
@@ -122,6 +195,7 @@ module DaVinciCRDTestKit
122
195
 
123
196
  def process_suggestion(card, suggestion)
124
197
  validate_presence_and_type(suggestion, 'label', String, 'Suggestion')
198
+ validate_presence_and_type(suggestion, 'uuid', String, 'Suggestion')
125
199
  return unless suggestion['actions']
126
200
 
127
201
  validate_and_process_actions(card, suggestion)
@@ -166,7 +240,7 @@ module DaVinciCRDTestKit
166
240
  def card_summary_check(card)
167
241
  return if !card['summary'].is_a?(String) || card['summary'].length < 140
168
242
 
169
- add_message('error', "`summary` is over the 140-character limit: `#{card}`")
243
+ add_message('error', "`summary` is over the 140-character limit: `#{card['summary']}`")
170
244
  end
171
245
 
172
246
  def card_indicator_check(card)
@@ -176,10 +250,10 @@ module DaVinciCRDTestKit
176
250
  add_message('error', msg)
177
251
  end
178
252
 
179
- def cards_check(cards)
253
+ def cards_check(cards, version = 'v221')
180
254
  cards.each do |card|
181
255
  current_error_count = messages.count { |msg| msg[:type] == 'error' }
182
- card_required_fields.each do |field, type|
256
+ card_required_fields[version].each do |field, type|
183
257
  validate_presence_and_type(card, field, type, 'Card')
184
258
  end
185
259
 
@@ -195,7 +269,7 @@ module DaVinciCRDTestKit
195
269
  "Server response #{index}"
196
270
  end
197
271
 
198
- def perform_cards_validation(cards, response_index = 0)
272
+ def perform_cards_validation(cards, response_has_system_actions, version, response_index)
199
273
  unless cards
200
274
  add_message('error', "#{response_label(response_index + 1)} did not have the `cards` field.")
201
275
  return
@@ -205,9 +279,10 @@ module DaVinciCRDTestKit
205
279
  return
206
280
  end
207
281
  warning do
208
- assert cards.present?, "#{response_label(response_index + 1)} has no decision support."
282
+ assert cards.present? || response_has_system_actions,
283
+ "#{response_label(response_index + 1)} has no decision support."
209
284
  end
210
- cards_check(cards)
285
+ cards_check(cards, version)
211
286
  end
212
287
 
213
288
  def all_requests
@@ -216,23 +291,5 @@ module DaVinciCRDTestKit
216
291
  reqs.concat(requests)
217
292
  end
218
293
  end
219
-
220
- def extract_all_valid_cards_from_hooks_responses
221
- all_requests.keep_if { |request| request.status == 200 }
222
- all_requests.each_with_index do |request, index|
223
- service_response = JSON.parse(request.response_body)
224
- perform_cards_validation(service_response['cards'], index)
225
- rescue JSON::ParserError
226
- add_message('error', "Invalid JSON: #{response_label(response_index + 1).downcase} is not a valid JSON.")
227
- end
228
- end
229
-
230
- def extract_valid_cards_with_links_from_hooks_responses
231
- extract_all_valid_cards_from_hooks_responses
232
-
233
- valid_cards.each do |card|
234
- valid_cards_with_links << card if valid_card_with_optionals?(card) && (card['links'])
235
- end
236
- end
237
294
  end
238
295
  end
@@ -0,0 +1,27 @@
1
+ ---
2
+ :name: coverage_information
3
+ :version: v2.0.1
4
+ :reformatted_version: v201
5
+ :profile_url: http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information
6
+ :profile_name: "Extension: Coverage Information"
7
+ :profile_version: 2.0.1
8
+ :title: Coverage Information
9
+ :must_supports:
10
+ :extensions:
11
+ - :id: Extension.extension:coverage
12
+ :path: extension
13
+ :url: coverage
14
+ - :id: Extension.extension:covered
15
+ :path: extension
16
+ :url: covered
17
+ - :id: Extension.extension:doc-needed
18
+ :path: extension
19
+ :url: doc-needed
20
+ - :id: Extension.extension:doc-purpose
21
+ :path: extension
22
+ :url: doc-purpose
23
+ - :id: Extension.extension:info-needed
24
+ :path: extension
25
+ :url: info-needed
26
+ :slices:
27
+ :elements:
@@ -0,0 +1,60 @@
1
+ ---
2
+ :name: coverage_information
3
+ :version: v2.2.1
4
+ :reformatted_version: v221
5
+ :profile_url: http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information
6
+ :profile_name: "Extension: Coverage Information"
7
+ :profile_version: 2.2.1
8
+ :title: Coverage Information
9
+ :must_supports:
10
+ :extensions:
11
+ - :id: Extension.extension:coverage
12
+ :path: extension
13
+ :url: coverage
14
+ - :id: Extension.extension:covered
15
+ :path: extension
16
+ :url: covered
17
+ - :id: Extension.extension:pa-needed
18
+ :path: extension
19
+ :url: pa-needed
20
+ - :id: Extension.extension:doc-needed
21
+ :path: extension
22
+ :url: doc-needed
23
+ - :id: Extension.extension:doc-purpose
24
+ :path: extension
25
+ :url: doc-purpose
26
+ - :id: Extension.extension:info-needed
27
+ :path: extension
28
+ :url: info-needed
29
+ - :id: Extension.extension:billingCode
30
+ :path: extension
31
+ :url: billingCode
32
+ - :id: Extension.extension:reason
33
+ :path: extension
34
+ :url: reason
35
+ - :id: Extension.extension:detail
36
+ :path: extension
37
+ :url: detail
38
+ - :id: Extension.extension:dependency
39
+ :path: extension
40
+ :url: dependency
41
+ - :id: Extension.extension:questionnaire
42
+ :path: extension
43
+ :url: questionnaire
44
+ - :id: Extension.extension:date
45
+ :path: extension
46
+ :url: date
47
+ - :id: Extension.extension:coverage-assertion-id
48
+ :path: extension
49
+ :url: coverage-assertion-id
50
+ - :id: Extension.extension:satisfied-pa-id
51
+ :path: extension
52
+ :url: satisfied-pa-id
53
+ - :id: Extension.extension:contact
54
+ :path: extension
55
+ :url: contact
56
+ - :id: Extension.extension:expiry-date
57
+ :path: extension
58
+ :url: expiry-date
59
+ :slices:
60
+ :elements: