davinci_crd_test_kit 0.14.0 → 0.14.2

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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/{inferno_crd_server_suite.json.erb → client_against_inferno_crd_server_suite.json.erb} +0 -33
  3. data/config/presets/{ri_crd_request_generator.json.erb → client_against_ri_crd_request_generator.json.erb} +1 -14
  4. data/config/presets/client_v221_against_inferno_crd_server_suite.json.erb +84 -0
  5. data/config/presets/client_v221_against_ri_br_provider.json.erb +31 -0
  6. data/config/presets/{ri_crd_request_generator.json_v221.json.erb → client_v221_against_ri_crd_request_generator.json.erb} +1 -1
  7. data/config/presets/{inferno_crd_client_suite.json.erb → server_against_inferno_crd_client_suite.json.erb} +0 -43
  8. data/config/presets/{ri_crd_server.json.erb → server_against_ri_crd_server.json.erb} +1 -44
  9. data/config/presets/{inferno_crd_client_suite_v221.json.erb → server_v221_against_inferno_crd_client_suite.json.erb} +48 -45
  10. data/config/presets/{inferno_crd_client_suite_prefetch_subset_v221.json.erb → server_v221_against_inferno_crd_client_suite_prefetch_subset.json.erb} +0 -46
  11. data/config/presets/server_v221_against_inferno_g31_suite.json.erb +49 -0
  12. data/lib/davinci_crd_test_kit/client/cross_hook_helper.rb +26 -0
  13. data/lib/davinci_crd_test_kit/client/endpoints/custom_service_response.rb +7 -7
  14. data/lib/davinci_crd_test_kit/client/endpoints/gather_response_generation_data.rb +4 -1
  15. data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +70 -39
  16. data/lib/davinci_crd_test_kit/client/endpoints/mock_service_response.rb +26 -7
  17. data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/external_reference.json +1 -1
  18. data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/launch_smart_app.json +0 -7
  19. data/lib/davinci_crd_test_kit/client/endpoints/scenario_service_response.rb +54 -0
  20. data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +8 -27
  21. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +35 -23
  22. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +34 -21
  23. data/lib/davinci_crd_test_kit/client/v2.0.1/cds-services-v201.json +20 -20
  24. data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +12 -10
  25. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +12 -10
  26. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +12 -10
  27. data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +5 -5
  28. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +12 -10
  29. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +12 -10
  30. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +12 -10
  31. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +3 -36
  32. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +3 -36
  33. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +3 -36
  34. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +4 -13
  35. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +3 -13
  36. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +3 -13
  37. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +3 -13
  38. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +1 -1
  39. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
  40. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_authorized_scope_attestation_test.rb +45 -0
  41. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_coverage_based_invocation_attestation_test.rb +44 -0
  42. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
  43. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_hook_invocation_logging_attestation_test.rb +43 -0
  44. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_exposure_attestation_test.rb +43 -0
  45. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_use_attestation_test.rb +41 -0
  46. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_order_sign_support_attestation_test.rb +42 -0
  47. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_prefetch_key_omission_attestation_test.rb +42 -0
  48. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_resource_identifiers_attestation_test.rb +43 -0
  49. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_response_case_distinction_attestation_test.rb +43 -0
  50. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_security_and_privacy_attestation_test.rb +43 -0
  51. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_workflow_integration_attestation_test.rb +44 -0
  52. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +1 -1
  53. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +29 -18
  54. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +35 -22
  55. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +47 -47
  56. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +50 -50
  57. data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +24 -15
  58. data/lib/davinci_crd_test_kit/client/v2.2.1/client_attestations_group.rb +49 -0
  59. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +22 -6
  60. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_interaction_group.rb +98 -0
  61. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +19 -11
  62. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +19 -11
  63. data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +14 -12
  64. data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +25 -5
  65. data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +3 -2
  66. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +23 -15
  67. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +19 -11
  68. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +23 -15
  69. data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +6 -0
  70. data/lib/davinci_crd_test_kit/client/v2.2.1/client_scenarios_group.rb +26 -0
  71. data/lib/davinci_crd_test_kit/client/v2.2.1/client_self_pay_hook_group.rb +36 -0
  72. data/lib/davinci_crd_test_kit/client/v2.2.1/client_unknown_content_hook_group.rb +34 -0
  73. data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +24 -3
  74. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +1 -1
  75. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +4 -11
  76. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +1 -9
  77. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +6 -2
  78. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +3 -12
  79. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +8 -89
  80. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/base_hook_invocation_receive_request_test.rb +163 -0
  81. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/cross_hooks_receive_request_test.rb +97 -0
  82. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +8 -90
  83. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +8 -90
  84. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +8 -98
  85. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +8 -98
  86. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +8 -98
  87. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +10 -2
  88. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +11 -6
  89. data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +2 -1
  90. data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_no_request_test.rb +30 -0
  91. data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_workflow_test.rb +55 -0
  92. data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_attestation_test.rb +99 -0
  93. data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_receive_request_test.rb +62 -0
  94. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +1 -1
  95. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +10 -2
  96. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +1 -1
  97. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +1 -1
  98. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +7 -1
  99. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +1 -1
  100. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +1 -1
  101. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +1 -1
  102. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +54 -21
  103. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +1 -1
  104. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +6 -3
  105. data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +18 -0
  106. data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +30 -13
  107. data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +25 -11
  108. data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +2 -0
  109. data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +28 -28
  110. data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +211 -43
  111. data/lib/davinci_crd_test_kit/cross_suite/tags.rb +7 -0
  112. data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
  113. data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +6 -2
  114. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +107 -107
  115. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +101 -97
  116. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +18 -18
  117. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +43 -39
  118. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
  119. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +3 -3
  120. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_no_special_requests.rb +17 -0
  121. data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_with_bad_auth.rb +14 -0
  122. data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +24 -6
  123. data/lib/davinci_crd_test_kit/server/server_hook_helper.rb +2 -2
  124. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +1 -1
  125. data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +5 -5
  126. data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +3 -0
  127. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_standard_prefetch_expressions_test.rb +165 -0
  128. data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_single_request_test.rb +22 -0
  129. data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +10 -102
  130. data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +3 -2
  131. data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +2 -0
  132. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +10 -97
  133. data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +10 -97
  134. data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +5 -5
  135. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +10 -103
  136. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +12 -116
  137. data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +12 -121
  138. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_response_group.rb +23 -0
  139. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_info_reason_test.rb +108 -0
  140. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_not_found_group.rb +116 -0
  141. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_active_coverage_group.rb +115 -0
  142. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_member_found_group.rb +117 -0
  143. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_group.rb +121 -0
  144. data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_invoke_test.rb +22 -0
  145. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +1 -0
  146. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +1 -0
  147. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +1 -0
  148. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +78 -35
  149. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_card_absence_test.rb +76 -0
  150. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +70 -124
  151. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +83 -39
  152. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +59 -17
  153. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +80 -45
  154. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +37 -0
  155. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +57 -6
  156. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +56 -17
  157. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +52 -25
  158. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +17 -51
  159. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +1 -1
  160. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +1 -1
  161. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +1 -1
  162. data/lib/davinci_crd_test_kit/version.rb +2 -2
  163. metadata +54 -16
  164. data/config/presets/inferno_crd_server_suite_v221.json.erb +0 -94
  165. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/card_optional_fields_validation_test.rb +0 -57
  166. data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_received_test.rb +0 -65
@@ -0,0 +1,121 @@
1
+ require_relative 'technical_issues_invoke_test'
2
+ require_relative 'coverage_info_reason_test'
3
+
4
+ module DaVinciCRDTestKit
5
+ module V221
6
+ class TechnicalIssuesGroup < Inferno::TestGroup
7
+ title 'Technical Issues'
8
+ id :crd_v221_server_technical_issues_group
9
+ description %(
10
+ This group of tests allows the system to demonstrate its ability to
11
+ respond to a CRD Hook invocation with an `indeterminate` coverage
12
+ determination due to technical issues.
13
+
14
+ For these tests, the hook call will include an invalid access token,
15
+ which due to the nature of Inferno's FHIR server simulation will result
16
+ in 500 response to FHIR requests, simulating a temporary server outage.
17
+ The tests then verify that a Coverage Information systemAction is
18
+ received with `indeterminate` coverage for `technical` reasons.
19
+ )
20
+
21
+ config options: { hook_name: TECHNICAL_ISSUES_TAG }
22
+ run_as_group
23
+
24
+ group do
25
+ title 'Interaction'
26
+
27
+ test from: :crd_v221_server_technical_issues_invoke_hook_test,
28
+ description: <<~DESCRIPTION,
29
+ This test initiates a POST request to a specified CDS Service
30
+ using the JSON body list provided by the user. This request is
31
+ generated so that requests for FHIR resources from the CDS service
32
+ result in 500 errors, simulating a temporary server error.
33
+ DESCRIPTION
34
+ config: {
35
+ inputs: {
36
+ service_ids: {
37
+ name: :technical_issues_service_ids,
38
+ title: 'Service id to use for the "Technical Issues" test',
39
+ description: %(
40
+ If blank, Inferno will attempt to infer the service id to use
41
+ by finding a service entry in the Discovery response for the
42
+ hook indicated in the provided request body. If it cannot be
43
+ inferred, the tests will be skipped.
44
+ )
45
+ },
46
+ service_request_bodies: {
47
+ name: :technical_issues_request_body,
48
+ title: 'Request body to use for the "Technical Issues" test',
49
+ description: %(
50
+ Provide a single JSON request body to submit for the hook
51
+ invocation. The type of hook invoked will be inferred based
52
+ on the `hook` element in the request.
53
+ )
54
+ }
55
+ }
56
+ }
57
+ end
58
+
59
+ group do
60
+ title 'Requests'
61
+ simulation_verification
62
+
63
+ test from: :crd_v221_service_request_required_fields_validation,
64
+ config: {
65
+ outputs: {
66
+ contexts: {
67
+ name: :technical_issues_contexts
68
+ }
69
+ }
70
+ }
71
+ test from: :crd_v221_service_request_context_validation,
72
+ config: {
73
+ inputs: {
74
+ contexts: {
75
+ name: :technical_issues_contexts
76
+ },
77
+ request_body: {
78
+ name: :technical_issues_request_body
79
+ }
80
+ }
81
+ }
82
+ end
83
+
84
+ group do
85
+ title 'Responses'
86
+
87
+ test from: :crd_v221_service_response_validation
88
+ test from: :crd_v221_coverage_info_system_action_validation,
89
+ config: {
90
+ outputs: {
91
+ coverage_info: {
92
+ name: :technical_issues_coverage_info
93
+ }
94
+ }
95
+ }
96
+ test from: :crd_v221_coverage_info_reason,
97
+ title: 'Coverage Information responses have indeterminate coverage for technical reasons',
98
+ description: <<~DESCRIPTION,
99
+ This test verifies that the Coverage Information responses received contain Coverage Information
100
+ extensions with `indeterminate` coverage and a `technical` reason, and additional details about the
101
+ failure are included in the `text` field of the reason extension.
102
+ DESCRIPTION
103
+ config: {
104
+ inputs: {
105
+ coverage_info: {
106
+ name: :technical_issues_coverage_info
107
+ }
108
+ },
109
+ options: {
110
+ expected_coverage_code: 'indeterminate',
111
+ expected_reason_code: 'technical',
112
+ require_reason_text: true
113
+ }
114
+ },
115
+ verifies_requirements: [
116
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-43'
117
+ ]
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../server_urls'
2
+ require_relative '../../jobs/invoke_hook_with_bad_auth'
3
+ require_relative '../../server_abstract_invoke_hook_test'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class TechnicalIssuesInvokeHookTest < ServerAbstractInvokeHookTest
8
+ include ServerURLs
9
+
10
+ title 'Inferno invokes the selected hook with invalid authorization'
11
+ id :crd_v221_server_technical_issues_invoke_hook_test
12
+
13
+ def perform_invoke_hook_job(*)
14
+ Inferno::Jobs.perform(DaVinciCRDTestKit::Jobs::InvokeHookWithBadAuth, *)
15
+ end
16
+
17
+ def check_request_length(payloads)
18
+ skip_if payloads.length != 1, 'The *Technical Issues* test supports only one request body.'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -16,6 +16,7 @@ module DaVinciCRDTestKit
16
16
  required fields.
17
17
  )
18
18
  input :contexts, :invoked_hook
19
+ simulation_verification
19
20
 
20
21
  run do
21
22
  parsed_contexts = parse_json(contexts)
@@ -17,6 +17,7 @@ module DaVinciCRDTestKit
17
17
  informational message.
18
18
  )
19
19
  optional
20
+ simulation_verification
20
21
 
21
22
  run do
22
23
  load_tagged_requests(tested_hook_name)
@@ -17,6 +17,7 @@ module DaVinciCRDTestKit
17
17
  )
18
18
  input :invoked_hook
19
19
  output :contexts
20
+ simulation_verification
20
21
 
21
22
  run do
22
23
  load_tagged_requests(tested_hook_name)
@@ -1,65 +1,108 @@
1
1
  require_relative '../../server_test_helper'
2
2
  require_relative '../../server_hook_helper'
3
- require_relative '../../../cross_suite/suggestion_actions_validation'
4
3
  require_relative '../../../cross_suite/cards_identification'
5
- require_relative '../../../cross_suite/cards_validation'
4
+ require_relative '../../../cross_suite/response_logical_model_validation'
6
5
 
7
6
  module DaVinciCRDTestKit
8
7
  module V221
9
8
  class AdditionalOrdersValidationTest < Inferno::Test
10
9
  include DaVinciCRDTestKit::ServerTestHelper
11
- include DaVinciCRDTestKit::SuggestionActionsValidation
12
10
  include DaVinciCRDTestKit::ServerHookHelper
13
11
  include DaVinciCRDTestKit::CardsIdentification
14
- include DaVinciCRDTestKit::CardsValidation
12
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
15
13
 
16
14
  title 'Additional Orders cards are valid'
17
15
  id :crd_v221_additional_orders_card_validation
18
16
  description %(
19
- This test validates that an [Additional Orders as companions/prerequisites](https://hl7.org/fhir/us/davinci-crd/STU2/cards.html#identify-additional-orders-as-companionsprerequisites-for-current-order)
17
+ This test validates that an [Identify Additional
18
+ Orders](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#identify-additional-orders-response-type)
20
19
  card was received. It does so by:
21
20
  - Filtering cards with the following criteria:
22
- - For each suggestion in the card's suggestions array, all actions have a type of 'create'
23
- and the action's resource type is one of the expected types: CommunicationRequest, Device,
24
- DeviceRequest, Medication, MedicationRequest, NutritionOrder, ServiceRequest, or VisionPrescription.
25
- - Then, for each valid Additional Orders card retrieved, verifying that each action within the
26
- card's suggestions complies with their respective profiles as specified in the
27
- [CRD IG section on Additional Orders as companions/prerequisites](https://hl7.org/fhir/us/davinci-crd/STU2/cards.html#identify-additional-orders-as-companionsprerequisites-for-current-order):
28
- - [crd-profile-communicationrequest](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-communicationrequest.html)
29
- - [crd-profile-device](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-device.html)
30
- - [crd-profile-deviceRequest](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-devicerequest.html)
31
- - [us-core-medication](http://hl7.org/fhir/us/core/STU3.1.1/StructureDefinition-us-core-medication.html)
32
- - [crd-profile-medicationRequest](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-medicationrequest.html)
33
- - [crd-profile-nutritionOrder](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-nutritionorder.html)
34
- - [crd-profile-serviceRequest](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-servicerequest.html)
35
- - [crd-profile-visionPrescription](https://hl7.org/fhir/us/davinci-crd/STU2/StructureDefinition-profile-visionprescription.html).
36
-
37
- The test will skip if no Additional Orders cards are found.
21
+ - For each suggestion in the card's suggestions array, all actions
22
+ have a type of 'create' and the action's resource type is one of the
23
+ expected types: CommunicationRequest, Device, DeviceRequest,
24
+ Medication, MedicationRequest, NutritionOrder, ServiceRequest, or
25
+ VisionPrescription.
26
+ - Then, for each valid Additional Orders card retrieved, verifying that
27
+ each action within the card's suggestions complies with their
28
+ respective profiles as specified in the [CRD IG section on Identify
29
+ Additional
30
+ Orders](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#identify-additional-orders-response-type):
31
+ -
32
+ [crd-profile-communicationrequest](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-communicationrequest.html)
33
+ -
34
+ [crd-profile-device](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-device.html)
35
+ -
36
+ [crd-profile-deviceRequest](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-devicerequest.html)
37
+ -
38
+ [us-core-medication](http://hl7.org/fhir/us/core/STU3.1.1/StructureDefinition-us-core-medication.html)
39
+ -
40
+ [crd-profile-medicationRequest](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-medicationrequest.html)
41
+ -
42
+ [crd-profile-nutritionOrder](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-nutritionorder.html)
43
+ -
44
+ [crd-profile-serviceRequest](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-servicerequest.html)
45
+ -
46
+ [crd-profile-visionPrescription](https://hl7.org/fhir/us/davinci-crd/2.2.1/StructureDefinition-profile-visionprescription.html).
47
+
48
+ The test will skip if no Identify Additional Orders cards are found.
38
49
  )
39
50
 
40
- verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-57',
51
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
52
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-57',
41
53
  'hl7.fhir.us.davinci-crd_2.2.1@resp-58'
42
54
 
55
+ input :invoked_hook
56
+
43
57
  optional
44
- input :valid_cards_with_suggestions
58
+
59
+ def body_has_no_cards?(body)
60
+ !body.is_a?(Hash) ||
61
+ body['cards'].blank? ||
62
+ !body['cards'].is_a?(Array) ||
63
+ !body['cards'].all?(Hash)
64
+ end
65
+
66
+ def additional_orders_cards(request)
67
+ return [] if request.status != 200
68
+
69
+ response_body = JSON.parse(request.response_body)
70
+
71
+ return [] if body_has_no_cards?(response_body)
72
+
73
+ response_body['cards'].select { |card| additional_orders_response_type? card }
74
+ rescue JSON::ParserError
75
+ []
76
+ end
45
77
 
46
78
  run do
47
- parsed_cards = parse_json(valid_cards_with_suggestions)
48
- additional_orders_cards = parsed_cards.filter do |card|
49
- additional_orders_response_type?(card)
50
- end
51
- skip_if additional_orders_cards.blank?,
52
- "#{tested_hook_name} hook response does not include Additional Orders as companion/prerequisite cards."
79
+ load_tagged_requests(tested_hook_name)
80
+
81
+ additional_orders_count = 0
82
+
83
+ successful_requests = requests.select { |request| request.status == 200 }
53
84
 
54
- additional_orders_cards.each do |card|
55
- card['suggestions'].each do |suggestion|
56
- actions_check(suggestion['actions'], ig_version: 'v221')
57
- end
85
+ skip_if successful_requests.blank?,
86
+ 'No successful hook responses were received'
58
87
 
59
- additional_orders_check(card)
88
+ requests.each_with_index do |request, index|
89
+ cards = additional_orders_cards(request)
90
+
91
+ additional_orders_count += cards.length
92
+
93
+ perform_response_logical_model_validation(
94
+ cards,
95
+ nil,
96
+ request.request_body,
97
+ index,
98
+ '2.2.1'
99
+ )
60
100
  end
61
101
 
62
- no_error_validation('Some Additional Order cards are not valid. See messages for more information.')
102
+ skip_if additional_orders_count.zero?,
103
+ "#{tested_hook_name} hook responses do not contain any Additional Orders cards."
104
+
105
+ no_error_validation('Not all Additional Orders cards were valid. See messages for more information.')
63
106
  end
64
107
  end
65
108
  end
@@ -0,0 +1,76 @@
1
+ require_relative '../../server_hook_helper'
2
+ require_relative '../../../cross_suite/cards_identification'
3
+ require_relative 'hook_request_resource_resolution'
4
+
5
+ module DaVinciCRDTestKit
6
+ module V221
7
+ class CoverageInformationCardAbsenceTest < Inferno::Test
8
+ include DaVinciCRDTestKit::ServerHookHelper
9
+ include DaVinciCRDTestKit::CardsIdentification
10
+ include HookRequestResourceResolution
11
+
12
+ title 'Hook responses do not include Coverage Information cards'
13
+ id :crd_v221_coverage_information_card_absence
14
+ description %(
15
+ This test verifies that the server does not return the
16
+ [Coverage Information](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#coverage-information-response-type)
17
+ response type as a CDS Hooks card. Coverage Information responses must be returned as `systemActions`
18
+ that update resources with the `coverage-information` extension (inclusion of systemActions is verified in a
19
+ previous test).
20
+ )
21
+
22
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-25'
23
+
24
+ input :mock_ehr_bundle, optional: true
25
+
26
+ def coverage_information_card_message(response_index, card)
27
+ identifier = card['uuid'].present? ? "uuid `#{card['uuid']}`" : 'no uuid'
28
+
29
+ "Server response #{response_index + 1} included a card with #{identifier} and a suggestion action that only " \
30
+ 'adds or modifies the coverage-information extension. Coverage Information must be returned as a ' \
31
+ 'systemAction, not as a card.'
32
+ end
33
+
34
+ def coverage_information_card_response_type?(card, request)
35
+ Array(card['suggestions']).any? do |suggestion|
36
+ Array(suggestion['actions']).any? do |action|
37
+ coverage_information_card_action?(action, request)
38
+ end
39
+ end
40
+ end
41
+
42
+ def coverage_information_card_action?(action, request)
43
+ return false unless coverage_information_response_type?(action)
44
+ return false unless action['type'] == 'update'
45
+
46
+ source_resource = find_action_source_resource(action, request)
47
+ return coverage_information_extension_only_payload?(action['resource']) unless source_resource
48
+
49
+ only_coverage_information_changed?(source_resource.to_hash, action['resource'])
50
+ end
51
+
52
+ run do
53
+ load_tagged_requests(tested_hook_name)
54
+ skip_if requests.blank?, "No #{tested_hook_name} request was made in a previous test as expected."
55
+
56
+ successful_requests = requests.select { |request| request.status == 200 }
57
+ skip_if successful_requests.empty?, 'All service requests were unsuccessful.'
58
+
59
+ successful_requests.each_with_index do |request, index|
60
+ response_body = JSON.parse(request.response_body)
61
+ cards = response_body['cards'].is_a?(Array) ? response_body['cards'] : []
62
+
63
+ cards.select { |card| coverage_information_card_response_type?(card, request) }.each do |card|
64
+ add_message('error', coverage_information_card_message(index, card))
65
+ end
66
+ rescue JSON::ParserError
67
+ add_message('error', "Invalid JSON: server response #{index + 1} is not valid JSON.")
68
+ end
69
+
70
+ assert_no_error_messages(
71
+ 'Service response(s) included Coverage Information cards. Check messages for details.'
72
+ )
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,6 +1,8 @@
1
1
  require_relative '../../server_hook_request_validation'
2
2
  require_relative '../../server_test_helper'
3
3
  require_relative '../../server_hook_helper'
4
+ require_relative '../../../cross_suite/cards_identification'
5
+ require_relative '../../../cross_suite/response_logical_model_validation'
4
6
  require_relative 'hook_request_resource_resolution'
5
7
 
6
8
  module DaVinciCRDTestKit
@@ -10,123 +12,42 @@ module DaVinciCRDTestKit
10
12
  include DaVinciCRDTestKit::ServerTestHelper
11
13
  include DaVinciCRDTestKit::ServerHookHelper
12
14
  include HookRequestResourceResolution
15
+ include DaVinciCRDTestKit::CardsIdentification
16
+ include DaVinciCRDTestKit::ResponseLogicalModelValidation
13
17
 
14
18
  COVERAGE_INFO_EXT_URL = 'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'.freeze
15
19
 
16
20
  title 'Coverage Information system actions are valid'
17
21
  id :crd_v221_coverage_info_system_action_validation
18
22
  description %(
19
- This test validates all [Coverage Information](https://hl7.org/fhir/us/davinci-crd/STU2/cards.html#coverage-information)
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)
20
25
  system actions received. It verifies the following for each action:
21
26
  - The action type is `update`.
22
27
  - The resource within the action conforms its respective FHIR profile.
23
- - The resource does not change any data elements other than adding or modifying
24
- the `coverage-information` extension.
25
-
26
- Additionally, the test examines the `coverage-info` extensions within the resource to ensure that:
27
- - Entries referencing differing coverage have distinct `coverage-assertion-ids` and `satisfied-pa-ids`
28
- (if present).
29
- - Entries referencing the same coverage have the same `coverage-assertion-ids` and `satisfied-pa-ids`
30
- (if present).
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).
31
37
  )
32
38
 
33
- verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-32',
39
+ verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-26',
40
+ 'hl7.fhir.us.davinci-crd_2.2.1@resp-32',
34
41
  'hl7.fhir.us.davinci-crd_2.2.1@resp-37',
35
42
  'hl7.fhir.us.davinci-crd_2.2.1@resp-47',
36
43
  'hl7.fhir.us.davinci-crd_2.2.1@resp-48',
37
44
  'hl7.fhir.us.davinci-crd_2.2.1@resp-52'
38
45
 
39
- input :coverage_info
46
+ input :invoked_hook
40
47
  input :mock_ehr_bundle, optional: true
48
+ output :coverage_info
41
49
 
42
- def find_extension_value(extension, url, *properties)
43
- found_extension = extension.extension.find { |ext| ext.url == url }
44
- return nil unless found_extension
45
-
46
- properties.reduce(found_extension) do |current, prop|
47
- return current unless current.respond_to?(prop)
48
-
49
- current.send(prop)
50
- end
51
- end
52
-
53
- def extract_and_group_coverage_info(resource)
54
- resource.extension.each_with_object({}) do |extension, grouped_extensions|
55
- next unless extension.url == COVERAGE_INFO_EXT_URL
56
-
57
- coverage_key = find_extension_value(extension, 'coverage', 'valueReference', 'reference')
58
- grouped_extensions[coverage_key] ||= []
59
- grouped_extensions[coverage_key] << extension
60
- end
61
- end
62
-
63
- # For the same coverage, ensure coverage-assertion-ids and satisfied-pa-ids are the same.
64
- # For different coverages, ensure coverage-assertion-ids and satisfied-pa-ids are distinct.
65
- def multiple_extensions_conformance_check(grouped_coverage_info, resource)
66
- resource_ref = "#{resource.resourceType}/#{resource.id}"
67
- assertion_ids_across_coverages = Set.new
68
- pa_ids_across_coverages = Set.new
69
-
70
- grouped_coverage_info.each do |coverage, extensions|
71
- coverage_assertion_ids = collect_extensions_id(extensions, 'coverage-assertion-id', 'valueString').uniq
72
- satisfied_pa_ids = collect_extensions_id(extensions, 'satisfied-pa-id', 'valueString').uniq.compact
73
- assert coverage_assertion_ids.length == 1,
74
- same_coverage_conformance_error_msg(resource_ref, coverage, 'coverage-assertion-ids')
75
-
76
- assert satisfied_pa_ids.length <= 1,
77
- same_coverage_conformance_error_msg(resource_ref, coverage, 'satisfied-pa-ids')
78
-
79
- assertion_id = coverage_assertion_ids.first
80
- assert !assertion_ids_across_coverages.include?(assertion_id),
81
- different_coverage_conformance_error_msg(resource_ref, 'coverage-assertion-ids')
82
- assertion_ids_across_coverages.add(assertion_id)
83
- pa_id = satisfied_pa_ids.first
84
- next unless pa_id
85
-
86
- assert !pa_ids_across_coverages.include?(pa_id),
87
- different_coverage_conformance_error_msg(resource_ref, 'satisfied-pa-ids')
88
- pa_ids_across_coverages.add(pa_id)
89
- end
90
- end
91
-
92
- def collect_extensions_id(extensions, url, *properties)
93
- extensions.map do |extension|
94
- find_extension_value(extension, url, *properties)
95
- end
96
- end
97
-
98
- def same_coverage_conformance_error_msg(resource_ref, coverage, id_name)
99
- "#{resource_ref}: extension has multiple repetitions of coverage `#{coverage}` with different #{id_name}."
100
- end
101
-
102
- def different_coverage_conformance_error_msg(resource_ref, id_name)
103
- "#{resource_ref}: extensions referencing differing coverage SHALL have distinct #{id_name}."
104
- end
105
-
106
- def normalize_value(value)
107
- case value
108
- when Hash
109
- value.transform_values { |child| normalize_value(child) }
110
- when Array
111
- value.map { |child| normalize_value(child) }.sort_by(&:to_json)
112
- else
113
- value
114
- end
115
- end
116
-
117
- def strip_coverage_info_extensions(resource_hash)
118
- normalized_hash = resource_hash.deep_dup
119
- return normalized_hash unless normalized_hash['extension'].is_a?(Array)
120
-
121
- normalized_hash['extension'] = normalized_hash['extension'].reject do |extension|
122
- extension['url'] == COVERAGE_INFO_EXT_URL
123
- end
124
- normalized_hash.delete('extension') if normalized_hash['extension'].empty?
125
- normalized_hash
126
- end
127
-
128
- def verify_only_coverage_info_changed(action)
129
- request = matching_request_for_action(action)
50
+ def verify_only_coverage_info_changed(action, request)
130
51
  source_resource = find_action_source_resource(action, request)
131
52
  updated_resource_hash = action['resource']
132
53
  resource_ref = "#{updated_resource_hash['resourceType']}/#{updated_resource_hash['id']}"
@@ -140,44 +61,69 @@ module DaVinciCRDTestKit
140
61
  return
141
62
  end
142
63
 
143
- source_resource_hash = source_resource.to_hash
64
+ return if only_coverage_information_changed?(source_resource.to_hash, updated_resource_hash)
144
65
 
145
- source_without_coverage_info = normalize_value(strip_coverage_info_extensions(source_resource_hash))
146
- updated_without_coverage_info = normalize_value(strip_coverage_info_extensions(updated_resource_hash))
66
+ add_message(
67
+ 'error',
68
+ "#{resource_ref}: resource content changed outside the coverage-information extension."
69
+ )
70
+ end
147
71
 
148
- assert source_without_coverage_info == updated_without_coverage_info,
149
- "#{resource_ref}: resource content changed outside the coverage-information extension."
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)
150
77
  end
151
78
 
152
- def coverage_info_system_action_check(coverage_info_system_action)
153
- type = coverage_info_system_action['type']
154
- assert type, '`type` field is missing.'
155
- assert type == 'update', "`type` must be `update`, but was `#{type}`"
79
+ def coverage_info_actions(request)
80
+ return [] if request.status != 200
81
+
82
+ response_body = JSON.parse(request.response_body)
156
83
 
157
- resource = FHIR.from_contents(coverage_info_system_action['resource'].to_json)
158
- profile_url = structure_definition_map('v221')[resource.resourceType]
159
- resource_is_valid?(resource:, profile_url:)
84
+ return [] if body_has_no_system_actions?(response_body)
160
85
 
161
- grouped_coverage_info = extract_and_group_coverage_info(resource)
162
- multiple_extensions_conformance_check(grouped_coverage_info, resource)
163
- verify_only_coverage_info_changed(coverage_info_system_action)
86
+ response_body['systemActions'].select { |action| coverage_information_response_type? action }
87
+ rescue JSON::ParserError
88
+ []
164
89
  end
165
90
 
166
91
  run do
167
92
  load_tagged_requests(tested_hook_name)
168
- parsed_coverage_info = parse_json(coverage_info)
169
- error_messages = []
170
- parsed_coverage_info.each do |action|
171
- coverage_info_system_action_check(action)
172
- rescue Inferno::Exceptions::AssertionException => e
173
- error_messages << "Coverage Info system action `#{action}`: #{e.message}"
174
- end
175
93
 
176
- error_messages.each do |msg|
177
- messages << { type: 'error', message: msg }
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)
178
117
  end
179
118
 
180
- assert_no_error_messages 'Some Coverage Info system actions are not valid.'
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
+ )
181
127
  end
182
128
  end
183
129
  end