davinci_dtr_test_kit 0.12.0 → 0.13.0
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/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_conformance_test.rb +15 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_correctness_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group.rb +15 -5
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +3 -7
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +9 -5
- data/lib/davinci_dtr_test_kit/cql_test.rb +182 -137
- data/lib/davinci_dtr_test_kit/docs/dtr_light_ehr_suite_description_v201.md +29 -0
- data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +38 -25
- data/lib/davinci_dtr_test_kit/dtr_options.rb +7 -0
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +118 -75
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +6 -3
- data/lib/davinci_dtr_test_kit/fixture_loader.rb +6 -84
- data/lib/davinci_dtr_test_kit/fixtures.rb +43 -48
- data/lib/davinci_dtr_test_kit/mock_auth_server.rb +101 -18
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +32 -24
- data/lib/davinci_dtr_test_kit/mock_payer.rb +41 -64
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +2 -2
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb +2 -1
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +6 -5
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_request_validation_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb +2 -1
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +6 -4
- data/lib/davinci_dtr_test_kit/tags.rb +1 -0
- data/lib/davinci_dtr_test_kit/urls.rb +13 -10
- data/lib/davinci_dtr_test_kit/validation_test.rb +2 -1
- data/lib/davinci_dtr_test_kit/version.rb +1 -1
- data/lib/davinci_dtr_test_kit.rb +1 -1
- metadata +24 -8
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_representation_attestation_test.rb +0 -33
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_full_ehr_questionnaire_workflow_group.rb +0 -19
- /data/lib/davinci_dtr_test_kit/fixtures/{pre_populated_questionnaire_response.json → respiratory_assist_device/pre_populated_questionnaire_response.json} +0 -0
- /data/lib/davinci_dtr_test_kit/fixtures/{questionnaire_package.json → respiratory_assist_device/questionnaire_package.json} +0 -0
@@ -1,16 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'urls'
|
2
|
-
require_relative 'fixtures'
|
3
4
|
|
4
5
|
module DaVinciDTRTestKit
|
5
6
|
module MockAuthServer
|
6
|
-
|
7
|
+
AUTHORIZED_PRACTITIONER_ID = 'pra1234' # Must exist on the FHIR_REFERENCE_SERVER (env var)
|
8
|
+
|
9
|
+
RSA_PRIVATE_KEY = OpenSSL::PKey::RSA.generate(2048)
|
10
|
+
RSA_PUBLIC_KEY = RSA_PRIVATE_KEY.public_key
|
11
|
+
SUPPORTED_SCOPES = ['launch', 'patient/*.rs', 'user/*.rs', 'offline_access', 'openid', 'fhirUser'].freeze
|
12
|
+
|
13
|
+
def requests_repo
|
14
|
+
@requests_repo ||= Inferno::Repositories::Requests.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def auth_server_jwks(_env)
|
18
|
+
response_body = {
|
19
|
+
keys: [
|
20
|
+
{
|
21
|
+
kty: 'RSA',
|
22
|
+
alg: 'RS256',
|
23
|
+
n: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.n.to_s(2), padding: false),
|
24
|
+
e: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.e.to_s(2), padding: false),
|
25
|
+
use: 'sig'
|
26
|
+
}
|
27
|
+
]
|
28
|
+
}.to_json
|
29
|
+
|
30
|
+
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
31
|
+
end
|
7
32
|
|
8
33
|
def ehr_smart_config(env)
|
9
|
-
|
10
|
-
host = env['HTTP_HOST']
|
11
|
-
path = env['REQUEST_PATH'] || env['PATH_INFO']
|
12
|
-
path.gsub!(%r{#{SMART_CONFIG_PATH}(/)?}, '')
|
13
|
-
base_url = "#{protocol}://#{host + path}"
|
34
|
+
base_url = env_base_url(env, SMART_CONFIG_PATH)
|
14
35
|
response_body =
|
15
36
|
{
|
16
37
|
authorization_endpoint: base_url + EHR_AUTHORIZE_PATH,
|
@@ -18,7 +39,7 @@ module DaVinciDTRTestKit
|
|
18
39
|
token_endpoint_auth_methods_supported: ['private_key_jwt'],
|
19
40
|
token_endpoint_auth_signing_alg_values_supported: ['RS256'],
|
20
41
|
grant_types_supported: ['authorization_code'],
|
21
|
-
scopes_supported:
|
42
|
+
scopes_supported: SUPPORTED_SCOPES,
|
22
43
|
response_types_supported: ['code'],
|
23
44
|
code_challenge_methods_supported: ['S256'],
|
24
45
|
capabilities: [
|
@@ -34,9 +55,23 @@ module DaVinciDTRTestKit
|
|
34
55
|
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
35
56
|
end
|
36
57
|
|
58
|
+
def ehr_openid_config(env)
|
59
|
+
base_url = env_base_url(env, OPENID_CONFIG_PATH)
|
60
|
+
response_body = {
|
61
|
+
issuer: base_url + FHIR_BASE_PATH,
|
62
|
+
authorization_endpoint: base_url + EHR_AUTHORIZE_PATH,
|
63
|
+
token_endpoint: base_url + EHR_TOKEN_PATH,
|
64
|
+
jwks_uri: base_url + JKWS_PATH,
|
65
|
+
response_types_supported: ['id_token'],
|
66
|
+
subject_types_supported: ['public'],
|
67
|
+
id_token_signing_alg_values_supported: ['RS256']
|
68
|
+
}.to_json
|
69
|
+
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
70
|
+
end
|
71
|
+
|
37
72
|
def ehr_authorize(request, _test = nil, _test_result = nil)
|
38
73
|
# Authorization requests can bet GET or POST
|
39
|
-
params =
|
74
|
+
params = params_hash(request)
|
40
75
|
if params['redirect_uri'].present?
|
41
76
|
redirect_uri = "#{params['redirect_uri']}?" \
|
42
77
|
"code=#{SecureRandom.hex}&" \
|
@@ -57,25 +92,34 @@ module DaVinciDTRTestKit
|
|
57
92
|
|
58
93
|
def ehr_token_response(request, _test = nil, test_result = nil)
|
59
94
|
client_id = extract_client_id_from_token_request(request)
|
60
|
-
|
61
|
-
|
62
|
-
test_input = JSON.parse(test_result.input_json)
|
95
|
+
access_token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
|
96
|
+
granted_scopes = SUPPORTED_SCOPES & requested_scopes(test_result.test_session_id)
|
63
97
|
|
64
|
-
|
65
|
-
|
98
|
+
response = { access_token:, scope: granted_scopes.join(' '), token_type: 'bearer', expires_in: 3600 }
|
99
|
+
|
100
|
+
if granted_scopes.include?('openid')
|
101
|
+
response.merge!(id_token: create_id_token(request, client_id, fhir_user: granted_scopes.include?('fhirUser')))
|
102
|
+
end
|
103
|
+
|
104
|
+
fhir_context_input = find_test_input(test_result, 'smart_fhir_context')
|
105
|
+
fhir_context_input_value = fhir_context_input['value'] if fhir_context_input
|
66
106
|
begin
|
67
107
|
fhir_context = JSON.parse(fhir_context_input_value)
|
68
108
|
rescue StandardError
|
69
109
|
fhir_context = nil
|
70
110
|
end
|
71
|
-
response.merge!(
|
111
|
+
response.merge!(fhirContext: fhir_context) if fhir_context
|
72
112
|
|
73
|
-
smart_patient_input =
|
113
|
+
smart_patient_input = find_test_input(test_result, 'smart_patient_id')
|
74
114
|
smart_patient_input_value = smart_patient_input['value'] if smart_patient_input.present?
|
75
|
-
response.merge!(
|
115
|
+
response.merge!(patient: smart_patient_input_value) if smart_patient_input_value
|
76
116
|
|
77
117
|
request.response_body = response.to_json
|
78
|
-
request.response_headers = {
|
118
|
+
request.response_headers = {
|
119
|
+
'Cache-Control' => 'no-store',
|
120
|
+
'Pragma' => 'no-cache',
|
121
|
+
'Access-Control-Allow-Origin' => '*'
|
122
|
+
}
|
79
123
|
request.status = 200
|
80
124
|
end
|
81
125
|
|
@@ -141,5 +185,44 @@ module DaVinciDTRTestKit
|
|
141
185
|
def extract_token_from_query_params(request)
|
142
186
|
request.query_parameters['token']
|
143
187
|
end
|
188
|
+
|
189
|
+
def create_id_token(request, client_id, fhir_user: false)
|
190
|
+
# No point in mocking an identity provider, just always use known Practitioner as the authorized user
|
191
|
+
suite_base_url = request.url.split(EHR_TOKEN_PATH).first
|
192
|
+
id_token_hash = {
|
193
|
+
iss: suite_base_url + FHIR_BASE_PATH,
|
194
|
+
sub: AUTHORIZED_PRACTITIONER_ID,
|
195
|
+
aud: client_id,
|
196
|
+
exp: Time.now.to_i + (24 * 60 * 60), # 24 hrs
|
197
|
+
iat: Time.now.to_i
|
198
|
+
}
|
199
|
+
id_token_hash.merge!(fhirUser: "#{suite_base_url}/fhir/Practitioner/#{AUTHORIZED_PRACTITIONER_ID}") if fhir_user
|
200
|
+
|
201
|
+
JWT.encode(id_token_hash, RSA_PRIVATE_KEY, 'RS256')
|
202
|
+
end
|
203
|
+
|
204
|
+
def requested_scopes(test_session_id)
|
205
|
+
auth_request = requests_repo.tagged_requests(test_session_id, [EHR_AUTHORIZE_TAG]).last
|
206
|
+
return [] unless auth_request
|
207
|
+
|
208
|
+
scope_str = params_hash(auth_request)&.dig('scope')
|
209
|
+
scope_str ? URI.decode_www_form_component(scope_str).split : []
|
210
|
+
end
|
211
|
+
|
212
|
+
def find_test_input(test_result, input_name)
|
213
|
+
JSON.parse(test_result.input_json)&.find { |input| input['name'] == input_name }
|
214
|
+
end
|
215
|
+
|
216
|
+
def params_hash(request)
|
217
|
+
request.verb == 'get' ? request.query_parameters : URI.decode_www_form(request.request_body)&.to_h
|
218
|
+
end
|
219
|
+
|
220
|
+
def env_base_url(env, endpoint_path)
|
221
|
+
protocol = env['rack.url_scheme']
|
222
|
+
host = env['HTTP_HOST']
|
223
|
+
path = env['REQUEST_PATH'] || env['PATH_INFO']
|
224
|
+
path.gsub!(%r{#{endpoint_path}(/)?}, '')
|
225
|
+
"#{protocol}://#{host + path}"
|
226
|
+
end
|
144
227
|
end
|
145
228
|
end
|
@@ -27,16 +27,10 @@ module DaVinciDTRTestKit
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def get_fhir_resource(request, _test = nil, test_result = nil)
|
30
|
-
|
30
|
+
fhir_class, id = fhir_class_and_id_from_url(request.url)
|
31
31
|
request.response_headers = RESPONSE_HEADERS
|
32
32
|
|
33
|
-
|
34
|
-
fhir_class = FHIR.const_get(resource_type)
|
35
|
-
rescue NameError
|
36
|
-
resource_type = nil
|
37
|
-
end
|
38
|
-
|
39
|
-
if resource_type.blank?
|
33
|
+
if fhir_class.nil?
|
40
34
|
request.status = 400
|
41
35
|
request.response_headers = { 'Content-Type': 'application/json' }
|
42
36
|
request.response_body = FHIR::OperationOutcome.new(
|
@@ -49,18 +43,9 @@ module DaVinciDTRTestKit
|
|
49
43
|
end
|
50
44
|
|
51
45
|
# Respond with user-inputted resource if there is one that matches the request
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
ehr_bundle = FHIR.from_contents(ehr_bundle_input_value) if ehr_bundle_input_value.present?
|
56
|
-
rescue StandardError
|
57
|
-
ehr_bundle = nil
|
58
|
-
end
|
59
|
-
|
60
|
-
if id.present? && ehr_bundle.present? && ehr_bundle.is_a?(FHIR::Bundle)
|
61
|
-
matching_resource = ehr_bundle.entry&.find do |entry|
|
62
|
-
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
|
63
|
-
end&.resource
|
46
|
+
ehr_bundle = ehr_input_bundle(test_result)
|
47
|
+
if id.present? && ehr_bundle.present?
|
48
|
+
matching_resource = find_resource_in_bundle(ehr_bundle, fhir_class, id)
|
64
49
|
if matching_resource.present?
|
65
50
|
request.status = 200
|
66
51
|
request.response_headers = { 'Content-Type': 'application/json' }
|
@@ -85,13 +70,36 @@ module DaVinciDTRTestKit
|
|
85
70
|
request.response_body = request.request_body
|
86
71
|
end
|
87
72
|
|
88
|
-
|
89
|
-
|
73
|
+
def ehr_input_bundle(test_result)
|
74
|
+
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'ehr_bundle' }
|
75
|
+
ehr_bundle_input_value = ehr_bundle_input_value = ehr_bundle_input['value'] if ehr_bundle_input.present?
|
76
|
+
ehr_bundle = FHIR.from_contents(ehr_bundle_input_value) if ehr_bundle_input_value.present?
|
77
|
+
ehr_bundle if ehr_bundle.is_a?(FHIR::Bundle)
|
78
|
+
rescue StandardError
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_resource_in_bundle(bundle, fhir_class, id)
|
83
|
+
bundle.entry&.find do |entry|
|
84
|
+
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
|
85
|
+
end&.resource
|
86
|
+
end
|
87
|
+
|
88
|
+
# Pull resource type class and ID from url
|
89
|
+
# e.g. http://example.org/fhir/Patient/123 -> [FHIR::Patient, '123']
|
90
90
|
# @private
|
91
|
-
def
|
91
|
+
def fhir_class_and_id_from_url(url)
|
92
92
|
path = url.split('?').first.split('/fhir/').second
|
93
93
|
path.sub!(%r{/$}, '')
|
94
|
-
path.split('/')
|
94
|
+
resource_type, id = path.split('/')
|
95
|
+
|
96
|
+
begin
|
97
|
+
fhir_class = FHIR.const_get(resource_type)
|
98
|
+
rescue NameError
|
99
|
+
fhir_class = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
[fhir_class, id]
|
95
103
|
end
|
96
104
|
end
|
97
105
|
end
|
@@ -4,14 +4,12 @@ require_relative 'fixtures'
|
|
4
4
|
|
5
5
|
module DaVinciDTRTestKit
|
6
6
|
module MockPayer
|
7
|
-
include Fixtures
|
8
|
-
|
9
7
|
RESPONSE_HEADERS = { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }.freeze
|
10
8
|
|
11
9
|
def questionnaire_package_response(request, _test = nil, test_result = nil)
|
12
10
|
request.status = 200
|
13
11
|
request.response_headers = RESPONSE_HEADERS
|
14
|
-
request.response_body =
|
12
|
+
request.response_body = build_questionnaire_package_response(request, test_result.test_id).to_json
|
15
13
|
end
|
16
14
|
|
17
15
|
def payer_questionnaire_response(request, _test = nil, test_result = nil)
|
@@ -45,79 +43,58 @@ module DaVinciDTRTestKit
|
|
45
43
|
!test.config.options[:accepts_multiple_requests]
|
46
44
|
end
|
47
45
|
|
48
|
-
|
49
|
-
test_questionnaire_canonical = find_questionnaire_canonical_for_test_id(test_id)
|
50
|
-
test_questionnaire_loaded = false
|
51
|
-
|
52
|
-
bundles = []
|
53
|
-
issues = []
|
54
|
-
|
55
|
-
# first try the parameters - load the questionnaire specified by the questionnaire parameter
|
56
|
-
input_parameters = FHIR.from_contents(request.request_body)
|
57
|
-
input_parameters.parameter.each do |one_parameter|
|
58
|
-
next unless one_parameter.name == 'questionnaire'
|
59
|
-
next unless one_parameter.valueCanonical
|
46
|
+
private
|
60
47
|
|
61
|
-
|
62
|
-
|
48
|
+
def build_questionnaire_package_response(request, test_id)
|
49
|
+
begin
|
50
|
+
input_parameters = FHIR.from_contents(request.request_body)
|
51
|
+
rescue StandardError
|
52
|
+
return operation_outcome('error', 'invalid', 'No valid input parameters')
|
53
|
+
end
|
63
54
|
|
64
|
-
|
55
|
+
questionnaire_package = Fixtures.questionnaire_package_for_test(test_id)
|
56
|
+
unless questionnaire_package
|
57
|
+
return operation_outcome('error', 'business-rule', "No Questionnaire found for Inferno test #{test_id}")
|
65
58
|
end
|
66
59
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
elsif bundles.empty?
|
72
|
-
# no questionnaire for this test ...
|
73
|
-
operation_outcome_issue = FHIR::OperationOutcome::Issue.new
|
74
|
-
operation_outcome_issue.severity = 'error'
|
75
|
-
operation_outcome_issue.code = 'business-rule'
|
76
|
-
details = FHIR::CodeableConcept.new
|
77
|
-
details.text = "no questionnaire found for test #{test_id}"
|
78
|
-
operation_outcome_issue.details = details
|
79
|
-
issues << operation_outcome_issue
|
80
|
-
end
|
60
|
+
questionnaire_canonical = find_questionnaire_canonical(questionnaire_package)
|
61
|
+
|
62
|
+
other_questionnaire_params = input_parameters.parameter.filter do |param|
|
63
|
+
param.name == 'questionnaire' && param.valueCanonical != questionnaire_canonical
|
81
64
|
end
|
82
65
|
|
83
|
-
|
66
|
+
return questionnaire_package unless other_questionnaire_params.any?
|
67
|
+
|
68
|
+
FHIR::Parameters.new(
|
69
|
+
parameter: [
|
70
|
+
FHIR::Parameters::Parameter.new(
|
71
|
+
name: 'PackageBundle',
|
72
|
+
resource: questionnaire_package
|
73
|
+
),
|
74
|
+
FHIR::Parameters::Parameter.new(
|
75
|
+
name: 'Outcome',
|
76
|
+
resource: FHIR::OperationOutcome.new(
|
77
|
+
issue: other_questionnaire_params.map do |param|
|
78
|
+
outcome_issue('warning', 'not-found', "Questionnaire #{param.valueCanonical} does not exist")
|
79
|
+
end
|
80
|
+
)
|
81
|
+
)
|
82
|
+
]
|
83
|
+
)
|
84
84
|
end
|
85
85
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
if questionnaire_bundle
|
90
|
-
bundles << questionnaire_bundle
|
91
|
-
else
|
92
|
-
operation_outcome_issue = FHIR::OperationOutcome::Issue.new
|
93
|
-
operation_outcome_issue.severity = 'warning'
|
94
|
-
operation_outcome_issue.code = 'value'
|
95
|
-
details = FHIR::CodeableConcept.new
|
96
|
-
details.text = "Questionnaire Canonical #{questionnaire_canonical} does not exist"
|
97
|
-
operation_outcome_issue.details = details
|
98
|
-
issues << operation_outcome_issue
|
99
|
-
end
|
86
|
+
def find_questionnaire_canonical(questionnaire_package)
|
87
|
+
questionnaire_package&.entry&.find { |e| e.resource.is_a?(FHIR::Questionnaire) }&.resource&.url
|
100
88
|
end
|
101
89
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
return_param = FHIR::Parameters::Parameter.new
|
106
|
-
return_param.name = 'return'
|
107
|
-
return_param.resource = one_bundle
|
108
|
-
response.parameter << return_param
|
109
|
-
end
|
90
|
+
def operation_outcome(severity, code, text = nil)
|
91
|
+
FHIR::OperationOutcome.new(issue: outcome_issue(severity, code, text))
|
92
|
+
end
|
110
93
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
outcome_param = FHIR::Parameters::Parameter.new
|
115
|
-
outcome_param.name = 'outcome'
|
116
|
-
outcome_param.resource = outcome
|
117
|
-
response.parameter << outcome_param
|
94
|
+
def outcome_issue(severity, code, text = nil)
|
95
|
+
FHIR::OperationOutcome::Issue.new(severity:, code:).tap do |issue|
|
96
|
+
issue.details = FHIR::CodeableConcept.new(text:) if text.present?
|
118
97
|
end
|
119
|
-
|
120
|
-
response
|
121
98
|
end
|
122
99
|
end
|
123
100
|
end
|
data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb
CHANGED
@@ -6,8 +6,8 @@ module DaVinciDTRTestKit
|
|
6
6
|
id :dtr_v201_payer_adaptive_next_form_expressions_test
|
7
7
|
title 'Questionnaire(s) contains items with expressions necessary for pre-population'
|
8
8
|
description %(
|
9
|
-
Inferno checks that the payer server response to $next-question operation has appropriate expressions and that
|
10
|
-
|
9
|
+
Inferno checks that the payer server response to $next-question operation has appropriate expressions and that
|
10
|
+
expressions are written in cql.
|
11
11
|
)
|
12
12
|
|
13
13
|
run do
|
data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb
CHANGED
@@ -22,7 +22,8 @@ module DaVinciDTRTestKit
|
|
22
22
|
if initial_adaptive_questionnaire_request.nil?
|
23
23
|
requests = load_tagged_requests(QUESTIONNAIRE_TAG)
|
24
24
|
skip_if requests.blank?, 'No request resource received from the client.'
|
25
|
-
# making the assumption that only one request was made here - if there were multiple, we are only validating the
|
25
|
+
# making the assumption that only one request was made here - if there were multiple, we are only validating the
|
26
|
+
# first
|
26
27
|
resource_is_valid?(resource: FHIR.from_contents(requests[0].request[:body]), profile_url: profile_with_version)
|
27
28
|
else
|
28
29
|
request = FHIR.from_contents(initial_adaptive_questionnaire_request)
|
data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb
CHANGED
@@ -24,21 +24,22 @@ module DaVinciDTRTestKit
|
|
24
24
|
profile_with_version = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-output-parameters|2.0.1'
|
25
25
|
endpoint = custom_endpoint.blank? ? '/Questionnaire/$questionnaire-package' : custom_endpoint
|
26
26
|
if initial_adaptive_questionnaire_request.nil?
|
27
|
-
# making the assumption that only one response was received - if there were multiple, we are only validating the
|
27
|
+
# making the assumption that only one response was received - if there were multiple, we are only validating the
|
28
|
+
# first
|
28
29
|
response = load_tagged_requests(QUESTIONNAIRE_TAG)[0]
|
29
30
|
scratch[:adaptive_responses] = [response]
|
30
31
|
resource = FHIR.from_contents(response.response[:body])
|
31
32
|
else
|
32
33
|
response = fhir_operation("#{url}#{endpoint}", body: JSON.parse(initial_adaptive_questionnaire_request),
|
33
|
-
|
34
|
+
headers: { 'Content-Type': 'application/json' })
|
34
35
|
resource = FHIR.from_contents(response.response[:body])
|
35
36
|
scratch[:adaptive_responses] = [response]
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
assert !scratch[:adaptive_responses].nil?, 'No resources to validate.'
|
39
40
|
assert_response_status([200, 201], response: response.response)
|
40
|
-
assert_resource_type(:parameters, resource:
|
41
|
-
assert_valid_resource(resource
|
41
|
+
assert_resource_type(:parameters, resource:)
|
42
|
+
assert_valid_resource(resource:, profile_url: profile_with_version)
|
42
43
|
questionnaire_bundle = resource.parameter.find { |param| param.resource.resourceType == 'Bundle' }&.resource
|
43
44
|
assert questionnaire_bundle, 'No questionnaire bundle found in the response'
|
44
45
|
assert_valid_resource(resource: questionnaire_bundle, profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle|2.0.1')
|
data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_request_validation_test.rb
CHANGED
@@ -50,7 +50,7 @@ module DaVinciDTRTestKit
|
|
50
50
|
)
|
51
51
|
else
|
52
52
|
messages << { type: 'error',
|
53
|
-
|
53
|
+
message: format_markdown("No resources were of type 'Parameters' or 'QuestionnaireResponse'") }
|
54
54
|
end
|
55
55
|
errors_found = messages.any? { |message| message[:type] == 'error' }
|
56
56
|
skip_if errors_found, "No resources conform to the profiles http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse-adapt
|
@@ -24,7 +24,8 @@ module DaVinciDTRTestKit
|
|
24
24
|
skip_if access_token.nil?, 'No access token provided - required for client flow.'
|
25
25
|
requests = load_tagged_requests(QUESTIONNAIRE_TAG)
|
26
26
|
skip_if requests.blank?, 'No request resource received from the client.'
|
27
|
-
# making the assumption that only one request was made here - if there were multiple, we are only validating the
|
27
|
+
# making the assumption that only one request was made here - if there were multiple, we are only validating the
|
28
|
+
# first
|
28
29
|
resource_is_valid?(resource: FHIR.from_contents(requests[0].request[:body]), profile_url: profile_with_version)
|
29
30
|
else
|
30
31
|
request = FHIR.from_contents(initial_static_questionnaire_request)
|
@@ -26,8 +26,10 @@ module DaVinciDTRTestKit
|
|
26
26
|
resources = load_tagged_requests(QUESTIONNAIRE_TAG)
|
27
27
|
skip_if resources.nil?, 'No request resource received from the client.'
|
28
28
|
scratch[:output_parameters] = resources
|
29
|
-
# making the assumption that only one response was received- if there were multiple, we are only validating the
|
30
|
-
|
29
|
+
# making the assumption that only one response was received- if there were multiple, we are only validating the
|
30
|
+
# first
|
31
|
+
assert_valid_resource(resource: FHIR.from_contents(resources[0].request[:body]),
|
32
|
+
profile_url: profile_with_version)
|
31
33
|
else
|
32
34
|
request = fhir_operation("#{url}/Questionnaire/$questionnaire-package",
|
33
35
|
body: JSON.parse(initial_static_questionnaire_request),
|
@@ -36,8 +38,8 @@ module DaVinciDTRTestKit
|
|
36
38
|
resource = FHIR.from_contents(request.response[:body])
|
37
39
|
scratch[:output_parameters] = resource
|
38
40
|
assert_response_status([200, 201], response: request.response)
|
39
|
-
assert_resource_type(:parameters, resource:
|
40
|
-
assert_valid_resource(resource
|
41
|
+
assert_resource_type(:parameters, resource:)
|
42
|
+
assert_valid_resource(resource:, profile_url: profile_with_version)
|
41
43
|
questionnaire_bundle = resource.parameter.find { |param| param.resource.resourceType == 'Bundle' }&.resource
|
42
44
|
assert questionnaire_bundle, 'No questionnaire bundle found in the response'
|
43
45
|
assert_valid_resource(resource: questionnaire_bundle, profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle|2.0.1')
|
@@ -1,17 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DaVinciDTRTestKit
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
FHIR_BASE_PATH = '/fhir'
|
5
|
+
SMART_CONFIG_PATH = "#{FHIR_BASE_PATH}/.well-known/smart-configuration".freeze
|
6
|
+
OPENID_CONFIG_PATH = "#{FHIR_BASE_PATH}/.well-known/openid-configuration".freeze
|
7
|
+
JKWS_PATH = "#{FHIR_BASE_PATH}/.well-known/jwks.json".freeze
|
8
|
+
EHR_AUTHORIZE_PATH = "#{FHIR_BASE_PATH}/mock_ehr_auth/authorize".freeze
|
9
|
+
EHR_TOKEN_PATH = "#{FHIR_BASE_PATH}/mock_ehr_auth/token".freeze
|
10
|
+
PAYER_TOKEN_PATH = "#{FHIR_BASE_PATH}/mock_payer_auth/token".freeze
|
11
|
+
QUESTIONNAIRE_PACKAGE_PATH = "#{FHIR_BASE_PATH}/Questionnaire/$questionnaire-package".freeze
|
12
|
+
NEXT_PATH = "#{FHIR_BASE_PATH}/Questionnaire/$next-question".freeze
|
13
|
+
QUESTIONNAIRE_RESPONSE_PATH = "#{FHIR_BASE_PATH}/QuestionnaireResponse".freeze
|
14
|
+
FHIR_RESOURCE_PATH = "#{FHIR_BASE_PATH}/:resource/:id".freeze
|
15
|
+
FHIR_SEARCH_PATH = "#{FHIR_BASE_PATH}/:resource".freeze
|
11
16
|
RESUME_PASS_PATH = '/resume_pass'
|
12
17
|
RESUME_FAIL_PATH = '/resume_fail'
|
13
|
-
FHIR_RESOURCE_PATH = '/fhir/:resource/:id'
|
14
|
-
FHIR_SEARCH_PATH = '/fhir/:resource'
|
15
18
|
|
16
19
|
module URLs
|
17
20
|
def base_url
|
@@ -43,7 +46,7 @@ module DaVinciDTRTestKit
|
|
43
46
|
end
|
44
47
|
|
45
48
|
def fhir_base_url
|
46
|
-
@fhir_base_url ||=
|
49
|
+
@fhir_base_url ||= base_url + FHIR_BASE_PATH
|
47
50
|
end
|
48
51
|
|
49
52
|
def resume_pass_url
|
@@ -42,7 +42,8 @@ module DaVinciDTRTestKit
|
|
42
42
|
else
|
43
43
|
if resource.url != resource_url
|
44
44
|
messages << { type: 'warning',
|
45
|
-
message: format_markdown(
|
45
|
+
message: format_markdown(%(Request made to wrong URL: #{resource.request[:url]}.
|
46
|
+
Should instead be to #{resource_url})) }
|
46
47
|
end
|
47
48
|
fhir_resource = FHIR.from_contents(resource.request[:body])
|
48
49
|
end
|
data/lib/davinci_dtr_test_kit.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
require_relative 'davinci_dtr_test_kit/dtr_payer_server_suite'
|
2
2
|
require_relative 'davinci_dtr_test_kit/dtr_smart_app_suite'
|
3
3
|
require_relative 'davinci_dtr_test_kit/dtr_full_ehr_suite'
|
4
|
-
|
4
|
+
require_relative 'davinci_dtr_test_kit/dtr_light_ehr_suite'
|