davinci_crd_test_kit 0.14.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.
- checksums.yaml +4 -4
- data/config/presets/inferno_crd_client_suite_v221.json.erb +64 -0
- data/config/presets/inferno_crd_server_suite_v221.json.erb +2 -2
- data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +12 -6
- data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/external_reference.json +1 -1
- data/lib/davinci_crd_test_kit/client/endpoints/mocked_card_responses/launch_smart_app.json +0 -7
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +8 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +20 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +1 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +7 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/client_registration_group.rb +6 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +5 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +10 -5
- data/lib/davinci_crd_test_kit/client/v2.2.1/registration/client_service_registration_attestation_test.rb +2 -1
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +6 -0
- data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +2 -1
- data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +9 -0
- data/lib/davinci_crd_test_kit/cross_suite/prefetch_completeness_checker.rb +25 -11
- data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +2 -1
- data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +164 -3
- data/lib/davinci_crd_test_kit/cross_suite/tags.rb +4 -0
- data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +38 -38
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook.rb +3 -3
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_no_special_requests.rb +17 -0
- data/lib/davinci_crd_test_kit/server/jobs/invoke_hook_with_bad_auth.rb +14 -0
- data/lib/davinci_crd_test_kit/server/server_abstract_invoke_hook_test.rb +24 -6
- data/lib/davinci_crd_test_kit/server/server_hook_helper.rb +2 -2
- data/lib/davinci_crd_test_kit/server/v2.2.1/crd_server_suite.rb +3 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_standard_prefetch_expressions_test.rb +166 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/interaction/server_invoke_hook_single_request_test.rb +22 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_appointment_book_group.rb +10 -102
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_discovery_group.rb +2 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_discharge_group.rb +10 -97
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_encounter_start_group.rb +10 -97
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_dispatch_group.rb +10 -103
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_select_group.rb +12 -116
- data/lib/davinci_crd_test_kit/server/v2.2.1/server_order_sign_group.rb +12 -121
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_response_group.rb +23 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_info_reason_test.rb +108 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/coverage_not_found_group.rb +116 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_active_coverage_group.rb +115 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/no_member_found_group.rb +117 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_group.rb +121 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/specific_coverage_responses/technical_issues_invoke_test.rb +22 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_context_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_optional_fields_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_request/service_request_required_fields_validation_test.rb +1 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/additional_orders_validation_test.rb +78 -35
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_card_absence_test.rb +76 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb +70 -124
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/create_or_update_coverage_info_response_validation_test.rb +83 -39
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/external_reference_card_validation_test.rb +59 -17
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/form_completion_response_validation_test.rb +80 -45
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb +37 -0
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb +57 -6
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb +56 -17
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/propose_alternate_request_card_validation_test.rb +52 -25
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb +17 -51
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_cds_hooks_elements_test.rb +1 -1
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_configuration_test.rb +1 -1
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/unknown_context_test.rb +1 -1
- data/lib/davinci_crd_test_kit/version.rb +2 -2
- metadata +18 -8
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/card_optional_fields_validation_test.rb +0 -57
- data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_received_test.rb +0 -65
|
@@ -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
|
|
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
|
|
24
|
-
the `coverage-information` extension.
|
|
25
|
-
|
|
26
|
-
Additionally, the test examines the `coverage-info` extensions within
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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-
|
|
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 :
|
|
46
|
+
input :invoked_hook
|
|
40
47
|
input :mock_ehr_bundle, optional: true
|
|
48
|
+
output :coverage_info
|
|
41
49
|
|
|
42
|
-
def
|
|
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
|
-
|
|
64
|
+
return if only_coverage_information_changed?(source_resource.to_hash, updated_resource_hash)
|
|
144
65
|
|
|
145
|
-
|
|
146
|
-
|
|
66
|
+
add_message(
|
|
67
|
+
'error',
|
|
68
|
+
"#{resource_ref}: resource content changed outside the coverage-information extension."
|
|
69
|
+
)
|
|
70
|
+
end
|
|
147
71
|
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
79
|
+
def coverage_info_actions(request)
|
|
80
|
+
return [] if request.status != 200
|
|
81
|
+
|
|
82
|
+
response_body = JSON.parse(request.response_body)
|
|
156
83
|
|
|
157
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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
|
|
@@ -1,74 +1,118 @@
|
|
|
1
1
|
require_relative '../../server_test_helper'
|
|
2
|
-
require_relative '../../../cross_suite/suggestion_actions_validation'
|
|
3
2
|
require_relative '../../server_hook_helper'
|
|
4
3
|
require_relative '../../../cross_suite/cards_identification'
|
|
5
|
-
require_relative '../../../cross_suite/
|
|
4
|
+
require_relative '../../../cross_suite/response_logical_model_validation'
|
|
6
5
|
|
|
7
6
|
module DaVinciCRDTestKit
|
|
8
7
|
module V221
|
|
9
8
|
class CreateOrUpdateCoverageInfoResponseValidationTest < Inferno::Test
|
|
10
9
|
include DaVinciCRDTestKit::ServerTestHelper
|
|
11
|
-
include DaVinciCRDTestKit::SuggestionActionsValidation
|
|
12
10
|
include DaVinciCRDTestKit::ServerHookHelper
|
|
13
11
|
include DaVinciCRDTestKit::CardsIdentification
|
|
14
|
-
include DaVinciCRDTestKit::
|
|
12
|
+
include DaVinciCRDTestKit::ResponseLogicalModelValidation
|
|
15
13
|
|
|
16
14
|
title 'Create or Update Coverage Information cards and system actions are valid'
|
|
17
15
|
id :crd_v221_create_or_update_coverage_info_response_validation
|
|
18
16
|
description %(
|
|
19
|
-
This test validates the Create or Update Coverage Information cards or
|
|
20
|
-
CRD service, as per the specifications
|
|
17
|
+
This test validates the Create or Update Coverage Information cards or
|
|
18
|
+
system actions received from the CRD service, as per the specifications
|
|
19
|
+
outlined in the [Da Vinci CRD Implementation
|
|
20
|
+
Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#update-coverage-records-response-type).
|
|
21
21
|
|
|
22
22
|
- **Checking for Presence:**
|
|
23
|
-
The test first checks if any Create or Update Coverage Information
|
|
24
|
-
the returned valid cards or
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
The test first checks if any Create or Update Coverage Information
|
|
24
|
+
cards or system actions are present in the returned valid cards or
|
|
25
|
+
valid system actions.
|
|
26
|
+
- **For cards**: it ensures there are cards with a `suggestions` array
|
|
27
|
+
containing a single suggestion, and the `actions` array of that
|
|
28
|
+
suggestion has one `create` or `update` action for the `Coverage`
|
|
29
|
+
resource.
|
|
30
|
+
- **For system actions**: it checks for the presence of `create` or
|
|
31
|
+
`update` actions for the `Coverage` resource.
|
|
29
32
|
|
|
30
33
|
- **Validating:**
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
If any Create or Update Coverage Information cards or system actions
|
|
35
|
+
are found, each `Coverage` resource is validated against the base FHIR
|
|
36
|
+
Coverage resource.
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
If no Create or Update Coverage Information cards or system actions
|
|
39
|
+
are received, the test is skipped.
|
|
35
40
|
)
|
|
36
41
|
|
|
37
|
-
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-
|
|
42
|
+
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
|
|
43
|
+
'hl7.fhir.us.davinci-crd_2.2.1@resp-71'
|
|
44
|
+
|
|
45
|
+
input :invoked_hook
|
|
38
46
|
|
|
39
47
|
optional
|
|
40
|
-
|
|
48
|
+
|
|
49
|
+
def body_has_no_cards?(body)
|
|
50
|
+
!body.is_a?(Hash) ||
|
|
51
|
+
body['cards'].blank? ||
|
|
52
|
+
!body['cards'].is_a?(Array) ||
|
|
53
|
+
!body['cards'].all?(Hash)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def update_coverage_cards(request)
|
|
57
|
+
return [] if request.status != 200
|
|
58
|
+
|
|
59
|
+
response_body = JSON.parse(request.response_body)
|
|
60
|
+
|
|
61
|
+
return [] if body_has_no_cards?(response_body)
|
|
62
|
+
|
|
63
|
+
response_body['cards'].select { |card| create_or_update_coverage_card_response_type? card }
|
|
64
|
+
rescue JSON::ParserError
|
|
65
|
+
[]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def body_has_no_system_actions?(body)
|
|
69
|
+
!body.is_a?(Hash) ||
|
|
70
|
+
body['systemActions'].blank? ||
|
|
71
|
+
!body['systemActions'].is_a?(Array) ||
|
|
72
|
+
!body['systemActions'].all?(Hash)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def update_coverage_actions(request)
|
|
76
|
+
return [] if request.status != 200
|
|
77
|
+
|
|
78
|
+
response_body = JSON.parse(request.response_body)
|
|
79
|
+
|
|
80
|
+
return [] if body_has_no_system_actions?(response_body)
|
|
81
|
+
|
|
82
|
+
response_body['systemActions'].select { |action| create_or_update_coverage_action_response_type? action }
|
|
83
|
+
rescue JSON::ParserError
|
|
84
|
+
[]
|
|
85
|
+
end
|
|
41
86
|
|
|
42
87
|
run do
|
|
43
|
-
|
|
44
|
-
parsed_actions = parse_json(valid_system_actions)
|
|
88
|
+
load_tagged_requests(tested_hook_name)
|
|
45
89
|
|
|
46
|
-
|
|
47
|
-
create_or_update_coverage_card_response_type?(card)
|
|
48
|
-
end
|
|
49
|
-
create_or_update_coverage_info_actions = parsed_actions.select do |action|
|
|
50
|
-
create_or_update_coverage_action_response_type?(action)
|
|
51
|
-
end
|
|
90
|
+
update_coverage_count = 0
|
|
52
91
|
|
|
53
|
-
|
|
54
|
-
'cards or system actions.'
|
|
55
|
-
skip_if create_or_update_coverage_info_cards.blank? && create_or_update_coverage_info_actions.blank?, skip_msg
|
|
92
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
56
93
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
end
|
|
94
|
+
skip_if successful_requests.blank?,
|
|
95
|
+
'No successful hook responses were received'
|
|
60
96
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
create_or_update_coverage_action_response_type?(action)
|
|
65
|
-
end, ig_version: 'v221')
|
|
97
|
+
requests.each_with_index do |request, index|
|
|
98
|
+
cards = update_coverage_cards(request)
|
|
99
|
+
actions = update_coverage_actions(request)
|
|
66
100
|
|
|
67
|
-
|
|
68
|
-
|
|
101
|
+
update_coverage_count += cards.length + actions.length
|
|
102
|
+
|
|
103
|
+
perform_response_logical_model_validation(
|
|
104
|
+
cards,
|
|
105
|
+
actions,
|
|
106
|
+
request.request_body,
|
|
107
|
+
index,
|
|
108
|
+
'2.2.1'
|
|
109
|
+
)
|
|
69
110
|
end
|
|
70
111
|
|
|
71
|
-
|
|
112
|
+
skip_if update_coverage_count.zero?,
|
|
113
|
+
"#{tested_hook_name} hook responses do not contain any Update Coverage Records cards or system actions."
|
|
114
|
+
|
|
115
|
+
no_error_validation('Not all Update Coverage Records responses were valid. See messages for more information.')
|
|
72
116
|
end
|
|
73
117
|
end
|
|
74
118
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require_relative '../../server_test_helper'
|
|
2
2
|
require_relative '../../server_hook_helper'
|
|
3
3
|
require_relative '../../../cross_suite/cards_identification'
|
|
4
|
-
require_relative '../../../cross_suite/
|
|
4
|
+
require_relative '../../../cross_suite/response_logical_model_validation'
|
|
5
5
|
|
|
6
6
|
module DaVinciCRDTestKit
|
|
7
7
|
module V221
|
|
@@ -9,38 +9,80 @@ module DaVinciCRDTestKit
|
|
|
9
9
|
include DaVinciCRDTestKit::ServerTestHelper
|
|
10
10
|
include DaVinciCRDTestKit::ServerHookHelper
|
|
11
11
|
include DaVinciCRDTestKit::CardsIdentification
|
|
12
|
-
include DaVinciCRDTestKit::
|
|
12
|
+
include DaVinciCRDTestKit::ResponseLogicalModelValidation
|
|
13
13
|
|
|
14
14
|
title 'External Reference cards are valid'
|
|
15
15
|
id :crd_v221_external_reference_card_validation
|
|
16
16
|
description %(
|
|
17
|
-
This test verifies the presence of valid External Reference cards within
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
This test verifies the presence of valid External Reference cards within
|
|
18
|
+
the CRD service responses.
|
|
19
|
+
|
|
20
|
+
As per the [Da Vinci CRD Implementation
|
|
21
|
+
Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#external-reference-response-type),
|
|
22
|
+
External Reference cards must contain links with the type set to
|
|
23
|
+
`absolute`. This test checks for the presence of any External Reference
|
|
24
|
+
cards by verifying:
|
|
22
25
|
- The presence of a `links` array within each card.
|
|
23
26
|
- That every link in the `links` array of a card is of type `absolute`.
|
|
27
|
+
|
|
28
|
+
The test will be skipped if no External Reference cards are found within
|
|
29
|
+
the returned valid cards.
|
|
24
30
|
)
|
|
25
31
|
|
|
26
|
-
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-
|
|
32
|
+
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-19',
|
|
33
|
+
'hl7.fhir.us.davinci-crd_2.2.1@resp-22'
|
|
34
|
+
|
|
35
|
+
input :invoked_hook
|
|
27
36
|
|
|
28
|
-
input :valid_cards_with_links
|
|
29
37
|
optional
|
|
30
38
|
|
|
39
|
+
def body_has_no_cards?(body)
|
|
40
|
+
!body.is_a?(Hash) ||
|
|
41
|
+
body['cards'].blank? ||
|
|
42
|
+
!body['cards'].is_a?(Array) ||
|
|
43
|
+
!body['cards'].all?(Hash)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def external_reference_cards(request)
|
|
47
|
+
return [] if request.status != 200
|
|
48
|
+
|
|
49
|
+
response_body = JSON.parse(request.response_body)
|
|
50
|
+
|
|
51
|
+
return [] if body_has_no_cards?(response_body)
|
|
52
|
+
|
|
53
|
+
response_body['cards'].select { |card| external_reference_response_type? card }
|
|
54
|
+
rescue JSON::ParserError
|
|
55
|
+
[]
|
|
56
|
+
end
|
|
57
|
+
|
|
31
58
|
run do
|
|
32
|
-
|
|
33
|
-
|
|
59
|
+
load_tagged_requests(tested_hook_name)
|
|
60
|
+
|
|
61
|
+
external_reference_count = 0
|
|
62
|
+
|
|
63
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
34
64
|
|
|
35
|
-
skip_if
|
|
36
|
-
|
|
65
|
+
skip_if successful_requests.blank?,
|
|
66
|
+
'No successful hook responses were received'
|
|
37
67
|
|
|
38
|
-
|
|
39
|
-
|
|
68
|
+
requests.each_with_index do |request, index|
|
|
69
|
+
cards = external_reference_cards(request)
|
|
70
|
+
|
|
71
|
+
external_reference_count += cards.length
|
|
72
|
+
|
|
73
|
+
perform_response_logical_model_validation(
|
|
74
|
+
cards,
|
|
75
|
+
nil,
|
|
76
|
+
request.request_body,
|
|
77
|
+
index,
|
|
78
|
+
'2.2.1'
|
|
79
|
+
)
|
|
40
80
|
end
|
|
41
81
|
|
|
42
|
-
|
|
43
|
-
|
|
82
|
+
skip_if external_reference_count.zero?,
|
|
83
|
+
"#{tested_hook_name} hook responses do not contain any External Reference cards."
|
|
84
|
+
|
|
85
|
+
no_error_validation('Not all External Reference cards were valid. See messages for more information.')
|
|
44
86
|
end
|
|
45
87
|
end
|
|
46
88
|
end
|