davinci_dtr_test_kit 0.11.0 → 0.11.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/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_dinner_questionnaire_package_request_test.rb +64 -27
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_resp_questionnaire_package_request_test.rb +64 -27
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +1 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +2 -2
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +1 -1
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +1 -1
- data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_dinner_order_static.json +1 -1
- data/lib/davinci_dtr_test_kit/mock_auth_server.rb +25 -15
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +8 -3
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb +1 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +1 -0
- data/lib/davinci_dtr_test_kit/validation_test.rb +1 -0
- data/lib/davinci_dtr_test_kit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3449c737f53b2443bc81890e9788ff4aad6837c70865512e58b5a5d3809ad96e
|
4
|
+
data.tar.gz: 4b2775168992e4887e5e330178138bd918a225bf9d57f2b7425a021acc7ee7c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6107a0cf03478d3bdc9c9b155af0664b8d39b9a3819e563c3dcf45bc69b34d80a83b0be270022be6d75aeb95a6b2b9b85d486c00693a9ad3e4f0605e2d504ee
|
7
|
+
data.tar.gz: 69701c0a2b4a2a69ae16d5e8dd1b79fd9d27fddf0230d02dc6793be32752d965f01688d3661df72cfdddc9a208b252fda1303f516b5aa6458d33631383fc17f2
|
@@ -11,39 +11,76 @@ module DaVinciDTRTestKit
|
|
11
11
|
Inferno will wait for a DTR questionnaire package request from the client. Upon receipt, Inferno will generate and
|
12
12
|
send a response.
|
13
13
|
)
|
14
|
-
input :smart_app_launch,
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
input :smart_app_launch,
|
15
|
+
type: 'radio',
|
16
|
+
title: 'SMART App Launch',
|
17
|
+
description: 'How will the DTR SMART App launch?',
|
18
|
+
options: { list_options: [{ label: 'EHR Launch from Inferno', value: 'ehr' },
|
19
|
+
{ label: 'Standalone Launch', value: 'standalone' }] }
|
18
20
|
input :client_id
|
19
|
-
input :launch_uri,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
input :launch_uri,
|
22
|
+
optional: true,
|
23
|
+
description: 'Required if "Launch from Inferno" is selected'
|
24
|
+
input :smart_patient_id,
|
25
|
+
optional: true,
|
26
|
+
title: 'SMART App Launch Patient ID (Dinner Static)',
|
27
|
+
type: 'text',
|
28
|
+
description: %(
|
29
|
+
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
|
30
|
+
Launch.
|
31
|
+
),
|
32
|
+
default: 'pat015'
|
33
|
+
input :smart_fhir_context,
|
34
|
+
optional: true,
|
35
|
+
title: 'SMART App Launch fhirContext (Dinner Static)',
|
36
|
+
type: 'textarea',
|
37
|
+
description: %(
|
38
|
+
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
|
39
|
+
Launch. These references help determine the behavior of the app. Referenced instances
|
40
|
+
may be provided in the "EHR-available resources" input.
|
41
|
+
),
|
42
|
+
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
|
43
|
+
{ reference: 'DeviceRequest/devreqe0470' }])
|
44
|
+
input :ehr_bundle,
|
45
|
+
optional: true,
|
46
|
+
title: 'EHR-available resources (Dinner Static)',
|
47
|
+
type: 'textarea',
|
48
|
+
description: %(
|
49
|
+
Resources available from the EHR needed to drive the dinner static workflow.
|
50
|
+
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
|
51
|
+
instance present will be available for retrieval from Inferno at the endpoint:
|
52
|
+
|
53
|
+
```
|
54
|
+
[fhir-base]/[resource type]/[instance id]
|
55
|
+
```
|
56
|
+
)
|
40
57
|
|
41
58
|
def example_client_jwt_payload_part
|
42
59
|
Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
|
43
60
|
end
|
44
61
|
|
45
62
|
run do
|
46
|
-
|
63
|
+
# validate relevant inputs and provide warnings if they are bad
|
64
|
+
warning do
|
65
|
+
if smart_fhir_context
|
66
|
+
assert_valid_json(smart_fhir_context,
|
67
|
+
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
|
68
|
+
the access token response.')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
warning do
|
73
|
+
if ehr_bundle
|
74
|
+
assert_valid_json(ehr_bundle,
|
75
|
+
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
|
76
|
+
will be available to access from Inferno.')
|
77
|
+
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
|
78
|
+
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
|
79
|
+
will be available to access from Inferno.')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
launch_prompt = if smart_app_launch == 'ehr'
|
47
84
|
%(Launch the DTR SMART App from Inferno by right clicking
|
48
85
|
[this link](#{launch_uri}?iss=#{fhir_base_url}&launch=#{launch_uri})
|
49
86
|
and selecting or "Open in new window" or "Open in new tab".)
|
@@ -60,7 +97,7 @@ module DaVinciDTRTestKit
|
|
60
97
|
|
61
98
|
#{launch_prompt}
|
62
99
|
|
63
|
-
#{inferno_prompt_cont if smart_app_launch == '
|
100
|
+
#{inferno_prompt_cont if smart_app_launch == 'ehr'}
|
64
101
|
|
65
102
|
Then, Inferno will expect the SMART App to invoke the DTR Questionnaire Package operation by sending a POST
|
66
103
|
request to
|
@@ -10,39 +10,76 @@ module DaVinciDTRTestKit
|
|
10
10
|
Inferno will wait for a DTR questionnaire package request from the client. Upon receipt, Inferno will generate and
|
11
11
|
send a response.
|
12
12
|
)
|
13
|
-
input :smart_app_launch,
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
input :smart_app_launch,
|
14
|
+
type: 'radio',
|
15
|
+
title: 'SMART App Launch',
|
16
|
+
description: 'How will the DTR SMART App launch?',
|
17
|
+
options: { list_options: [{ label: 'EHR Launch from Inferno', value: 'ehr' },
|
18
|
+
{ label: 'Standalone Launch', value: 'standalone' }] }
|
17
19
|
input :client_id
|
18
|
-
input :launch_uri,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
20
|
+
input :launch_uri,
|
21
|
+
optional: true,
|
22
|
+
description: 'Required if "Launch from Inferno" is selected'
|
23
|
+
input :smart_patient_id,
|
24
|
+
optional: true,
|
25
|
+
title: 'SMART App Launch Patient ID (Respiratory Assist Device)',
|
26
|
+
type: 'text',
|
27
|
+
description: %(
|
28
|
+
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
|
29
|
+
Launch.
|
30
|
+
),
|
31
|
+
default: 'pat015'
|
32
|
+
input :smart_fhir_context,
|
33
|
+
optional: true,
|
34
|
+
title: 'SMART App Launch fhirContext (Respiratory Assist Device)',
|
35
|
+
type: 'textarea',
|
36
|
+
description: %(
|
37
|
+
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
|
38
|
+
Launch. These references help determine the behavior of the app. Referenced instances
|
39
|
+
may be provided in the "EHR-available resources" input.
|
40
|
+
),
|
41
|
+
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
|
42
|
+
{ reference: 'DeviceRequest/devreqe0470' }])
|
43
|
+
input :ehr_bundle,
|
44
|
+
optional: true,
|
45
|
+
title: 'EHR-available resources (Respiratory Assist Device)',
|
46
|
+
type: 'textarea',
|
47
|
+
description: %(
|
48
|
+
Resources available from the EHR needed to drive the respiratory assist device workflow.
|
49
|
+
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
|
50
|
+
instance present will be available for retrieval from Inferno at the endpoint
|
51
|
+
|
52
|
+
```
|
53
|
+
[fhir-base]/[resource type]/[instance id]
|
54
|
+
```
|
55
|
+
)
|
39
56
|
|
40
57
|
def example_client_jwt_payload_part
|
41
58
|
Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
|
42
59
|
end
|
43
60
|
|
44
61
|
run do
|
45
|
-
|
62
|
+
# validate relevant inputs and provide warnings if they are bad
|
63
|
+
warning do
|
64
|
+
if smart_fhir_context
|
65
|
+
assert_valid_json(smart_fhir_context,
|
66
|
+
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
|
67
|
+
the access token response.')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
warning do
|
72
|
+
if ehr_bundle
|
73
|
+
assert_valid_json(ehr_bundle,
|
74
|
+
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
|
75
|
+
will be available to access from Inferno.')
|
76
|
+
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
|
77
|
+
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
|
78
|
+
will be available to access from Inferno.')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
launch_prompt = if smart_app_launch == 'ehr'
|
46
83
|
%(Launch the DTR SMART App from Inferno by right clicking
|
47
84
|
[this link](#{launch_uri}?iss=#{fhir_base_url}&launch=#{launch_uri})
|
48
85
|
and selecting or "Open in new window" or "Open in new tab".)
|
@@ -58,7 +95,7 @@ module DaVinciDTRTestKit
|
|
58
95
|
|
59
96
|
#{launch_prompt}
|
60
97
|
|
61
|
-
#{inferno_prompt_cont if smart_app_launch == '
|
98
|
+
#{inferno_prompt_cont if smart_app_launch == 'ehr'}
|
62
99
|
|
63
100
|
Then, Inferno will expect the SMART App to invoke the DTR Questionnaire Package operation by sending a POST
|
64
101
|
request to
|
@@ -81,9 +81,9 @@ If you would like to try out the tests but don't have a DTR payer server impleme
|
|
81
81
|
you can run these tests against the DTR SMART Client test suite included in this test kit
|
82
82
|
using the following steps:
|
83
83
|
1. Start an Inferno session of the Da Vinci DTR SMART App Test Suite.
|
84
|
-
1. Select test
|
84
|
+
1. Select test 1.1.1 *Retrieving the Static Questionnaire* from the menu on the left.
|
85
85
|
1. Click the "Run All Tests" button in the upper right.
|
86
|
-
1. In the "
|
86
|
+
1. In the "SMART App Launch" select `Standalone Launch` and in the "client_id" input, put `sample`.
|
87
87
|
1. Click the "submit" button in the dialog that appears. The client tests will now be waiting for requests.
|
88
88
|
1. Start an Inferno session of the DTR Payer Server test suite.
|
89
89
|
1. Select test 1 *Static Questionnaire Package Retrieval* from the menu on the left.
|
@@ -61,7 +61,7 @@ module DaVinciDTRTestKit
|
|
61
61
|
DTRSmartAppSuite.extract_client_id_from_query_params(request)
|
62
62
|
end
|
63
63
|
|
64
|
-
record_response_route :post, EHR_AUTHORIZE_PATH, '
|
64
|
+
record_response_route :post, EHR_AUTHORIZE_PATH, 'dtr_smart_app_ehr_authorize', method(:ehr_authorize),
|
65
65
|
resumes: ->(_) { false } do |request|
|
66
66
|
DTRSmartAppSuite.extract_client_id_from_form_params(request)
|
67
67
|
end
|
@@ -60,22 +60,20 @@ module DaVinciDTRTestKit
|
|
60
60
|
token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
|
61
61
|
response = { access_token: token, token_type: 'bearer', expires_in: 3600 }
|
62
62
|
test_input = JSON.parse(test_result.input_json)
|
63
|
-
smart_app_launch_input = test_input.find { |input| input['name'] == 'smart_app_launch' }
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
fhir_context = fhir_context_input_value
|
69
|
-
|
70
|
-
|
71
|
-
|
64
|
+
fhir_context_input = test_input.find { |input| input['name'] == 'smart_fhir_context' }
|
65
|
+
fhir_context_input_value = fhir_context_input['value'] if fhir_context_input.present?
|
66
|
+
begin
|
67
|
+
fhir_context = JSON.parse(fhir_context_input_value)
|
68
|
+
rescue StandardError
|
69
|
+
fhir_context = nil
|
70
|
+
end
|
71
|
+
response.merge!({ fhirContext: fhir_context }) if fhir_context
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
smart_patient_input = test_input.find { |input| input['name'] == 'smart_patient_id' }
|
74
|
+
smart_patient_input_value = smart_patient_input['value'] if smart_patient_input.present?
|
75
|
+
response.merge!({ patient: smart_patient_input_value }) if smart_patient_input_value
|
76
76
|
|
77
|
-
response.merge!({ patient: smart_patient, fhirContext: fhir_context })
|
78
|
-
end
|
79
77
|
request.response_body = response.to_json
|
80
78
|
request.response_headers = { 'Access-Control-Allow-Origin' => '*' }
|
81
79
|
request.status = 200
|
@@ -102,7 +100,13 @@ module DaVinciDTRTestKit
|
|
102
100
|
encoded_jwt = URI.decode_www_form(request.request_body).to_h['client_assertion']
|
103
101
|
return unless encoded_jwt.present?
|
104
102
|
|
105
|
-
jwt_payload =
|
103
|
+
jwt_payload =
|
104
|
+
begin
|
105
|
+
JWT.decode(encoded_jwt, nil, false)&.first # skip signature verification
|
106
|
+
rescue StandardError
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
106
110
|
jwt_payload['iss'] || jwt_payload['sub'] if jwt_payload.present?
|
107
111
|
end
|
108
112
|
|
@@ -120,7 +124,13 @@ module DaVinciDTRTestKit
|
|
120
124
|
|
121
125
|
def extract_client_id_from_bearer_token(request)
|
122
126
|
token = extract_bearer_token(request)
|
123
|
-
|
127
|
+
jwt =
|
128
|
+
begin
|
129
|
+
JWT.decode(token, nil, false)
|
130
|
+
rescue StandardError
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
jwt&.first&.dig('inferno_client_id')
|
124
134
|
end
|
125
135
|
|
126
136
|
# Header expected to be a bearer token of the form "Bearer: <token>"
|
@@ -49,9 +49,14 @@ module DaVinciDTRTestKit
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# Respond with user-inputted resource if there is one that matches the request
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
begin
|
53
|
+
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'ehr_bundle' }
|
54
|
+
ehr_bundle_input_value = ehr_bundle_input_value = ehr_bundle_input['value'] if ehr_bundle_input.present?
|
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
|
+
|
55
60
|
if id.present? && ehr_bundle.present? && ehr_bundle.is_a?(FHIR::Bundle)
|
56
61
|
matching_resource = ehr_bundle.entry&.find do |entry|
|
57
62
|
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
|
@@ -37,6 +37,7 @@ module DaVinciDTRTestKit
|
|
37
37
|
else
|
38
38
|
# TODO: fix redundant logic here
|
39
39
|
skip_if initial_static_questionnaire_request.nil?, 'No request resource was provided - required for manual flow'
|
40
|
+
assert_valid_json(initial_static_questionnaire_request)
|
40
41
|
request = FHIR.from_contents(initial_static_questionnaire_request)
|
41
42
|
assert assert_valid_resource(resource: request, profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters')
|
42
43
|
end
|
@@ -36,6 +36,7 @@ module DaVinciDTRTestKit
|
|
36
36
|
request = fhir_operation("#{url}/Questionnaire/$questionnaire-package",
|
37
37
|
body: JSON.parse(initial_static_questionnaire_request),
|
38
38
|
headers: { 'Content-Type': 'application/json' })
|
39
|
+
assert_valid_json(request.response[:body])
|
39
40
|
resource = FHIR.from_contents(request.response[:body])
|
40
41
|
scratch[:output_parameters] = resource
|
41
42
|
assert_response_status([200, 201], response: request.response)
|
@@ -60,6 +60,7 @@ module DaVinciDTRTestKit
|
|
60
60
|
omit_if resources.blank?,
|
61
61
|
"No #{resource_type} resources provided so the #{profile_url} profile does not apply"
|
62
62
|
resources.each_with_index do |resource, index|
|
63
|
+
assert_valid_json(resource.response[:body])
|
63
64
|
fhir_resource = FHIR.from_contents(resource.response[:body])
|
64
65
|
assert_response_status([200, 202], request: resource, response: resource.response)
|
65
66
|
validate_resource(fhir_resource, resource_type, profile_url, index)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: davinci_dtr_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Naden
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-07-
|
13
|
+
date: 2024-07-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: inferno_core
|