davinci_dtr_test_kit 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/lib/davinci_dtr_test_kit/auth_groups/oauth2_authentication_group.rb +51 -0
- data/lib/davinci_dtr_test_kit/auth_groups/token_request_test.rb +25 -0
- data/lib/davinci_dtr_test_kit/auth_groups/token_validation_test.rb +13 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group.rb +20 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_questionnaire_response_save_test.rb +31 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb +89 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/prepopulation_attestation_test.rb +29 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/prepopulation_override_attestation_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/rendering_enabled_questions_attestation_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_full_ehr_questionnaire_workflow_group.rb +19 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_package_group.rb +16 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_attestation_test.rb +32 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_group.rb +14 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_response_group.rb +23 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_response_save_test.rb +31 -0
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_smart_app_questionnaire_workflow_group.rb +22 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_test.rb +36 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb +35 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +28 -0
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/cql_test.rb +387 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +127 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +118 -0
- data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +55 -0
- data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +39 -0
- data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +104 -0
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +180 -0
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +85 -0
- data/lib/davinci_dtr_test_kit/ext/inferno_core/record_response_route.rb +98 -0
- data/lib/davinci_dtr_test_kit/ext/inferno_core/request.rb +19 -0
- data/lib/davinci_dtr_test_kit/ext/inferno_core/runnable.rb +35 -0
- data/lib/davinci_dtr_test_kit/fixture_loader.rb +99 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +170 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +175 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +140 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json +95 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_dinner_order_static.json +283 -0
- data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_response_dinner_order_static.json +170 -0
- data/lib/davinci_dtr_test_kit/fixtures/pre_populated_questionnaire_response.json +581 -0
- data/lib/davinci_dtr_test_kit/fixtures/questionnaire_package.json +2121 -0
- data/lib/davinci_dtr_test_kit/fixtures.rb +65 -0
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +72 -0
- data/lib/davinci_dtr_test_kit/mock_payer.rb +142 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_libraries_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_expressions_test.rb +20 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_extensions_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +20 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_extensions_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_group.rb +88 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_test.rb +41 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb +44 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_bundles_validation_test.rb +40 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_search_validation_test.rb +42 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +49 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_request_validation_test.rb +61 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_complete_test.rb +17 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_validation_test.rb +43 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_static_group.rb +51 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_libraries_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_expressions_test.rb +20 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_extensions_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_test.rb +33 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb +46 -0
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +50 -0
- data/lib/davinci_dtr_test_kit/tags.rb +8 -0
- data/lib/davinci_dtr_test_kit/urls.rb +50 -0
- data/lib/davinci_dtr_test_kit/validation_test.rb +72 -0
- data/lib/davinci_dtr_test_kit/version.rb +5 -0
- data/lib/davinci_dtr_test_kit.rb +4 -0
- metadata +132 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'ext/inferno_core/runnable'
|
2
|
+
require_relative 'ext/inferno_core/record_response_route'
|
3
|
+
require_relative 'ext/inferno_core/request'
|
4
|
+
require_relative 'auth_groups/oauth2_authentication_group'
|
5
|
+
require_relative 'client_groups/resp_assist_device/dtr_smart_app_questionnaire_workflow_group'
|
6
|
+
require_relative 'client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group'
|
7
|
+
require_relative 'client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group'
|
8
|
+
require_relative 'mock_payer'
|
9
|
+
require_relative 'mock_ehr'
|
10
|
+
require_relative 'version'
|
11
|
+
|
12
|
+
module DaVinciDTRTestKit
|
13
|
+
class DTRSmartAppSuite < Inferno::TestSuite
|
14
|
+
extend MockPayer
|
15
|
+
extend MockEHR
|
16
|
+
|
17
|
+
id :dtr_smart_app
|
18
|
+
title 'Da Vinci DTR SMART App Test Suite'
|
19
|
+
description File.read(File.join(__dir__, 'docs', 'dtr_smart_app_suite_description_v201.md'))
|
20
|
+
|
21
|
+
version VERSION
|
22
|
+
|
23
|
+
# All FHIR validation requsets will use this FHIR validator
|
24
|
+
validator do
|
25
|
+
url ENV.fetch('VALIDATOR_URL')
|
26
|
+
end
|
27
|
+
|
28
|
+
allow_cors QUESTIONNAIRE_PACKAGE_PATH, QUESTIONNAIRE_RESPONSE_PATH, FHIR_RESOURCE_PATH, FHIR_SEARCH_PATH
|
29
|
+
|
30
|
+
route(:get, '/fhir/metadata', method(:metadata_handler))
|
31
|
+
|
32
|
+
record_response_route :post, TOKEN_PATH, 'dtr_auth', method(:token_response) do |request|
|
33
|
+
DTRSmartAppSuite.extract_client_id(request)
|
34
|
+
end
|
35
|
+
|
36
|
+
record_response_route :post, QUESTIONNAIRE_PACKAGE_PATH, QUESTIONNAIRE_PACKAGE_TAG,
|
37
|
+
method(:questionnaire_package_response), resumes: ->(_) { false } do |request|
|
38
|
+
DTRSmartAppSuite.extract_bearer_token(request)
|
39
|
+
end
|
40
|
+
|
41
|
+
record_response_route :post, QUESTIONNAIRE_RESPONSE_PATH, 'dtr_smart_app_questionnaire_response',
|
42
|
+
method(:questionnaire_response_response) do |request|
|
43
|
+
DTRSmartAppSuite.extract_bearer_token(request)
|
44
|
+
end
|
45
|
+
|
46
|
+
record_response_route :get, FHIR_RESOURCE_PATH, SMART_APP_EHR_REQUEST_TAG, method(:get_fhir_resource),
|
47
|
+
resumes: ->(_) { false } do |request|
|
48
|
+
DTRSmartAppSuite.extract_bearer_token(request)
|
49
|
+
end
|
50
|
+
|
51
|
+
record_response_route :get, FHIR_SEARCH_PATH, SMART_APP_EHR_REQUEST_TAG, method(:get_fhir_resource),
|
52
|
+
resumes: ->(_) { false } do |request|
|
53
|
+
DTRSmartAppSuite.extract_bearer_token(request)
|
54
|
+
end
|
55
|
+
|
56
|
+
resume_test_route :get, RESUME_PASS_PATH do |request|
|
57
|
+
DTRSmartAppSuite.extract_token_from_query_params(request)
|
58
|
+
end
|
59
|
+
|
60
|
+
resume_test_route :get, RESUME_FAIL_PATH, result: 'fail' do |request|
|
61
|
+
DTRSmartAppSuite.extract_token_from_query_params(request)
|
62
|
+
end
|
63
|
+
|
64
|
+
group from: :oauth2_authentication
|
65
|
+
group do
|
66
|
+
id :dtr_smart_app_basic_workflows
|
67
|
+
title 'Basic Workflows'
|
68
|
+
description %(
|
69
|
+
Tests in this group validate that the client can complete basic DTR workflows
|
70
|
+
)
|
71
|
+
|
72
|
+
group from: :dtr_smart_app_static_dinner_questionnaire_workflow
|
73
|
+
# group from: :dtr_smart_app_adaptive_dinner_questionnaire_workflow - TODO
|
74
|
+
end
|
75
|
+
group do
|
76
|
+
id :dtr_smart_app_questionnaire_functionality
|
77
|
+
title 'Questionnaire Functionality Coverage'
|
78
|
+
description %(
|
79
|
+
Tests in this group validate that the client can complete additional DTR workflows
|
80
|
+
covering additional must support features of questionnaires.
|
81
|
+
)
|
82
|
+
group from: :dtr_smart_app_questionnaire_workflow
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'hanami/controller'
|
2
|
+
|
3
|
+
module Inferno
|
4
|
+
module DSL
|
5
|
+
# A base class for creating routes with custom response logic. Requests and responses are tagged and saved.
|
6
|
+
# @private
|
7
|
+
# @see Inferno::DSL::Runnable#resume_test_route
|
8
|
+
class RecordResponseRoute < Hanami::Action
|
9
|
+
include Import[
|
10
|
+
requests_repo: 'inferno.repositories.requests',
|
11
|
+
results_repo: 'inferno.repositories.results',
|
12
|
+
test_runs_repo: 'inferno.repositories.test_runs',
|
13
|
+
tests_repo: 'inferno.repositories.tests'
|
14
|
+
]
|
15
|
+
|
16
|
+
def self.call(...)
|
17
|
+
new.call(...)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @private
|
21
|
+
def test_run_identifier_block
|
22
|
+
self.class.singleton_class.instance_variable_get(:@test_run_identifier_block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @private
|
26
|
+
def build_response_block
|
27
|
+
self.class.singleton_class.instance_variable_get(:@build_response_block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @private
|
31
|
+
def tags
|
32
|
+
self.class.singleton_class.instance_variable_get(:@tags)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @private
|
36
|
+
def resumes?(test)
|
37
|
+
instance_exec(test, &self.class.singleton_class.instance_variable_get(:@resumes))
|
38
|
+
end
|
39
|
+
|
40
|
+
# @private
|
41
|
+
def find_test_run(test_run_identifier)
|
42
|
+
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @private
|
46
|
+
def find_waiting_result(test_run)
|
47
|
+
results_repo.find_waiting_result(test_run_id: test_run.id)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @private
|
51
|
+
def update_result(waiting_result)
|
52
|
+
results_repo.update_result(waiting_result.id, 'pass')
|
53
|
+
end
|
54
|
+
|
55
|
+
# @private
|
56
|
+
def persist_request(request, test_run, waiting_result, test)
|
57
|
+
requests_repo.create(
|
58
|
+
request.to_hash.merge(
|
59
|
+
test_session_id: test_run.test_session_id,
|
60
|
+
result_id: waiting_result.id,
|
61
|
+
name: test.config.request_name(test.incoming_request_name),
|
62
|
+
tags:
|
63
|
+
)
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @private
|
68
|
+
def find_test(waiting_result)
|
69
|
+
tests_repo.find(waiting_result.test_id)
|
70
|
+
end
|
71
|
+
|
72
|
+
# @private
|
73
|
+
def handle(req, res)
|
74
|
+
request = Inferno::Entities::Request.from_hanami_request(req)
|
75
|
+
|
76
|
+
test_run_identifier = instance_exec(request, &test_run_identifier_block)
|
77
|
+
|
78
|
+
test_run = find_test_run(test_run_identifier)
|
79
|
+
|
80
|
+
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
81
|
+
|
82
|
+
waiting_result = find_waiting_result(test_run)
|
83
|
+
test = find_test(waiting_result)
|
84
|
+
|
85
|
+
test_runs_repo.mark_as_no_longer_waiting(test_run.id) if resumes? test
|
86
|
+
|
87
|
+
update_result(waiting_result) if resumes? test
|
88
|
+
|
89
|
+
instance_exec(request, test, waiting_result, &build_response_block)
|
90
|
+
|
91
|
+
Inferno::Entities::Request.to_hanami_response(request, res)
|
92
|
+
persist_request(request, test_run, waiting_result, test)
|
93
|
+
|
94
|
+
Jobs.perform(Jobs::ResumeTestRun, test_run.id) if resumes? test
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Inferno
|
2
|
+
module Entities
|
3
|
+
class Request
|
4
|
+
def self.to_hanami_response(request, response)
|
5
|
+
response.status = request.status
|
6
|
+
response.body = request.response_body
|
7
|
+
request.response_headers.each do |header|
|
8
|
+
response.headers[header.name] = header.value
|
9
|
+
end
|
10
|
+
|
11
|
+
response
|
12
|
+
end
|
13
|
+
|
14
|
+
def response_headers=(headers_hash)
|
15
|
+
headers.concat(headers_hash.map { |key, value| Header.new(name: key.to_s, value:, type: 'response') })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'record_response_route'
|
2
|
+
|
3
|
+
module Inferno
|
4
|
+
module DSL
|
5
|
+
module Runnable
|
6
|
+
PRE_FLIGHT_HANDLER = proc do
|
7
|
+
[
|
8
|
+
200,
|
9
|
+
{
|
10
|
+
'Access-Control-Allow-Origin' => '*',
|
11
|
+
'Access-Control-Allow-Headers' => 'Content-Type, Authorization'
|
12
|
+
},
|
13
|
+
['']
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow_cors(*paths)
|
18
|
+
paths.each do |path|
|
19
|
+
route(:options, path, PRE_FLIGHT_HANDLER)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def record_response_route(method, path, tags, build_response, resumes: ->(_) { true }, &block)
|
24
|
+
route_class = Class.new(Inferno::DSL::RecordResponseRoute) do |klass|
|
25
|
+
klass.singleton_class.instance_variable_set(:@build_response_block, build_response)
|
26
|
+
klass.singleton_class.instance_variable_set(:@test_run_identifier_block, block)
|
27
|
+
klass.singleton_class.instance_variable_set(:@tags, Array.wrap(tags))
|
28
|
+
klass.singleton_class.instance_variable_set(:@resumes, resumes)
|
29
|
+
end
|
30
|
+
|
31
|
+
route(method, path, route_class)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'fhir_models'
|
3
|
+
|
4
|
+
module DaVinciDTRTestKit
|
5
|
+
class FixtureLoader
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
# list of lists
|
10
|
+
# - first entry is the path to a file containing a Questionnaire Bundle (not Parameters)
|
11
|
+
# - second entry is the path to a file containing a Populated QuestionnaireResponse
|
12
|
+
# for use in validation.
|
13
|
+
# - third entry is a list of group id within which this questionnaire should be used and
|
14
|
+
# will be returned for any $questionnaire-package calls. This association of a questionnaire
|
15
|
+
# with a specific test is Inferno's simulated version of payer business logic.
|
16
|
+
questionnaires_to_load =
|
17
|
+
[
|
18
|
+
[
|
19
|
+
'fixtures/questionnaire_package.json',
|
20
|
+
'fixtures/pre_populated_questionnaire_response.json',
|
21
|
+
['dtr_smart_app_questionnaire_workflow', 'dtr_full_ehr_questionnaire_workflow']
|
22
|
+
],
|
23
|
+
[
|
24
|
+
'fixtures/dinner_static/questionnaire_dinner_order_static.json',
|
25
|
+
'fixtures/dinner_static/questionnaire_response_dinner_order_static.json',
|
26
|
+
['dtr_smart_app_static_dinner_questionnaire_workflow']
|
27
|
+
],
|
28
|
+
[
|
29
|
+
'fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json',
|
30
|
+
'',
|
31
|
+
['dtr_smart_app_adaptive_dinner_questionnaire_workflow']
|
32
|
+
]
|
33
|
+
]
|
34
|
+
|
35
|
+
questionnaires_to_load.each do |questionnaire_details|
|
36
|
+
init_questionnaire_package_and_response(questionnaire_details[0], questionnaire_details[1],
|
37
|
+
questionnaire_details[2])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def canonical_to_questionnaire_package_map
|
42
|
+
@canonical_to_questionnaire_package_map ||= {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def questionnaire_package_for_canonical(url)
|
46
|
+
@canonical_to_questionnaire_package_map[url]
|
47
|
+
end
|
48
|
+
|
49
|
+
def group_id_to_questionnaire_canonical_map
|
50
|
+
@group_id_to_questionnaire_canonical_map ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def questionnaire_canonical_for_group_id(group_id)
|
54
|
+
group_id_to_questionnaire_canonical_map[group_id]
|
55
|
+
end
|
56
|
+
|
57
|
+
def questionnaire_package_for_group_id(group_id)
|
58
|
+
canonical = questionnaire_canonical_for_group_id(group_id)
|
59
|
+
return unless canonical
|
60
|
+
|
61
|
+
@canonical_to_questionnaire_package_map[canonical]
|
62
|
+
end
|
63
|
+
|
64
|
+
def group_id_to_questionnaire_response_map
|
65
|
+
@group_id_to_questionnaire_response_map ||= {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def questionnaire_response_for_group_id(group_id)
|
69
|
+
group_id_to_questionnaire_response_map[group_id]
|
70
|
+
end
|
71
|
+
|
72
|
+
def init_questionnaire_package_and_response(package_file, response_file = nil, covered_groups = nil)
|
73
|
+
package_json = File.read(File.join(__dir__, package_file))
|
74
|
+
package = FHIR.from_contents(package_json)
|
75
|
+
url = get_url_for_questionnaire(package)
|
76
|
+
|
77
|
+
canonical_to_questionnaire_package_map[url] = package if url
|
78
|
+
covered_groups&.each do |group|
|
79
|
+
group_id_to_questionnaire_canonical_map[group] = url
|
80
|
+
end
|
81
|
+
|
82
|
+
if response_file.present?
|
83
|
+
response_json = File.read(File.join(__dir__, response_file))
|
84
|
+
response = FHIR.from_contents(response_json)
|
85
|
+
|
86
|
+
covered_groups&.each do |group|
|
87
|
+
group_id_to_questionnaire_response_map[group] = response
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
package
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_url_for_questionnaire(questionnaire_bundle)
|
96
|
+
questionnaire_bundle.entry[0].resource.url
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
{
|
2
|
+
"resourceType": "Questionnaire",
|
3
|
+
"id": "DinnerOrderAdaptive",
|
4
|
+
"meta": {
|
5
|
+
"profile": [
|
6
|
+
"http://hl7.org/fhir/StructureDefinition/cqf-questionnaire",
|
7
|
+
"http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt"
|
8
|
+
]
|
9
|
+
},
|
10
|
+
"extension": [
|
11
|
+
{
|
12
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-questionnaireAdaptive",
|
13
|
+
"valueBoolean": true
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"url": "http://hl7.org/fhir/StructureDefinition/cqf-library",
|
17
|
+
"valueCanonical": "https://madie.cms.gov/Library/DTRTest"
|
18
|
+
}
|
19
|
+
],
|
20
|
+
"name": "DinnerOrderAdaptive",
|
21
|
+
"title": "Dinner Order (Adaptive)",
|
22
|
+
"status": "draft",
|
23
|
+
"subjectType": [
|
24
|
+
"Patient"
|
25
|
+
],
|
26
|
+
"date": "2024-05-06",
|
27
|
+
"publisher": "Inferno",
|
28
|
+
"item": [
|
29
|
+
{
|
30
|
+
"extension": [
|
31
|
+
{
|
32
|
+
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
33
|
+
"valueCodeableConcept": {
|
34
|
+
"coding": [
|
35
|
+
{
|
36
|
+
"system": "http://hl7.org/fhir/questionnaire-item-control",
|
37
|
+
"code": "gtable"
|
38
|
+
}
|
39
|
+
]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
],
|
43
|
+
"linkId": "PBD",
|
44
|
+
"text": "Patient Information",
|
45
|
+
"type": "group",
|
46
|
+
"item": [
|
47
|
+
{
|
48
|
+
"extension": [
|
49
|
+
{
|
50
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
51
|
+
"valueExpression": {
|
52
|
+
"language": "text/cql",
|
53
|
+
"expression": "\"DTRTest\".LastName"
|
54
|
+
}
|
55
|
+
}
|
56
|
+
],
|
57
|
+
"linkId": "PBD.1",
|
58
|
+
"text": "Last Name:",
|
59
|
+
"type": "string",
|
60
|
+
"required": true
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"extension": [
|
64
|
+
{
|
65
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
66
|
+
"valueExpression": {
|
67
|
+
"language": "text/cql",
|
68
|
+
"expression": "\"DTRTest\".FirstName"
|
69
|
+
}
|
70
|
+
}
|
71
|
+
],
|
72
|
+
"linkId": "PBD.2",
|
73
|
+
"text": "First Name:",
|
74
|
+
"type": "string",
|
75
|
+
"required": true
|
76
|
+
}
|
77
|
+
]
|
78
|
+
},
|
79
|
+
{
|
80
|
+
"extension": [
|
81
|
+
{
|
82
|
+
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
83
|
+
"valueCodeableConcept": {
|
84
|
+
"coding": [
|
85
|
+
{
|
86
|
+
"system": "http://hl7.org/fhir/questionnaire-item-control",
|
87
|
+
"code": "gtable"
|
88
|
+
}
|
89
|
+
]
|
90
|
+
}
|
91
|
+
}
|
92
|
+
],
|
93
|
+
"linkId": "LOC",
|
94
|
+
"text": "Patient's Location",
|
95
|
+
"type": "group",
|
96
|
+
"item": [
|
97
|
+
{
|
98
|
+
"extension": [
|
99
|
+
{
|
100
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
101
|
+
"valueExpression": {
|
102
|
+
"language": "text/cql",
|
103
|
+
"expression": "\"DTRTest\".FirstLocationDescription"
|
104
|
+
}
|
105
|
+
}
|
106
|
+
],
|
107
|
+
"linkId": "LOC.1",
|
108
|
+
"text": "Location",
|
109
|
+
"type": "string",
|
110
|
+
"required": true
|
111
|
+
}
|
112
|
+
]
|
113
|
+
},
|
114
|
+
{
|
115
|
+
"linkId": "3",
|
116
|
+
"text": "Dinner Order",
|
117
|
+
"type": "group",
|
118
|
+
"item": [
|
119
|
+
{
|
120
|
+
"linkId": "3.1",
|
121
|
+
"text": "What would you like for dinner?",
|
122
|
+
"type": "choice",
|
123
|
+
"required": true,
|
124
|
+
"answerOption": [
|
125
|
+
{
|
126
|
+
"valueCoding": {
|
127
|
+
"code": "Hamburger"
|
128
|
+
}
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"valueCoding": {
|
132
|
+
"code": "Bean Burrito"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
]
|
136
|
+
},
|
137
|
+
{
|
138
|
+
"linkId": "3.2.b",
|
139
|
+
"text": "What would you like on your bean burrito?",
|
140
|
+
"type": "choice",
|
141
|
+
"required": false,
|
142
|
+
"repeats": true,
|
143
|
+
"answerOption": [
|
144
|
+
{
|
145
|
+
"valueCoding": {
|
146
|
+
"code": "Cheese"
|
147
|
+
}
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"valueCoding": {
|
151
|
+
"code": "Pico de Gallo"
|
152
|
+
}
|
153
|
+
},
|
154
|
+
{
|
155
|
+
"valueCoding": {
|
156
|
+
"code": "Guacamole"
|
157
|
+
}
|
158
|
+
}
|
159
|
+
]
|
160
|
+
},
|
161
|
+
{
|
162
|
+
"linkId": "3.3",
|
163
|
+
"text": "Any special requests?",
|
164
|
+
"type": "string",
|
165
|
+
"required": false
|
166
|
+
}
|
167
|
+
]
|
168
|
+
}
|
169
|
+
]
|
170
|
+
}
|
@@ -0,0 +1,175 @@
|
|
1
|
+
{
|
2
|
+
"resourceType": "Questionnaire",
|
3
|
+
"id": "DinnerOrderAdaptive",
|
4
|
+
"meta": {
|
5
|
+
"profile": [
|
6
|
+
"http://hl7.org/fhir/StructureDefinition/cqf-questionnaire",
|
7
|
+
"http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt"
|
8
|
+
]
|
9
|
+
},
|
10
|
+
"extension": [
|
11
|
+
{
|
12
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-questionnaireAdaptive",
|
13
|
+
"valueBoolean": true
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"url": "http://hl7.org/fhir/StructureDefinition/cqf-library",
|
17
|
+
"valueCanonical": "https://madie.cms.gov/Library/DTRTest"
|
18
|
+
}
|
19
|
+
],
|
20
|
+
"name": "DinnerOrderAdaptive",
|
21
|
+
"title": "Dinner Order (Adaptive)",
|
22
|
+
"status": "draft",
|
23
|
+
"subjectType": [
|
24
|
+
"Patient"
|
25
|
+
],
|
26
|
+
"date": "2024-05-06",
|
27
|
+
"publisher": "Inferno",
|
28
|
+
"item": [
|
29
|
+
{
|
30
|
+
"extension": [
|
31
|
+
{
|
32
|
+
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
33
|
+
"valueCodeableConcept": {
|
34
|
+
"coding": [
|
35
|
+
{
|
36
|
+
"system": "http://hl7.org/fhir/questionnaire-item-control",
|
37
|
+
"code": "gtable"
|
38
|
+
}
|
39
|
+
]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
],
|
43
|
+
"linkId": "PBD",
|
44
|
+
"text": "Patient Information",
|
45
|
+
"type": "group",
|
46
|
+
"item": [
|
47
|
+
{
|
48
|
+
"extension": [
|
49
|
+
{
|
50
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
51
|
+
"valueExpression": {
|
52
|
+
"language": "text/cql",
|
53
|
+
"expression": "\"DTRTest\".LastName"
|
54
|
+
}
|
55
|
+
}
|
56
|
+
],
|
57
|
+
"linkId": "PBD.1",
|
58
|
+
"text": "Last Name:",
|
59
|
+
"type": "string",
|
60
|
+
"required": true
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"extension": [
|
64
|
+
{
|
65
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
66
|
+
"valueExpression": {
|
67
|
+
"language": "text/cql",
|
68
|
+
"expression": "\"DTRTest\".FirstName"
|
69
|
+
}
|
70
|
+
}
|
71
|
+
],
|
72
|
+
"linkId": "PBD.2",
|
73
|
+
"text": "First Name:",
|
74
|
+
"type": "string",
|
75
|
+
"required": true
|
76
|
+
}
|
77
|
+
]
|
78
|
+
},
|
79
|
+
{
|
80
|
+
"extension": [
|
81
|
+
{
|
82
|
+
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
83
|
+
"valueCodeableConcept": {
|
84
|
+
"coding": [
|
85
|
+
{
|
86
|
+
"system": "http://hl7.org/fhir/questionnaire-item-control",
|
87
|
+
"code": "gtable"
|
88
|
+
}
|
89
|
+
]
|
90
|
+
}
|
91
|
+
}
|
92
|
+
],
|
93
|
+
"linkId": "LOC",
|
94
|
+
"text": "Patient's Location",
|
95
|
+
"type": "group",
|
96
|
+
"item": [
|
97
|
+
{
|
98
|
+
"extension": [
|
99
|
+
{
|
100
|
+
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
|
101
|
+
"valueExpression": {
|
102
|
+
"language": "text/cql",
|
103
|
+
"expression": "\"DTRTest\".FirstLocationDescription"
|
104
|
+
}
|
105
|
+
}
|
106
|
+
],
|
107
|
+
"linkId": "LOC.1",
|
108
|
+
"text": "Location",
|
109
|
+
"type": "string",
|
110
|
+
"required": true
|
111
|
+
}
|
112
|
+
]
|
113
|
+
},
|
114
|
+
{
|
115
|
+
"linkId": "3",
|
116
|
+
"text": "Dinner Order",
|
117
|
+
"type": "group",
|
118
|
+
"item": [
|
119
|
+
{
|
120
|
+
"linkId": "3.1",
|
121
|
+
"text": "What would you like for dinner?",
|
122
|
+
"type": "choice",
|
123
|
+
"required": true,
|
124
|
+
"answerOption": [
|
125
|
+
{
|
126
|
+
"valueCoding": {
|
127
|
+
"code": "Hamburger"
|
128
|
+
}
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"valueCoding": {
|
132
|
+
"code": "Bean Burrito"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
]
|
136
|
+
},
|
137
|
+
{
|
138
|
+
"linkId": "3.2.a",
|
139
|
+
"text": "What would you like on your hamburger?",
|
140
|
+
"type": "choice",
|
141
|
+
"required": false,
|
142
|
+
"repeats": true,
|
143
|
+
"answerOption": [
|
144
|
+
{
|
145
|
+
"valueCoding": {
|
146
|
+
"code": "Ketchup"
|
147
|
+
}
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"valueCoding": {
|
151
|
+
"code": "Mustard"
|
152
|
+
}
|
153
|
+
},
|
154
|
+
{
|
155
|
+
"valueCoding": {
|
156
|
+
"code": "Pickels"
|
157
|
+
}
|
158
|
+
},
|
159
|
+
{
|
160
|
+
"valueCoding": {
|
161
|
+
"code": "Tomato"
|
162
|
+
}
|
163
|
+
}
|
164
|
+
]
|
165
|
+
},
|
166
|
+
{
|
167
|
+
"linkId": "3.3",
|
168
|
+
"text": "Any special requests?",
|
169
|
+
"type": "string",
|
170
|
+
"required": false
|
171
|
+
}
|
172
|
+
]
|
173
|
+
}
|
174
|
+
]
|
175
|
+
}
|