Skip to content

Commit

Permalink
Differentiate inputs for different workflows (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
tstrass authored Dec 3, 2024
1 parent 4ee804d commit 5dfceac
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,35 @@ class DTRSmartAppAdaptiveQuestionnaireRequestTest < Inferno::Test
input :launch_uri,
optional: true,
description: 'Required if "Launch from Inferno" is selected'
input :smart_patient_id,
input :adaptive_smart_patient_id,
optional: true,
title: 'SMART App Launch Patient ID (Dinner Adaptive)',
type: 'text',
description: %(
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
Launch.
),
Patient instance ID to be provided by Inferno as the patient as a part of the SMART App Launch.
),
default: 'pat015'
input :smart_fhir_context,
input :adaptive_smart_fhir_context,
optional: true,
title: 'SMART App Launch fhirContext (Dinner Adaptive)',
type: 'textarea',
description: %(
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
Launch. These references help determine the behavior of the app. Referenced instances
may be provided in the "EHR-available resources" input.
),
References to be provided by Inferno as the fhirContext as a part of the SMART App
Launch. These references help determine the behavior of the app. Referenced instances
may be provided in the "EHR-available resources" input.
),
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
{ reference: 'DeviceRequest/devreqe0470' }])
input :ehr_bundle,
input :adaptive_ehr_bundle,
optional: true,
title: 'EHR-available resources (Dinner Adaptive)',
type: 'textarea',
description: %(
Resources available from the EHR needed to drive the dinner adaptive workflow.
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
instance present will be available for retrieval from Inferno at the endpoint:
```
[fhir-base]/[resource type]/[instance id]
```
)
Resources available from the EHR needed to drive the dinner adaptive workflow.
Formatted as a FHIR bundle that contains resources, each with an ID property populated. Each
instance present will be available for retrieval from Inferno at the endpoint:
<fhir-base>/<resource type>/<instance id>
)

def example_client_jwt_payload_part
Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
Expand All @@ -69,19 +65,19 @@ def example_client_jwt_payload_part
run do
# validate relevant inputs and provide warnings if they are bad
warning do
if smart_fhir_context
assert_valid_json(smart_fhir_context,
if adaptive_smart_fhir_context
assert_valid_json(adaptive_smart_fhir_context,
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
the access token response.')
end
end

warning do
if ehr_bundle
assert_valid_json(ehr_bundle,
if adaptive_ehr_bundle
assert_valid_json(adaptive_ehr_bundle,
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
will be available to access from Inferno.')
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
assert(FHIR.from_contents(adaptive_ehr_bundle).is_a?(FHIR::Bundle),
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
will be available to access from Inferno.')
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,34 @@ class DTRSmartAppDinnerQuestionnairePackageRequestTest < Inferno::Test
input :launch_uri,
optional: true,
description: 'Required if "Launch from Inferno" is selected'
input :smart_patient_id,
input :static_smart_patient_id,
optional: true,
title: 'SMART App Launch Patient ID (Dinner Static)',
type: 'text',
description: %(
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
Launch.
Patient instance ID to be provided by Inferno as the patient as a part of the SMART App Launch.
),
default: 'pat015'
input :smart_fhir_context,
input :static_smart_fhir_context,
optional: true,
title: 'SMART App Launch fhirContext (Dinner Static)',
type: 'textarea',
description: %(
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
References to be provided by Inferno as the fhirContext as a part of the SMART App
Launch. These references help determine the behavior of the app. Referenced instances
may be provided in the "EHR-available resources" input.
),
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
{ reference: 'DeviceRequest/devreqe0470' }])
input :ehr_bundle,
input :static_ehr_bundle,
optional: true,
title: 'EHR-available resources (Dinner Static)',
type: 'textarea',
description: %(
Resources available from the EHR needed to drive the dinner static workflow.
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
Formatted as a FHIR bundle that contains resources, each with an ID property populated. Each
instance present will be available for retrieval from Inferno at the endpoint:
```
[fhir-base]/[resource type]/[instance id]
```
<fhir-base>/<resource type>/<instance id>
)

def example_client_jwt_payload_part
Expand All @@ -62,19 +58,19 @@ def example_client_jwt_payload_part
run do
# validate relevant inputs and provide warnings if they are bad
warning do
if smart_fhir_context
assert_valid_json(smart_fhir_context,
if static_smart_fhir_context
assert_valid_json(static_smart_fhir_context,
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
the access token response.')
end
end

warning do
if ehr_bundle
assert_valid_json(ehr_bundle,
if static_ehr_bundle
assert_valid_json(static_ehr_bundle,
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
will be available to access from Inferno.')
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
assert(FHIR.from_contents(static_ehr_bundle).is_a?(FHIR::Bundle),
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
will be available to access from Inferno.')
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,34 @@ class DTRRespQuestionnairePackageRequestTest < Inferno::Test
input :launch_uri,
optional: true,
description: 'Required if "Launch from Inferno" is selected'
input :smart_patient_id,
input :resp_smart_patient_id,
optional: true,
title: 'SMART App Launch Patient ID (Respiratory Assist Device)',
type: 'text',
description: %(
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
Launch.
Patient instance ID to be provided by Inferno as the patient as a part of the SMART App Launch.
),
default: 'pat015'
input :smart_fhir_context,
input :resp_smart_fhir_context,
optional: true,
title: 'SMART App Launch fhirContext (Respiratory Assist Device)',
type: 'textarea',
description: %(
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
References to be provided by Inferno as the fhirContext as a part of the SMART App
Launch. These references help determine the behavior of the app. Referenced instances
may be provided in the "EHR-available resources" input.
),
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
{ reference: 'DeviceRequest/devreqe0470' }])
input :ehr_bundle,
input :resp_ehr_bundle,
optional: true,
title: 'EHR-available resources (Respiratory Assist Device)',
type: 'textarea',
description: %(
Resources available from the EHR needed to drive the respiratory assist device workflow.
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
instance present will be available for retrieval from Inferno at the endpoint
```
[fhir-base]/[resource type]/[instance id]
```
Formatted as a FHIR bundle that contains resources, each with an ID property populated. Each
instance present will be available for retrieval from Inferno at the endpoint:
<fhir-base>/<resource type>/<instance id>
)

def example_client_jwt_payload_part
Expand All @@ -61,19 +57,19 @@ def example_client_jwt_payload_part
run do
# validate relevant inputs and provide warnings if they are bad
warning do
if smart_fhir_context
assert_valid_json(smart_fhir_context,
if resp_smart_fhir_context
assert_valid_json(resp_smart_fhir_context,
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
the access token response.')
end
end

warning do
if ehr_bundle
assert_valid_json(ehr_bundle,
if resp_ehr_bundle
assert_valid_json(resp_ehr_bundle,
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
will be available to access from Inferno.')
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
assert(FHIR.from_contents(resp_ehr_bundle).is_a?(FHIR::Bundle),
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
will be available to access from Inferno.')
end
Expand Down
16 changes: 13 additions & 3 deletions lib/davinci_dtr_test_kit/mock_auth_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def ehr_authorize(request, _test = nil, _test_result = nil)
end
end

def ehr_token_response(request, _test = nil, test_result = nil)
def ehr_token_response(request, test = nil, test_result = nil)
client_id = extract_client_id_from_token_request(request)
access_token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
granted_scopes = SUPPORTED_SCOPES & requested_scopes(test_result.test_session_id)
Expand All @@ -101,7 +101,7 @@ def ehr_token_response(request, _test = nil, test_result = nil)
response.merge!(id_token: create_id_token(request, client_id, fhir_user: granted_scopes.include?('fhirUser')))
end

fhir_context_input = find_test_input(test_result, 'smart_fhir_context')
fhir_context_input = find_test_input(test_result, "#{input_group_prefix(test)}_smart_fhir_context")
fhir_context_input_value = fhir_context_input['value'] if fhir_context_input
begin
fhir_context = JSON.parse(fhir_context_input_value)
Expand All @@ -110,7 +110,7 @@ def ehr_token_response(request, _test = nil, test_result = nil)
end
response.merge!(fhirContext: fhir_context) if fhir_context

smart_patient_input = find_test_input(test_result, 'smart_patient_id')
smart_patient_input = find_test_input(test_result, "#{input_group_prefix(test)}_smart_patient_id")
smart_patient_input_value = smart_patient_input['value'] if smart_patient_input.present?
response.merge!(patient: smart_patient_input_value) if smart_patient_input_value

Expand Down Expand Up @@ -214,6 +214,16 @@ def requested_scopes(test_session_id)
scope_str ? URI.decode_www_form_component(scope_str).split : []
end

def input_group_prefix(test)
if test.id.include?('static')
'static'
elsif test.id.include?('adaptive')
'adaptive'
else
'resp'
end
end

def find_test_input(test_result, input_name)
JSON.parse(test_result.input_json)&.find { |input| input['name'] == input_name }
end
Expand Down
19 changes: 15 additions & 4 deletions lib/davinci_dtr_test_kit/mock_ehr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def metadata_handler(_env)
end
end

def get_fhir_resource(request, _test = nil, test_result = nil)
def get_fhir_resource(request, test = nil, test_result = nil)
fhir_class, id = fhir_class_and_id_from_url(request.url)
request.response_headers = RESPONSE_HEADERS

Expand All @@ -43,7 +43,7 @@ def get_fhir_resource(request, _test = nil, test_result = nil)
end

# Respond with user-inputted resource if there is one that matches the request
ehr_bundle = ehr_input_bundle(test_result)
ehr_bundle = ehr_input_bundle(test, test_result)
if id.present? && ehr_bundle.present?
matching_resource = find_resource_in_bundle(ehr_bundle, fhir_class, id)
if matching_resource.present?
Expand All @@ -70,15 +70,26 @@ def questionnaire_response_response(request, _test = nil, _test_result = nil)
request.response_body = request.request_body
end

def ehr_input_bundle(test_result)
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'ehr_bundle' }
def ehr_input_bundle(test, test_result)
input_name = "#{input_group_prefix(test)}_ehr_bundle"
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == input_name }
ehr_bundle_input_value = ehr_bundle_input_value = ehr_bundle_input['value'] if ehr_bundle_input.present?
ehr_bundle = FHIR.from_contents(ehr_bundle_input_value) if ehr_bundle_input_value.present?
ehr_bundle if ehr_bundle.is_a?(FHIR::Bundle)
rescue StandardError
nil
end

def input_group_prefix(test)
if test.id.include?('static')
'static'
elsif test.id.include?('adaptive')
'adaptive'
else
'resp'
end
end

def find_resource_in_bundle(bundle, fhir_class, id)
bundle.entry&.find do |entry|
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
Expand Down

0 comments on commit 5dfceac

Please sign in to comment.