davinci_dtr_test_kit 0.15.2 → 0.16.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/full_ehr_postman_dinner_order_example.json.erb +41 -0
- data/config/presets/full_ehr_postman_respiratory_device_example.json +1 -1
- data/config/presets/light_ehr_ref_server_prod.json +7 -10
- data/config/presets/payer_server_run_against_smart_app_tests.json +6 -3
- data/config/presets/smart_app_postman_dinner_order_example.json +8 -1
- data/config/presets/smart_app_postman_respiratory_device_example.json +1 -1
- data/lib/davinci_dtr_test_kit/certs/InfernoCA.key +52 -0
- data/lib/davinci_dtr_test_kit/certs/InfernoCA.pem +35 -0
- data/lib/davinci_dtr_test_kit/certs/TestKit.pem +32 -0
- data/lib/davinci_dtr_test_kit/certs/TestKitPrivateKey.key +28 -0
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_custom_next_question_response_validation_test.rb +95 -0
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_full_ehr_custom_adaptive_request_test.rb +87 -0
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_full_ehr_custom_adaptive_workflow_group.rb +136 -0
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_smart_app_custom_adaptive_request_test.rb +171 -0
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/custom/dtr_smart_app_custom_adaptive_workflow_group.rb +146 -0
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_next_question_retrieval_group.rb +3 -3
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_full_ehr_adaptive_dinner_workflow_group.rb +21 -11
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_full_ehr_adaptive_initial_retrieval_group.rb +6 -6
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_smart_app_adaptive_dinner_workflow_group.rb +5 -5
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_smart_app_adaptive_initial_retrieval_group.rb +5 -5
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire}/dtr_adaptive_next_question_request_test.rb +9 -24
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire}/dtr_adaptive_next_question_request_validation_test.rb +36 -17
- data/lib/davinci_dtr_test_kit/client_groups/adaptive_questionnaire/dtr_adaptive_response_validation_test.rb +130 -0
- data/lib/davinci_dtr_test_kit/client_groups/auth/dtr_client_payer_auth_smart_group.rb +29 -0
- data/lib/davinci_dtr_test_kit/client_groups/auth/dtr_client_payer_auth_udap_group.rb +29 -0
- data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_full_ehr_custom_static_workflow_group.rb +15 -14
- data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_smart_app_custom_static_workflow_group.rb +5 -5
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_static_dinner_workflow_group.rb +14 -10
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_static_dinner_workflow_group.rb +1 -1
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → full_ehr}/dtr_full_ehr_adaptive_request_test.rb +11 -14
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_package_request_test.rb +9 -17
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_correctness_test.rb +10 -1
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_store_attestation_test.rb +3 -3
- data/lib/davinci_dtr_test_kit/client_groups/light_ehr/fhir_context_references_test.rb +4 -5
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_full_ehr_ms_questionnaire_package_request_test.rb +75 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_full_ehr_questionnaire_must_support_group.rb +85 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_must_support_attestation_test.rb +39 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_questionnaire_must_support_test.rb +42 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_smart_app_ms_questionnaire_package_request_test.rb +148 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/dtr_smart_app_questionnaire_must_support_group.rb +85 -0
- data/lib/davinci_dtr_test_kit/client_groups/must_support/questionnaire_must_support_elements.rb +55 -0
- data/lib/davinci_dtr_test_kit/client_groups/payer_registration/configuration_display_smart_test.rb +35 -0
- data/lib/davinci_dtr_test_kit/client_groups/payer_registration/configuration_display_udap_test.rb +35 -0
- data/lib/davinci_dtr_test_kit/client_groups/payer_registration/dtr_client_registration_group.rb +48 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_custom_questionnaire_expressions_test.rb +36 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_custom_questionnaire_extensions_test.rb +32 -0
- data/lib/davinci_dtr_test_kit/client_groups/{custom_static → shared}/dtr_custom_questionnaire_libraries_test.rb +7 -2
- data/lib/davinci_dtr_test_kit/client_groups/{custom_static → shared}/dtr_custom_questionnaire_package_validation_test.rb +6 -2
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb +6 -2
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_prepopulation_test.rb +7 -1
- data/lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_questionnaire_response_correctness_test.rb +4 -3
- data/lib/davinci_dtr_test_kit/descriptions.rb +8 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md +145 -78
- data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +4 -3
- data/lib/davinci_dtr_test_kit/dtr_client_options.rb +13 -0
- data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +47 -7
- data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +33 -6
- data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +4 -4
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +33 -21
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +7 -4
- data/lib/davinci_dtr_test_kit/endpoints/mock_ehr.rb +1 -1
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +20 -1
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +21 -1
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_endpoint.rb +29 -4
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_proxy_endpoint.rb +6 -2
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_endpoint.rb +1 -1
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_proxy_endpoint.rb +6 -2
- data/lib/davinci_dtr_test_kit/endpoints/mock_udap_smart_server/token_endpoint.rb +36 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_group.rb +1 -1
- data/lib/davinci_dtr_test_kit/requirements/davinci-dtr-test-kit_out_of_scope_requirements.csv +6 -5
- data/lib/davinci_dtr_test_kit/requirements/davinci-dtr-test-kit_requirements.csv +10 -9
- data/lib/davinci_dtr_test_kit/requirements/generated/davinci-dtr-test-kit_requirements_coverage.csv +21 -21
- data/lib/davinci_dtr_test_kit/urls.rb +21 -4
- data/lib/davinci_dtr_test_kit/version.rb +2 -2
- metadata +63 -25
- data/config/presets/full_ehr_postman_dinner_order_example_postman.json +0 -19
- data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_custom_questionnaire_expressions_test.rb +0 -22
- data/lib/davinci_dtr_test_kit/client_groups/custom_static/dtr_custom_questionnaire_extensions_test.rb +0 -19
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_response_validation_test.rb +0 -68
- /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_completion_group.rb +0 -0
- /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → adaptive_questionnaire/dinner_order}/dtr_adaptive_followup_questions_group.rb +0 -0
- /data/lib/davinci_dtr_test_kit/client_groups/{dinner_adaptive → smart_app}/dtr_smart_app_adaptive_request_test.rb +0 -0
@@ -1,12 +1,19 @@
|
|
1
|
+
require 'udap_security_test_kit'
|
2
|
+
require 'smart_app_launch_test_kit'
|
1
3
|
require_relative 'client_groups/custom_static/dtr_full_ehr_custom_static_workflow_group'
|
2
4
|
require_relative 'client_groups/dinner_static/dtr_full_ehr_static_dinner_workflow_group'
|
3
|
-
require_relative 'client_groups/
|
4
|
-
require_relative '
|
5
|
+
require_relative 'client_groups/adaptive_questionnaire/dinner_order/dtr_full_ehr_adaptive_dinner_workflow_group'
|
6
|
+
require_relative 'client_groups/adaptive_questionnaire/custom/dtr_full_ehr_custom_adaptive_workflow_group'
|
7
|
+
require_relative 'client_groups/payer_registration/dtr_client_registration_group'
|
8
|
+
require_relative 'client_groups/must_support/dtr_full_ehr_questionnaire_must_support_group'
|
9
|
+
require_relative 'client_groups/auth/dtr_client_payer_auth_smart_group'
|
10
|
+
require_relative 'client_groups/auth/dtr_client_payer_auth_udap_group'
|
5
11
|
require_relative 'endpoints/cors'
|
6
|
-
require_relative 'endpoints/
|
12
|
+
require_relative 'endpoints/mock_udap_smart_server/token_endpoint'
|
7
13
|
require_relative 'endpoints/mock_payer/full_ehr_questionnaire_package_endpoint'
|
8
14
|
require_relative 'endpoints/mock_payer/full_ehr_next_question_endpoint'
|
9
15
|
require_relative 'version'
|
16
|
+
require_relative 'dtr_client_options'
|
10
17
|
|
11
18
|
module DaVinciDTRTestKit
|
12
19
|
class DTRFullEHRSuite < Inferno::TestSuite
|
@@ -35,9 +42,22 @@ module DaVinciDTRTestKit
|
|
35
42
|
}
|
36
43
|
]
|
37
44
|
|
45
|
+
suite_option :client_type,
|
46
|
+
title: 'Client Security Type',
|
47
|
+
list_options: [
|
48
|
+
{
|
49
|
+
label: 'SMART Backend Services',
|
50
|
+
value: DTRClientOptions::SMART_BACKEND_SERVICES_CONFIDENTIAL_ASYMMETRIC
|
51
|
+
},
|
52
|
+
{
|
53
|
+
label: 'UDAP B2B Client Credentials',
|
54
|
+
value: DTRClientOptions::UDAP_CLIENT_CREDENTIALS
|
55
|
+
}
|
56
|
+
]
|
57
|
+
|
38
58
|
# Hl7 Validator Wrapper:
|
39
59
|
fhir_resource_validator do
|
40
|
-
igs '
|
60
|
+
igs 'igs/davinci_dtr_2.0.1.tgz'
|
41
61
|
|
42
62
|
exclude_message do |message|
|
43
63
|
message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
|
@@ -46,7 +66,16 @@ module DaVinciDTRTestKit
|
|
46
66
|
|
47
67
|
allow_cors QUESTIONNAIRE_PACKAGE_PATH, NEXT_PATH
|
48
68
|
|
49
|
-
|
69
|
+
route(:get, UDAPSecurityTestKit::UDAP_DISCOVERY_PATH, lambda { |_env|
|
70
|
+
UDAPSecurityTestKit::MockUDAPServer.udap_server_metadata(id)
|
71
|
+
})
|
72
|
+
route(:get, SMARTAppLaunch::SMART_DISCOVERY_PATH, lambda { |_env|
|
73
|
+
SMARTAppLaunch::MockSMARTServer.smart_server_metadata(id)
|
74
|
+
})
|
75
|
+
|
76
|
+
suite_endpoint :post, UDAPSecurityTestKit::REGISTRATION_PATH,
|
77
|
+
UDAPSecurityTestKit::MockUDAPServer::RegistrationEndpoint
|
78
|
+
suite_endpoint :post, UDAPSecurityTestKit::TOKEN_PATH, MockUdapSmartServer::TokenEndpoint
|
50
79
|
|
51
80
|
suite_endpoint :post, QUESTIONNAIRE_PACKAGE_PATH, MockPayer::FullEHRQuestionnairePackageEndpoint
|
52
81
|
suite_endpoint :post, NEXT_PATH, MockPayer::FullEHRNextQuestionEndpoint
|
@@ -59,13 +88,13 @@ module DaVinciDTRTestKit
|
|
59
88
|
request.query_parameters['token']
|
60
89
|
end
|
61
90
|
|
62
|
-
group from: :
|
91
|
+
group from: :dtr_client_payer_registration
|
63
92
|
group do
|
64
93
|
id :dtr_full_ehr_basic_workflows
|
65
94
|
title 'Basic Workflows'
|
66
95
|
|
67
96
|
group from: :dtr_full_ehr_custom_static_workflow
|
68
|
-
group from: :
|
97
|
+
group from: :dtr_full_ehr_custom_adaptive_workflow
|
69
98
|
end
|
70
99
|
group do
|
71
100
|
id :dtr_full_ehr_questionnaire_functionality
|
@@ -75,6 +104,17 @@ module DaVinciDTRTestKit
|
|
75
104
|
covering additional pre-population features of questionnaires.
|
76
105
|
)
|
77
106
|
group from: :dtr_full_ehr_static_dinner_workflow
|
107
|
+
group from: :dtr_full_ehr_adaptive_dinner_workflow
|
78
108
|
end
|
109
|
+
group from: :dtr_full_ehr_questionnaire_ms
|
110
|
+
|
111
|
+
group from: :dtr_client_payer_auth_smart,
|
112
|
+
required_suite_options: {
|
113
|
+
client_type: DTRClientOptions::SMART_BACKEND_SERVICES_CONFIDENTIAL_ASYMMETRIC
|
114
|
+
}
|
115
|
+
group from: :dtr_client_payer_auth_udap,
|
116
|
+
required_suite_options: {
|
117
|
+
client_type: DTRClientOptions::UDAP_CLIENT_CREDENTIALS
|
118
|
+
}
|
79
119
|
end
|
80
120
|
end
|
@@ -65,6 +65,24 @@ module DaVinciDTRTestKit
|
|
65
65
|
group do
|
66
66
|
title 'Authorization'
|
67
67
|
|
68
|
+
config(
|
69
|
+
inputs: {
|
70
|
+
smart_auth_info: {
|
71
|
+
name: :smart_auth_info,
|
72
|
+
title: 'EHR Launch Credentials',
|
73
|
+
options: {
|
74
|
+
mode: 'auth',
|
75
|
+
components: [
|
76
|
+
Inferno::DSL::AuthInfo.default_auth_type_component_without_backend_services
|
77
|
+
]
|
78
|
+
}
|
79
|
+
}
|
80
|
+
},
|
81
|
+
outputs: {
|
82
|
+
smart_auth_info: { name: :smart_auth_info }
|
83
|
+
}
|
84
|
+
)
|
85
|
+
|
68
86
|
group from: :smart_discovery_stu2 do
|
69
87
|
required_suite_options DTROptions::SMART_2_REQUIREMENT
|
70
88
|
run_as_group
|
@@ -98,8 +116,7 @@ module DaVinciDTRTestKit
|
|
98
116
|
id_token: { name: :id_token },
|
99
117
|
client_id: { name: :client_id },
|
100
118
|
requested_scopes: { name: :requested_scopes },
|
101
|
-
access_token: { name: :access_token }
|
102
|
-
smart_credentials: { name: :smart_credentials }
|
119
|
+
access_token: { name: :access_token }
|
103
120
|
}
|
104
121
|
}
|
105
122
|
end
|
@@ -117,6 +134,17 @@ module DaVinciDTRTestKit
|
|
117
134
|
title: 'FHIR Server Base Url',
|
118
135
|
description: 'URL of the target DTR Light EHR'
|
119
136
|
|
137
|
+
config(
|
138
|
+
inputs: {
|
139
|
+
smart_auth_info: {
|
140
|
+
title: 'OAuth Credentials',
|
141
|
+
options: {
|
142
|
+
mode: 'access'
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
)
|
147
|
+
|
120
148
|
group from: :'us_core_v311-us_core_v311_fhir_api',
|
121
149
|
run_as_group: true,
|
122
150
|
verifies_requirements: ['hl7.fhir.us.davinci-dtr_2.0.1@2', 'hl7.fhir.us.davinci-dtr_2.0.1@281']
|
@@ -131,15 +159,14 @@ module DaVinciDTRTestKit
|
|
131
159
|
)
|
132
160
|
run_as_group
|
133
161
|
|
134
|
-
input :
|
135
|
-
|
136
|
-
type: :oauth_credentials,
|
162
|
+
input :smart_auth_info,
|
163
|
+
type: :auth_info,
|
137
164
|
optional: true
|
138
165
|
|
139
166
|
# All FHIR requests in this suite will use this FHIR client
|
140
167
|
fhir_client do
|
141
168
|
url :url
|
142
|
-
|
169
|
+
auth_info :smart_auth_info
|
143
170
|
end
|
144
171
|
|
145
172
|
group from: :questionnaire_response_group
|
@@ -71,9 +71,9 @@ module DaVinciDTRTestKit
|
|
71
71
|
title: 'Custom Endpoint for Accessing a Particular Resource',
|
72
72
|
description: 'Either Flow (optional)'
|
73
73
|
|
74
|
-
input :
|
74
|
+
input :smart_auth_info,
|
75
75
|
title: 'OAuth Credentials',
|
76
|
-
type: :
|
76
|
+
type: :auth_info,
|
77
77
|
optional: true
|
78
78
|
|
79
79
|
input_order :retrieval_method,
|
@@ -83,12 +83,12 @@ module DaVinciDTRTestKit
|
|
83
83
|
:initial_static_questionnaire_request,
|
84
84
|
:initial_adaptive_questionnaire_request,
|
85
85
|
:next_question_requests,
|
86
|
-
:
|
86
|
+
:smart_auth_info
|
87
87
|
|
88
88
|
# All FHIR requests in this suite will use this FHIR client
|
89
89
|
fhir_client do
|
90
90
|
url :url
|
91
|
-
|
91
|
+
auth_info :smart_auth_info
|
92
92
|
end
|
93
93
|
|
94
94
|
# Hl7 Validator Wrapper:
|
@@ -29,14 +29,7 @@ module DaVinciDTRTestKit
|
|
29
29
|
"Couldn't find Questionnaire #{qr.questionnaire} in the provided custom questionnaire package
|
30
30
|
to validate the QuestionnaireResponse."
|
31
31
|
|
32
|
-
|
33
|
-
unless missing_origin_sources.empty?
|
34
|
-
add_message(
|
35
|
-
'error',
|
36
|
-
'All origin sources (auto, manual, override) must be present in the QuestionnaireResponse. ' \
|
37
|
-
"Missing #{missing_origin_sources.to_sentence}"
|
38
|
-
)
|
39
|
-
end
|
32
|
+
check_missing_origin_sources(qr)
|
40
33
|
end
|
41
34
|
|
42
35
|
check_origin_sources(questionnaire.item, qr.item, expected_overrides:)
|
@@ -46,6 +39,18 @@ module DaVinciDTRTestKit
|
|
46
39
|
assert(messages.none? { |m| m[:type] == 'error' }, 'QuestionnaireResponse is not correct, see error message(s)')
|
47
40
|
end
|
48
41
|
|
42
|
+
def check_missing_origin_sources(questionnaire_response, index = nil)
|
43
|
+
missing_origin_sources = ['auto', 'manual', 'override'] - extract_origin_sources(questionnaire_response.item)
|
44
|
+
return if missing_origin_sources.empty?
|
45
|
+
|
46
|
+
prefix = index ? "Request #{index}: " : ''
|
47
|
+
add_message(
|
48
|
+
'error',
|
49
|
+
"#{prefix}All origin sources (auto, manual, override) must be present in the QuestionnaireResponse. " \
|
50
|
+
"Missing #{missing_origin_sources.to_sentence}"
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
49
54
|
def check_is_questionnaire_response(questionnaire_response_json)
|
50
55
|
assert_valid_json(questionnaire_response_json)
|
51
56
|
questionnaire_response = begin
|
@@ -65,9 +70,10 @@ module DaVinciDTRTestKit
|
|
65
70
|
end
|
66
71
|
|
67
72
|
# This only checks answers in the questionnaire response, meaning it does not catch missing answers
|
68
|
-
def check_origin_sources(questionnaire_items, response_items, expected_overrides: [])
|
73
|
+
def check_origin_sources(questionnaire_items, response_items, expected_overrides: [], index: nil)
|
74
|
+
prefix = index ? "Request #{index}: " : ''
|
69
75
|
response_items&.each do |response_item|
|
70
|
-
check_origin_sources(questionnaire_items, response_item.item, expected_overrides:)
|
76
|
+
check_origin_sources(questionnaire_items, response_item.item, expected_overrides:, index:)
|
71
77
|
next unless response_item.answer&.any?
|
72
78
|
|
73
79
|
link_id = response_item.linkId
|
@@ -76,20 +82,25 @@ module DaVinciDTRTestKit
|
|
76
82
|
is_cql_expression = item_is_cql_expression?(questionnaire_item)
|
77
83
|
|
78
84
|
if origin_source.nil?
|
79
|
-
add_message('error', "Required `origin.source` extension not present on answer to item `#{link_id}`")
|
85
|
+
add_message('error', "#{prefix}Required `origin.source` extension not present on answer to item `#{link_id}`")
|
80
86
|
else
|
81
|
-
check_origin_source(
|
87
|
+
check_origin_source(
|
88
|
+
origin_source, link_id, is_cql_expression,
|
89
|
+
override: expected_overrides.include?(link_id),
|
90
|
+
index:
|
91
|
+
)
|
82
92
|
end
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
86
|
-
def check_origin_source(origin_source, link_id, is_cql_expression, override: false)
|
96
|
+
def check_origin_source(origin_source, link_id, is_cql_expression, override: false, index: nil) # rubocop:disable Metrics/CyclomaticComplexity
|
97
|
+
prefix = index ? "Request #{index}: " : ''
|
87
98
|
if override
|
88
|
-
origin_source_error(link_id, ['override'], origin_source) unless origin_source == 'override'
|
99
|
+
origin_source_error(link_id, ['override'], origin_source, prefix) unless origin_source == 'override'
|
89
100
|
elsif is_cql_expression && !['auto', 'override'].include?(origin_source)
|
90
|
-
origin_source_error(link_id, 'auto or override', origin_source)
|
101
|
+
origin_source_error(link_id, 'auto or override', origin_source, prefix)
|
91
102
|
elsif !is_cql_expression && origin_source != 'manual'
|
92
|
-
origin_source_error(link_id, 'manual', origin_source)
|
103
|
+
origin_source_error(link_id, 'manual', origin_source, prefix)
|
93
104
|
end
|
94
105
|
end
|
95
106
|
|
@@ -104,11 +115,13 @@ module DaVinciDTRTestKit
|
|
104
115
|
|
105
116
|
# Ensures that all required questions have been answered.
|
106
117
|
# If required_link_ids not provided, all questions are treated as optional.
|
107
|
-
def check_answer_presence(response_items, required_link_ids = [])
|
118
|
+
def check_answer_presence(response_items, required_link_ids = [], index = nil)
|
119
|
+
prefix = index ? "Request #{index}: " : ''
|
120
|
+
|
108
121
|
required_link_ids.each do |link_id|
|
109
122
|
item = find_item_by_link_id(response_items, link_id)
|
110
123
|
unless item&.answer&.any? { |answer| answer.value.present? }
|
111
|
-
add_message('error', "No answer for item #{link_id}")
|
124
|
+
add_message('error', "#{prefix}No answer for item #{link_id}")
|
112
125
|
end
|
113
126
|
end
|
114
127
|
end
|
@@ -176,7 +189,6 @@ module DaVinciDTRTestKit
|
|
176
189
|
questionnaire_cql_expression_link_ids,
|
177
190
|
expected_prepopulated = {},
|
178
191
|
expected_overrides = {})
|
179
|
-
|
180
192
|
questionnaire_cql_expression_link_ids.each do |target_link_id|
|
181
193
|
target_item = find_item_by_link_id(template_questionnaire_response.item, target_link_id)
|
182
194
|
raise "Template QuestionnaireResponse missing item with link id `#{target_link_id}`" unless target_item.present?
|
@@ -235,8 +247,8 @@ module DaVinciDTRTestKit
|
|
235
247
|
end
|
236
248
|
end
|
237
249
|
|
238
|
-
def origin_source_error(link_id, expected, actual)
|
239
|
-
add_message('error', %(`origin.source` extension on item `#{link_id}` contains unexpected value.
|
250
|
+
def origin_source_error(link_id, expected, actual, msg_prefix = nil)
|
251
|
+
add_message('error', %(#{msg_prefix}`origin.source` extension on item `#{link_id}` contains unexpected value.
|
240
252
|
Expected: #{expected}. Found: #{actual}))
|
241
253
|
end
|
242
254
|
|
@@ -1,8 +1,10 @@
|
|
1
1
|
require_relative 'auth_groups/oauth2_authentication_group'
|
2
2
|
require_relative 'client_groups/respiratory/dtr_smart_app_respiratory_workflow_group'
|
3
3
|
require_relative 'client_groups/dinner_static/dtr_smart_app_static_dinner_workflow_group'
|
4
|
-
require_relative 'client_groups/
|
4
|
+
require_relative 'client_groups/adaptive_questionnaire/dinner_order/dtr_smart_app_adaptive_dinner_workflow_group'
|
5
5
|
require_relative 'client_groups/custom_static/dtr_smart_app_custom_static_workflow_group'
|
6
|
+
require_relative 'client_groups/adaptive_questionnaire/custom/dtr_smart_app_custom_adaptive_workflow_group'
|
7
|
+
require_relative 'client_groups/must_support/dtr_smart_app_questionnaire_must_support_group'
|
6
8
|
require_relative 'endpoints/cors'
|
7
9
|
require_relative 'endpoints/mock_authorization'
|
8
10
|
require_relative 'endpoints/mock_authorization/authorize_endpoint'
|
@@ -43,7 +45,7 @@ module DaVinciDTRTestKit
|
|
43
45
|
|
44
46
|
# Hl7 Validator Wrapper:
|
45
47
|
fhir_resource_validator do
|
46
|
-
igs '
|
48
|
+
igs 'igs/davinci_dtr_2.0.1.tgz'
|
47
49
|
|
48
50
|
exclude_message do |message|
|
49
51
|
message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
|
@@ -90,10 +92,9 @@ module DaVinciDTRTestKit
|
|
90
92
|
)
|
91
93
|
|
92
94
|
group from: :dtr_smart_app_custom_static_workflow
|
93
|
-
group from: :
|
95
|
+
group from: :dtr_smart_app_custom_adaptive_workflow
|
94
96
|
end
|
95
97
|
group do
|
96
|
-
id :dtr_smart_app_questionnaire_functionality
|
97
98
|
title 'Questionnaire Functionality Coverage'
|
98
99
|
description %(
|
99
100
|
Tests in this group validate that the client can complete additional DTR workflows
|
@@ -101,6 +102,8 @@ module DaVinciDTRTestKit
|
|
101
102
|
)
|
102
103
|
group from: :dtr_smart_app_resp_workflow
|
103
104
|
group from: :dtr_smart_app_static_dinner_workflow
|
105
|
+
group from: :dtr_smart_app_adaptive_dinner_workflow
|
104
106
|
end
|
107
|
+
group from: :dtr_smart_app_questionnaire_ms
|
105
108
|
end
|
106
109
|
end
|
@@ -21,7 +21,7 @@ module DaVinciDTRTestKit
|
|
21
21
|
# Overwrite the OAuth URIs returned by the reference server to point to the suite endpoints instead
|
22
22
|
oauth_uris_url = 'http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris'
|
23
23
|
base_url = MockAuthorization.env_base_url(env, METADATA_PATH)
|
24
|
-
sec_ext = cs.rest.first&.security&.extension&.delete_if { |e| e.url == oauth_uris_url }
|
24
|
+
sec_ext = cs.rest.first&.security&.extension&.delete_if { |e| e.url == oauth_uris_url } # rubocop:disable Style/SafeNavigationChainLength
|
25
25
|
sec_ext&.push(
|
26
26
|
FHIR::Extension.new(
|
27
27
|
url: oauth_uris_url,
|
@@ -4,7 +4,26 @@ module DaVinciDTRTestKit
|
|
4
4
|
module MockPayer
|
5
5
|
class FullEHRNextQuestionEndpoint < NextQuestionEndpoint
|
6
6
|
def test_run_identifier
|
7
|
-
request.
|
7
|
+
return request.params[:session_path] if request.params[:session_path].present?
|
8
|
+
|
9
|
+
UDAPSecurityTestKit::MockUDAPServer.issued_token_to_client_id(
|
10
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def make_response
|
15
|
+
return if response.status == 401 # set in update_result (expired token handling there)
|
16
|
+
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_result
|
21
|
+
if UDAPSecurityTestKit::MockUDAPServer.request_has_expired_token?(request)
|
22
|
+
UDAPSecurityTestKit::MockUDAPServer.update_response_for_expired_token(response, 'Bearer token')
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
super
|
8
27
|
end
|
9
28
|
end
|
10
29
|
end
|
data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb
CHANGED
@@ -1,10 +1,30 @@
|
|
1
|
+
require 'udap_security_test_kit'
|
1
2
|
require_relative 'questionnaire_package_endpoint'
|
2
3
|
|
3
4
|
module DaVinciDTRTestKit
|
4
5
|
module MockPayer
|
5
6
|
class FullEHRQuestionnairePackageEndpoint < QuestionnairePackageEndpoint
|
6
7
|
def test_run_identifier
|
7
|
-
request.
|
8
|
+
return request.params[:session_path] if request.params[:session_path].present?
|
9
|
+
|
10
|
+
UDAPSecurityTestKit::MockUDAPServer.issued_token_to_client_id(
|
11
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def make_response
|
16
|
+
return if response.status == 401 # set in update_result (expired token handling there)
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_result
|
22
|
+
if UDAPSecurityTestKit::MockUDAPServer.request_has_expired_token?(request)
|
23
|
+
UDAPSecurityTestKit::MockUDAPServer.update_response_for_expired_token(response, 'Bearer token')
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
super
|
8
28
|
end
|
9
29
|
end
|
10
30
|
end
|
@@ -22,6 +22,29 @@ module DaVinciDTRTestKit
|
|
22
22
|
response.body = build_questionnaire_next_response.to_json
|
23
23
|
end
|
24
24
|
|
25
|
+
def custom_next_question_requests
|
26
|
+
requests_repo.tagged_requests(test_run.test_session_id, ["custom_#{DaVinciDTRTestKit::CLIENT_NEXT_TAG}"])
|
27
|
+
end
|
28
|
+
|
29
|
+
def custom_questionnaires
|
30
|
+
return @custom_questionnaires unless @custom_questionnaires.nil?
|
31
|
+
|
32
|
+
questionnaires = JSON.parse(result.input_json)
|
33
|
+
.find { |input| input['name'].include?('custom_next_question_questionnaires') }
|
34
|
+
&.dig('value')
|
35
|
+
return unless questionnaires
|
36
|
+
|
37
|
+
@custom_questionnaires = [JSON.parse(questionnaires)].flatten.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
def next_custom_questionnaire
|
41
|
+
custom_questionnaires[custom_next_question_requests.length]
|
42
|
+
end
|
43
|
+
|
44
|
+
def complete_questionnaire?
|
45
|
+
custom_questionnaires && next_custom_questionnaire.blank?
|
46
|
+
end
|
47
|
+
|
25
48
|
def update_result
|
26
49
|
results_repo.update_result(result.id, 'pass') unless test.config.options[:accepts_multiple_requests]
|
27
50
|
end
|
@@ -41,9 +64,9 @@ module DaVinciDTRTestKit
|
|
41
64
|
|
42
65
|
questionnaire_response_param = FHIR::Parameters::Parameter.new(name: 'return', resource: questionnaire_response)
|
43
66
|
|
44
|
-
if questionnaire_last_dinner_order_question_present?(questionnaire_response)
|
67
|
+
if complete_questionnaire? || questionnaire_last_dinner_order_question_present?(questionnaire_response)
|
45
68
|
# change the questionnaire response status to completed and return the parameters
|
46
|
-
return
|
69
|
+
return complete_questionnaire(questionnaire_response)
|
47
70
|
end
|
48
71
|
|
49
72
|
next_questionnaire = determine_next_questionnaire(questionnaire_response, test.id)
|
@@ -103,15 +126,17 @@ module DaVinciDTRTestKit
|
|
103
126
|
end
|
104
127
|
|
105
128
|
def determine_next_questionnaire(questionnaire_response, test_id)
|
129
|
+
if custom_questionnaires
|
130
|
+
FHIR.from_contents(next_custom_questionnaire.to_json)
|
106
131
|
# Retrieve the selected option from the response and determine the next set of questions
|
107
|
-
|
132
|
+
elsif questionnaire_dinner_order_selection_present?(questionnaire_response)
|
108
133
|
dinner_question_from_selection(questionnaire_response, test_id)
|
109
134
|
else
|
110
135
|
Fixtures.next_question_for_test(test_id)
|
111
136
|
end
|
112
137
|
end
|
113
138
|
|
114
|
-
def
|
139
|
+
def complete_questionnaire(questionnaire_response)
|
115
140
|
update_questionnaire_response(questionnaire_response)
|
116
141
|
questionnaire_response
|
117
142
|
end
|
@@ -13,8 +13,12 @@ module DaVinciDTRTestKit
|
|
13
13
|
session_id = result.test_session_id
|
14
14
|
session_data = Inferno::Repositories::SessionData.new
|
15
15
|
url_input = session_data.load(test_session_id: session_id, name: 'url')
|
16
|
-
credentials_input =
|
17
|
-
|
16
|
+
credentials_input =
|
17
|
+
session_data.load(
|
18
|
+
test_session_id: session_id,
|
19
|
+
name: 'smart_auth_info',
|
20
|
+
type: 'auth_info'
|
21
|
+
)
|
18
22
|
|
19
23
|
client = FHIR::Client.new(url_input)
|
20
24
|
client.default_json
|
@@ -14,8 +14,12 @@ module DaVinciDTRTestKit
|
|
14
14
|
session_data = Inferno::Repositories::SessionData.new
|
15
15
|
endpoint_input = session_data.load(test_session_id: session_id, name: 'custom_endpoint')
|
16
16
|
url_input = session_data.load(test_session_id: session_id, name: 'url')
|
17
|
-
credentials_input =
|
18
|
-
|
17
|
+
credentials_input =
|
18
|
+
session_data.load(
|
19
|
+
test_session_id: session_id,
|
20
|
+
name: 'smart_auth_info',
|
21
|
+
type: 'auth_info'
|
22
|
+
)
|
19
23
|
|
20
24
|
client = FHIR::Client.new(url_input)
|
21
25
|
client.default_json
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'udap_security_test_kit'
|
4
|
+
require 'smart_app_launch_test_kit'
|
5
|
+
require_relative '../../urls'
|
6
|
+
require_relative '../../tags'
|
7
|
+
|
8
|
+
module DaVinciDTRTestKit
|
9
|
+
module MockUdapSmartServer
|
10
|
+
class TokenEndpoint < Inferno::DSL::SuiteEndpoint
|
11
|
+
include SMARTAppLaunch::MockSMARTServer::SMARTTokenResponseCreation
|
12
|
+
include UDAPSecurityTestKit::MockUDAPServer::UDAPTokenResponseCreation
|
13
|
+
|
14
|
+
def test_run_identifier
|
15
|
+
UDAPSecurityTestKit::MockUDAPServer.client_id_from_client_assertion(request.params[:client_assertion])
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_response
|
19
|
+
if request.params[:udap].present?
|
20
|
+
make_udap_client_credential_token_response
|
21
|
+
else
|
22
|
+
make_smart_client_credential_token_response
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_result
|
27
|
+
nil # never update for now
|
28
|
+
end
|
29
|
+
|
30
|
+
def tags
|
31
|
+
type_tag = request.params[:udap].present? ? UDAPSecurityTestKit::UDAP_TAG : SMARTAppLaunch::SMART_TAG
|
32
|
+
[UDAPSecurityTestKit::TOKEN_TAG, UDAPSecurityTestKit::CLIENT_CREDENTIALS_TAG, type_tag]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/davinci_dtr_test_kit/requirements/davinci-dtr-test-kit_out_of_scope_requirements.csv
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
Req Set,ID,Reason,Details
|
2
2
|
hl7.fhir.us.davinci-dtr_2.0.1,10,Not Tested,"QuestionnaireResponse.source is not must support or required, so these systems are not required to support it."
|
3
3
|
hl7.fhir.us.davinci-dtr_2.0.1,129,Not Tested,Cdex workflows out of initial scope
|
4
|
-
hl7.fhir.us.davinci-dtr_2.0.1,231,Not Tested,
|
5
|
-
hl7.fhir.us.davinci-dtr_2.0.1,232,Not Tested,
|
6
|
-
hl7.fhir.us.davinci-dtr_2.0.1,233,Not Tested,
|
7
|
-
hl7.fhir.us.davinci-dtr_2.0.1,234,Not Tested,
|
8
|
-
hl7.fhir.us.davinci-dtr_2.0.1,
|
4
|
+
hl7.fhir.us.davinci-dtr_2.0.1,231,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
5
|
+
hl7.fhir.us.davinci-dtr_2.0.1,232,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
6
|
+
hl7.fhir.us.davinci-dtr_2.0.1,233,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
7
|
+
hl7.fhir.us.davinci-dtr_2.0.1,234,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
8
|
+
hl7.fhir.us.davinci-dtr_2.0.1,235,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
9
|
+
hl7.fhir.us.davinci-dtr_2.0.1,236,Not Tested,Not compatible with the PAS approach to prior authorization submission
|
9
10
|
hl7.fhir.us.davinci-dtr_2.0.1,237,Not Tested,"automatic or manual allowed, no clear impact on downstream functionality"
|
10
11
|
hl7.fhir.us.davinci-dtr_2.0.1,238,Not Tested,"automatic or manual allowed, no clear impact on downstream functionality"
|
11
12
|
hl7.fhir.us.davinci-dtr_2.0.1,328,Not Tested,metrics are optional at this time
|