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
|
@@ -1,38 +1,42 @@
|
|
|
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 FormCompletionResponseValidationTest < 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 'Request Form Completion cards and system actions are valid'
|
|
17
15
|
id :crd_v221_request_form_completion_response_validation
|
|
18
16
|
description %(
|
|
19
|
-
This test validates the Request Form Completion cards or system actions
|
|
20
|
-
as per the specifications outlined in the
|
|
17
|
+
This test validates the Request Form Completion cards or system actions
|
|
18
|
+
received from the CRD service, as per the specifications outlined in the
|
|
19
|
+
[Da Vinci CRD Implementation
|
|
20
|
+
Guide](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#request-form-completion-response-type).
|
|
21
21
|
|
|
22
22
|
- **Checking for Presence:**
|
|
23
|
-
The test begins by verifying whether any Request Form Completion cards
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
The test begins by verifying whether any Request Form Completion cards
|
|
24
|
+
or system actions are present.
|
|
25
|
+
- **For cards:** It ensures that there are cards with `suggestions`
|
|
26
|
+
containing `create` actions for the `Task` resource, specifically:
|
|
26
27
|
- The `Task` must have a `code` of `complete-questionnaire`.
|
|
27
|
-
- The `Task` should include an input of type `text`
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
the
|
|
28
|
+
- The `Task` should include an input of type `text`
|
|
29
|
+
(`Task.input.type.text`) labeled as `questionnaire` and associated
|
|
30
|
+
with a valid canonical URL (`Task.input.valueCanonical`).
|
|
31
|
+
- **For system actions:** It checks for the presence of `create`
|
|
32
|
+
actions for the `Task` resource with the characteristics described
|
|
33
|
+
above.
|
|
31
34
|
|
|
32
35
|
- **Validating:**
|
|
33
|
-
If any Request Form Completion cards or system actions are found, the
|
|
34
|
-
Each `Task` resource is validated
|
|
35
|
-
|
|
36
|
+
If any Request Form Completion cards or system actions are found, the
|
|
37
|
+
test proceeds to validate them. Each `Task` resource is validated
|
|
38
|
+
against the [CRD Questionnaire Task
|
|
39
|
+
profile](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/StructureDefinition-profile-taskquestionnaire.html).
|
|
36
40
|
Additionally, if any actions for the creation of a `Questionnaire` are
|
|
37
41
|
found, the test verifies that they include the
|
|
38
42
|
`davinci-crd.if-none-exist` extension.
|
|
@@ -41,50 +45,81 @@ module DaVinciCRDTestKit
|
|
|
41
45
|
)
|
|
42
46
|
|
|
43
47
|
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@dev-20',
|
|
48
|
+
'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
|
|
44
49
|
'hl7.fhir.us.davinci-crd_2.2.1@resp-62',
|
|
45
50
|
'hl7.fhir.us.davinci-crd_2.2.1@resp-65'
|
|
46
51
|
|
|
52
|
+
input :invoked_hook
|
|
53
|
+
|
|
47
54
|
optional
|
|
48
|
-
|
|
55
|
+
|
|
56
|
+
def body_has_no_cards?(body)
|
|
57
|
+
!body.is_a?(Hash) ||
|
|
58
|
+
body['cards'].blank? ||
|
|
59
|
+
!body['cards'].is_a?(Array) ||
|
|
60
|
+
!body['cards'].all?(Hash)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def form_completion_cards(request)
|
|
64
|
+
return [] if request.status != 200
|
|
65
|
+
|
|
66
|
+
response_body = JSON.parse(request.response_body)
|
|
67
|
+
|
|
68
|
+
return [] if body_has_no_cards?(response_body)
|
|
69
|
+
|
|
70
|
+
response_body['cards'].select { |card| form_completion_card_response_type? card }
|
|
71
|
+
rescue JSON::ParserError
|
|
72
|
+
[]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def body_has_no_system_actions?(body)
|
|
76
|
+
!body.is_a?(Hash) ||
|
|
77
|
+
body['systemActions'].blank? ||
|
|
78
|
+
!body['systemActions'].is_a?(Array) ||
|
|
79
|
+
!body['systemActions'].all?(Hash)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def form_completion_actions(request)
|
|
83
|
+
return [] if request.status != 200
|
|
84
|
+
|
|
85
|
+
response_body = JSON.parse(request.response_body)
|
|
86
|
+
|
|
87
|
+
return [] if body_has_no_system_actions?(response_body)
|
|
88
|
+
|
|
89
|
+
response_body['systemActions'].select { |action| form_completion_action_response_type? action }
|
|
90
|
+
rescue JSON::ParserError
|
|
91
|
+
[]
|
|
92
|
+
end
|
|
49
93
|
|
|
50
94
|
run do
|
|
51
|
-
|
|
52
|
-
parsed_actions = parse_json(valid_system_actions)
|
|
95
|
+
load_tagged_requests(tested_hook_name)
|
|
53
96
|
|
|
54
|
-
|
|
55
|
-
form_completion_actions = parsed_actions.select { |action| form_completion_action_response_type?(action) }
|
|
97
|
+
form_completion_count = 0
|
|
56
98
|
|
|
57
|
-
|
|
58
|
-
"#{tested_hook_name} hook response does not contain any Request Form Completion cards " \
|
|
59
|
-
'or system actions.'
|
|
99
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
60
100
|
|
|
61
|
-
|
|
101
|
+
skip_if successful_requests.blank?,
|
|
102
|
+
'No successful hook responses were received'
|
|
62
103
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
card['suggestions']
|
|
67
|
-
.flat_map { |suggestion| suggestion['actions'] }
|
|
68
|
-
.compact
|
|
69
|
-
.select { |action| form_completion_action_response_type? action }
|
|
104
|
+
requests.each_with_index do |request, index|
|
|
105
|
+
cards = form_completion_cards(request)
|
|
106
|
+
actions = form_completion_actions(request)
|
|
70
107
|
|
|
71
|
-
|
|
108
|
+
form_completion_count += cards.length + actions.length
|
|
72
109
|
|
|
73
|
-
|
|
74
|
-
|
|
110
|
+
perform_response_logical_model_validation(
|
|
111
|
+
cards,
|
|
112
|
+
actions,
|
|
113
|
+
request.request_body,
|
|
114
|
+
index,
|
|
115
|
+
'2.2.1'
|
|
116
|
+
)
|
|
75
117
|
end
|
|
76
118
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
form_completion_cards
|
|
80
|
-
.flat_map { |card| card['suggestions'] }
|
|
81
|
-
.flat_map { |suggestion| suggestion['actions'] }
|
|
82
|
-
.compact
|
|
83
|
-
.select { |action| create_questionnaire_action_response_type?(action) }
|
|
84
|
-
|
|
85
|
-
questionnaire_create_actions.each { |action| questionnaire_creation_check(action) }
|
|
119
|
+
skip_if form_completion_count.zero?,
|
|
120
|
+
"#{tested_hook_name} hook responses do not contain any Request Form Completion cards or system actions."
|
|
86
121
|
|
|
87
|
-
no_error_validation('
|
|
122
|
+
no_error_validation('Not all Request Form Completion responses were valid. See messages for more information.')
|
|
88
123
|
end
|
|
89
124
|
end
|
|
90
125
|
end
|
data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/hook_request_resource_resolution.rb
CHANGED
|
@@ -34,6 +34,43 @@ module DaVinciCRDTestKit
|
|
|
34
34
|
fallback_source_resource(request_body, target_type, target_id)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
def only_coverage_information_changed?(source_resource_hash, updated_resource_hash)
|
|
38
|
+
return true if coverage_information_extension_only_payload?(updated_resource_hash)
|
|
39
|
+
|
|
40
|
+
source_without_coverage_info = normalize_value(strip_coverage_info_extensions(source_resource_hash))
|
|
41
|
+
updated_without_coverage_info = normalize_value(strip_coverage_info_extensions(updated_resource_hash))
|
|
42
|
+
|
|
43
|
+
source_without_coverage_info == updated_without_coverage_info
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def coverage_information_extension_only_payload?(resource_hash)
|
|
47
|
+
return false unless resource_hash.is_a?(Hash)
|
|
48
|
+
|
|
49
|
+
strip_coverage_info_extensions(resource_hash).keys.all? { |key| ['resourceType', 'id', 'meta'].include?(key) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def strip_coverage_info_extensions(resource_hash)
|
|
53
|
+
normalized_hash = resource_hash.deep_dup
|
|
54
|
+
return normalized_hash unless normalized_hash['extension'].is_a?(Array)
|
|
55
|
+
|
|
56
|
+
normalized_hash['extension'] = normalized_hash['extension'].reject do |extension|
|
|
57
|
+
extension['url'] == DaVinciCRDTestKit::CardsIdentification::COVERAGE_INFO_EXT_URL
|
|
58
|
+
end
|
|
59
|
+
normalized_hash.delete('extension') if normalized_hash['extension'].empty?
|
|
60
|
+
normalized_hash
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def normalize_value(value)
|
|
64
|
+
case value
|
|
65
|
+
when Hash
|
|
66
|
+
value.transform_values { |child| normalize_value(child) }
|
|
67
|
+
when Array
|
|
68
|
+
value.map { |child| normalize_value(child) }.sort_by(&:to_json)
|
|
69
|
+
else
|
|
70
|
+
value
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
37
74
|
def find_appointment_book_resource(request_body, target_type, target_id)
|
|
38
75
|
appointments_bundle = request_body.dig('context', 'appointments')
|
|
39
76
|
find_resource_in_bundle(appointments_bundle, target_type, target_id) ||
|
data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/instructions_card_received_test.rb
CHANGED
|
@@ -1,6 +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/response_logical_model_validation'
|
|
4
5
|
|
|
5
6
|
module DaVinciCRDTestKit
|
|
6
7
|
module V221
|
|
@@ -8,24 +9,74 @@ module DaVinciCRDTestKit
|
|
|
8
9
|
include DaVinciCRDTestKit::ServerTestHelper
|
|
9
10
|
include DaVinciCRDTestKit::ServerHookHelper
|
|
10
11
|
include DaVinciCRDTestKit::CardsIdentification
|
|
12
|
+
include DaVinciCRDTestKit::ResponseLogicalModelValidation
|
|
11
13
|
|
|
12
14
|
title 'Instructions cards are valid'
|
|
13
15
|
id :crd_v221_valid_instructions_card_received
|
|
14
16
|
description %(
|
|
15
|
-
This test validates that an
|
|
17
|
+
This test validates that an
|
|
18
|
+
[Instructions](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#instructions-response-type)
|
|
16
19
|
card was received. It does so by:
|
|
17
|
-
- Checking for the presence of a valid card that does not contain the
|
|
20
|
+
- Checking for the presence of a valid card that does not contain the
|
|
21
|
+
`links` field and the `suggestions` field.
|
|
22
|
+
|
|
23
|
+
The test will be skipped if no Instructions cards are found within the
|
|
24
|
+
returned valid cards.
|
|
18
25
|
)
|
|
19
26
|
|
|
20
27
|
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-24'
|
|
21
28
|
|
|
22
|
-
input :
|
|
29
|
+
input :invoked_hook
|
|
30
|
+
|
|
23
31
|
optional
|
|
24
32
|
|
|
33
|
+
def body_has_no_cards?(body)
|
|
34
|
+
!body.is_a?(Hash) ||
|
|
35
|
+
body['cards'].blank? ||
|
|
36
|
+
!body['cards'].is_a?(Array) ||
|
|
37
|
+
!body['cards'].all?(Hash)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def instructions_cards(request)
|
|
41
|
+
return [] if request.status != 200
|
|
42
|
+
|
|
43
|
+
response_body = JSON.parse(request.response_body)
|
|
44
|
+
|
|
45
|
+
return [] if body_has_no_cards?(response_body)
|
|
46
|
+
|
|
47
|
+
response_body['cards'].select { |card| instructions_response_type? card }
|
|
48
|
+
rescue JSON::ParserError
|
|
49
|
+
[]
|
|
50
|
+
end
|
|
51
|
+
|
|
25
52
|
run do
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
load_tagged_requests(tested_hook_name)
|
|
54
|
+
|
|
55
|
+
instructions_count = 0
|
|
56
|
+
|
|
57
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
58
|
+
|
|
59
|
+
skip_if successful_requests.blank?,
|
|
60
|
+
'No successful hook responses were received'
|
|
61
|
+
|
|
62
|
+
requests.each_with_index do |request, index|
|
|
63
|
+
cards = instructions_cards(request)
|
|
64
|
+
|
|
65
|
+
instructions_count += cards.length
|
|
66
|
+
|
|
67
|
+
perform_response_logical_model_validation(
|
|
68
|
+
cards,
|
|
69
|
+
nil,
|
|
70
|
+
request.request_body,
|
|
71
|
+
index,
|
|
72
|
+
'2.2.1'
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
skip_if instructions_count.zero?,
|
|
77
|
+
"#{tested_hook_name} hook responses do not contain any Instructions cards."
|
|
78
|
+
|
|
79
|
+
no_error_validation('Not all Instructions cards were valid. See messages for more information.')
|
|
29
80
|
end
|
|
30
81
|
end
|
|
31
82
|
end
|
data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/launch_smart_app_card_validation_test.rb
CHANGED
|
@@ -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,40 +9,79 @@ 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 'Launch SMART Application cards are valid'
|
|
15
15
|
id :crd_v221_launch_smart_app_card_validation
|
|
16
16
|
description %(
|
|
17
|
-
This test verifies the presence of valid Launch SMART Application cards
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
This test verifies the presence of valid Launch SMART Application cards
|
|
18
|
+
within 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#launch-smart-application-response-type),
|
|
22
|
+
Launch SMART Application cards must contain links with the type set to
|
|
23
|
+
`smart`. This test checks for the presence of any Launch SMART
|
|
24
|
+
Application cards by verifying:
|
|
22
25
|
- The existence of a `links` array within each card.
|
|
23
26
|
- That every link in the `links` array of a card is of type `smart`.
|
|
24
27
|
|
|
25
|
-
The test will be skipped if no Launch SMART Application cards are found
|
|
28
|
+
The test will be skipped if no Launch SMART Application cards are found
|
|
29
|
+
within the returned valid cards.
|
|
26
30
|
)
|
|
27
31
|
|
|
28
32
|
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-72'
|
|
29
33
|
|
|
34
|
+
input :invoked_hook
|
|
35
|
+
|
|
30
36
|
optional
|
|
31
|
-
|
|
37
|
+
|
|
38
|
+
def body_has_no_cards?(body)
|
|
39
|
+
!body.is_a?(Hash) ||
|
|
40
|
+
body['cards'].blank? ||
|
|
41
|
+
!body['cards'].is_a?(Array) ||
|
|
42
|
+
!body['cards'].all?(Hash)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def launch_smart_app_cards(request)
|
|
46
|
+
return [] if request.status != 200
|
|
47
|
+
|
|
48
|
+
response_body = JSON.parse(request.response_body)
|
|
49
|
+
|
|
50
|
+
return [] if body_has_no_cards?(response_body)
|
|
51
|
+
|
|
52
|
+
response_body['cards'].select { |card| launch_smart_app_response_type? card }
|
|
53
|
+
rescue JSON::ParserError
|
|
54
|
+
[]
|
|
55
|
+
end
|
|
32
56
|
|
|
33
57
|
run do
|
|
34
|
-
|
|
35
|
-
|
|
58
|
+
load_tagged_requests(tested_hook_name)
|
|
59
|
+
|
|
60
|
+
launch_smart_app_count = 0
|
|
61
|
+
|
|
62
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
36
63
|
|
|
37
|
-
skip_if
|
|
38
|
-
|
|
64
|
+
skip_if successful_requests.blank?,
|
|
65
|
+
'No successful hook responses were received'
|
|
39
66
|
|
|
40
|
-
|
|
41
|
-
|
|
67
|
+
requests.each_with_index do |request, index|
|
|
68
|
+
cards = launch_smart_app_cards(request)
|
|
69
|
+
|
|
70
|
+
launch_smart_app_count += cards.length
|
|
71
|
+
|
|
72
|
+
perform_response_logical_model_validation(
|
|
73
|
+
cards,
|
|
74
|
+
nil,
|
|
75
|
+
request.request_body,
|
|
76
|
+
index,
|
|
77
|
+
'2.2.1'
|
|
78
|
+
)
|
|
42
79
|
end
|
|
43
80
|
|
|
44
|
-
|
|
45
|
-
|
|
81
|
+
skip_if launch_smart_app_count.zero?,
|
|
82
|
+
"#{tested_hook_name} hook responses do not contain any Launch SMART App cards."
|
|
83
|
+
|
|
84
|
+
no_error_validation('Not all Launch SMART App cards were valid. See messages for more information.')
|
|
46
85
|
end
|
|
47
86
|
end
|
|
48
87
|
end
|
|
@@ -1,53 +1,80 @@
|
|
|
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 ProposeAlternateRequestCardValidationTest < 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 'Propose Alternate Request cards are valid'
|
|
17
15
|
id :crd_v221_propose_alternate_request_card_validation
|
|
18
|
-
description %(
|
|
19
|
-
|
|
20
|
-
cards received are valid. It checks for the presence of a card's
|
|
21
|
-
with a single action with `Action.type` of `update` or a card
|
|
22
|
-
two actions, one with `Action.type` of `delete` and the
|
|
23
|
-
`Action.type` of `create`.
|
|
16
|
+
description %( This test validates that all [Propose Alternate
|
|
17
|
+
Request](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/cards.html#propose-alternate-request-response-type)
|
|
18
|
+
cards received are valid. It checks for the presence of a card's
|
|
19
|
+
suggestion with a single action with `Action.type` of `update` or a card
|
|
20
|
+
with at least two actions, one with `Action.type` of `delete` and the
|
|
21
|
+
other with `Action.type` of `create`.
|
|
24
22
|
)
|
|
25
23
|
optional
|
|
26
24
|
|
|
27
|
-
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-
|
|
25
|
+
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-3',
|
|
26
|
+
'hl7.fhir.us.davinci-crd_2.2.1@resp-55',
|
|
28
27
|
'hl7.fhir.us.davinci-crd_2.2.1@resp-56'
|
|
29
28
|
|
|
30
|
-
input :
|
|
29
|
+
input :invoked_hook
|
|
30
|
+
|
|
31
|
+
def body_has_no_cards?(body)
|
|
32
|
+
!body.is_a?(Hash) ||
|
|
33
|
+
body['cards'].blank? ||
|
|
34
|
+
!body['cards'].is_a?(Array) ||
|
|
35
|
+
!body['cards'].all?(Hash)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def alternate_request_cards(request)
|
|
39
|
+
return [] if request.status != 200
|
|
40
|
+
|
|
41
|
+
response_body = JSON.parse(request.response_body)
|
|
42
|
+
|
|
43
|
+
return [] if body_has_no_cards?(response_body)
|
|
44
|
+
|
|
45
|
+
response_body['cards'].select { |card| propose_alternative_request_response_type? card }
|
|
46
|
+
rescue JSON::ParserError
|
|
47
|
+
[]
|
|
48
|
+
end
|
|
31
49
|
|
|
32
50
|
run do
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
propose_alternative_request_response_type?(card)
|
|
37
|
-
end
|
|
51
|
+
load_tagged_requests(tested_hook_name)
|
|
52
|
+
|
|
53
|
+
alternate_request_count = 0
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
"#{tested_hook_name} hook response does not contain a Propose Alternate Request card."
|
|
55
|
+
successful_requests = requests.select { |request| request.status == 200 }
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
actions_check(suggestion['actions'], parsed_contexts, ig_version: 'v221')
|
|
45
|
-
end
|
|
57
|
+
skip_if successful_requests.blank?,
|
|
58
|
+
'No successful hook responses were received'
|
|
46
59
|
|
|
47
|
-
|
|
60
|
+
requests.each_with_index do |request, index|
|
|
61
|
+
cards = alternate_request_cards(request)
|
|
62
|
+
|
|
63
|
+
alternate_request_count += cards.length
|
|
64
|
+
|
|
65
|
+
perform_response_logical_model_validation(
|
|
66
|
+
cards,
|
|
67
|
+
nil,
|
|
68
|
+
request.request_body,
|
|
69
|
+
index,
|
|
70
|
+
'2.2.1'
|
|
71
|
+
)
|
|
48
72
|
end
|
|
49
73
|
|
|
50
|
-
|
|
74
|
+
skip_if alternate_request_count.zero?,
|
|
75
|
+
"#{tested_hook_name} hook responses do not contain any Propose Alternate Request cards."
|
|
76
|
+
|
|
77
|
+
no_error_validation('Not all Propose Alternate Request cards were valid. See messages for more information')
|
|
51
78
|
end
|
|
52
79
|
end
|
|
53
80
|
end
|
data/lib/davinci_crd_test_kit/server/v2.2.1/verify_response/service_response_validation_test.rb
CHANGED
|
@@ -12,83 +12,49 @@ module DaVinciCRDTestKit
|
|
|
12
12
|
title 'Service responses contain valid cards and systemActions'
|
|
13
13
|
id :crd_v221_service_response_validation
|
|
14
14
|
description %(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
successful server's response to a service request must be a JSON object
|
|
18
|
-
containing a `cards` array and optionally a `systemActions` array.
|
|
15
|
+
This test validates the responses against the [CRD v2.2.1 logical
|
|
16
|
+
models](https://hl7.org/fhir/us/davinci-crd/2.2.1/en/artifacts.html#4).
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
This test implements [corrections to errors in the logical
|
|
19
|
+
models](https://github.com/inferno-framework/davinci-crd-test-kit/wiki/Logical-Model-Validation-Changes).
|
|
22
20
|
)
|
|
23
21
|
|
|
24
22
|
verifies_requirements 'hl7.fhir.us.davinci-crd_2.2.1@resp-4',
|
|
25
23
|
'hl7.fhir.us.davinci-crd_2.2.1@resp-5',
|
|
26
|
-
'hl7.fhir.us.davinci-crd_2.2.1@resp-13'
|
|
27
|
-
'hl7.fhir.us.davinci-crd_2.2.1@resp-22',
|
|
28
|
-
'hl7.fhir.us.davinci-crd_2.2.1@resp-24',
|
|
29
|
-
'hl7.fhir.us.davinci-crd_2.2.1@resp-56'
|
|
24
|
+
'hl7.fhir.us.davinci-crd_2.2.1@resp-13'
|
|
30
25
|
|
|
31
26
|
input :invoked_hook
|
|
32
|
-
output :valid_cards, :valid_system_actions
|
|
33
|
-
|
|
34
|
-
SYSTEM_ACTIONS_HOOK_NAMES = ['appointment-book', 'order-sign', 'order-dispatch'].freeze
|
|
35
|
-
|
|
36
|
-
def valid_cards
|
|
37
|
-
@valid_cards ||= []
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def valid_system_actions
|
|
41
|
-
@valid_system_actions ||= []
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def system_actions_check(system_actions)
|
|
45
|
-
system_actions.each do |action|
|
|
46
|
-
current_error_count = messages.count { |msg| msg[:type] == 'error' }
|
|
47
|
-
action_fields_validation(action, ig_version: 'v221')
|
|
48
|
-
valid_system_actions << action if current_error_count == messages.count { |msg| msg[:type] == 'error' }
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def perform_system_actions_validation(system_actions, response_index)
|
|
53
|
-
if SYSTEM_ACTIONS_HOOK_NAMES.include?(invoked_hook) && system_actions.nil?
|
|
54
|
-
msg = "Server response #{response_index + 1} did not have the `systemActions` field, " \
|
|
55
|
-
"which must be present for the `#{invoked_hook}` hook."
|
|
56
|
-
add_message('error', msg)
|
|
57
|
-
end
|
|
58
|
-
return if system_actions.nil?
|
|
59
|
-
|
|
60
|
-
unless system_actions.is_a?(Array)
|
|
61
|
-
add_message('error', "`systemActions` of server response #{response_index + 1} is not an array.")
|
|
62
|
-
return
|
|
63
|
-
end
|
|
64
|
-
system_actions_check(system_actions)
|
|
65
|
-
end
|
|
66
27
|
|
|
67
28
|
run do
|
|
68
29
|
load_tagged_requests(tested_hook_name)
|
|
30
|
+
|
|
69
31
|
skip_if requests.blank?, "No #{tested_hook_name} request was made in a previous test as expected."
|
|
32
|
+
|
|
70
33
|
successful_requests = requests.select { |request| request.status == 200 }
|
|
34
|
+
|
|
71
35
|
skip_if successful_requests.empty?, 'All service requests were unsuccessful.'
|
|
72
36
|
|
|
73
37
|
info do
|
|
74
38
|
unsuccessful_count = (requests - successful_requests).length
|
|
39
|
+
|
|
75
40
|
assert unsuccessful_count.zero?, "#{unsuccessful_count} out of #{requests.length} requests were unsuccessful"
|
|
76
41
|
end
|
|
77
42
|
|
|
78
43
|
successful_requests.each_with_index do |request, index|
|
|
79
44
|
service_response = JSON.parse(request.response_body)
|
|
80
|
-
perform_cards_validation(service_response['cards'], service_response['systemActions'].present?, 'v221', index)
|
|
81
45
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
46
|
+
conforms_to_logical_model?(
|
|
47
|
+
service_response,
|
|
48
|
+
'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/CRDHooksResponseBase|2.2.1',
|
|
49
|
+
message_prefix: "Request #{index}: "
|
|
50
|
+
)
|
|
86
51
|
rescue JSON::ParserError
|
|
87
52
|
add_message('error', "Invalid JSON: server response #{index + 1} is not valid JSON.")
|
|
88
53
|
end
|
|
89
54
|
|
|
90
|
-
|
|
91
|
-
|
|
55
|
+
messages.reject! do |message|
|
|
56
|
+
message[:type] == 'error' && message[:message].end_with?('Resource requires an id, but none is present')
|
|
57
|
+
end
|
|
92
58
|
|
|
93
59
|
no_error_validation('Some service responses are not valid. Check messages for issues found.')
|
|
94
60
|
end
|