davinci_dtr_test_kit 0.12.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_completion_group.rb +23 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_followup_questions_group.rb +26 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_test.rb +93 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_validation_test.rb +62 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_retrieval_group.rb +23 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_response_validation_test.rb +66 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_dinner_questionnaire_workflow_group.rb +76 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_initial_retrieval_group.rb +27 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_request_test.rb +63 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_initial_retrieval_group.rb +24 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_request_test.rb +148 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group.rb +75 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group.rb +22 -28
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb +14 -17
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb +9 -31
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_launch_attestation_test.rb +7 -6
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_prepopulation_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_prepopulation_override_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static/dtr_full_ehr_dinner_questionnaire_package_request_test.rb → full_ehr/dtr_full_ehr_questionnaire_package_request_test.rb} +2 -3
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_conformance_test.rb +19 -0
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_correctness_test.rb +37 -0
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_rendering_enabled_questions_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_saving_questionnaire_response_group.rb +29 -0
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_store_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_attestation_test.rb +7 -6
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_resp_questionnaire_package_request_test.rb +15 -18
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +16 -5
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_prepopulation_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_prepopulation_override_attestation_test.rb +7 -6
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_questionnaire_response_save_test.rb +17 -7
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_rendering_enabled_questions_attestation_test.rb +7 -7
- data/lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_saving_questionnaire_response_group.rb +27 -0
- data/lib/davinci_dtr_test_kit/cql_test.rb +114 -172
- data/lib/davinci_dtr_test_kit/create_test.rb +25 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md +95 -37
- data/lib/davinci_dtr_test_kit/docs/dtr_light_ehr_suite_description_v201.md +34 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +32 -29
- data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +48 -32
- data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +13 -17
- data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +101 -23
- data/lib/davinci_dtr_test_kit/dtr_options.rb +7 -0
- data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +9 -20
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +126 -75
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +32 -56
- data/lib/davinci_dtr_test_kit/endpoints/cors.rb +20 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/authorize_endpoint.rb +32 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/simple_token_endpoint.rb +19 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/token_endpoint.rb +116 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_authorization.rb +83 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_ehr/fhir_get_endpoint.rb +95 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_ehr/questionnaire_response_endpoint.rb +22 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_ehr.rb +25 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +11 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +11 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_endpoint.rb +162 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_proxy_endpoint.rb +36 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_endpoint.rb +62 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_proxy_endpoint.rb +38 -0
- data/lib/davinci_dtr_test_kit/endpoints/mock_payer.rb +36 -0
- data/lib/davinci_dtr_test_kit/fixture_loader.rb +6 -84
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +10 -2
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +10 -2
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +10 -2
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json +4 -3
- data/lib/davinci_dtr_test_kit/fixtures.rb +64 -46
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_libraries_test.rb +2 -2
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_expressions_test.rb +4 -3
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_extensions_test.rb +3 -2
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +8 -8
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_extensions_test.rb +6 -5
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_group.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_bundles_validation_test.rb +6 -9
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_search_validation_test.rb +15 -12
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +33 -22
- 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/payer_server_next_response_complete_test.rb +4 -4
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_validation_test.rb +16 -12
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_libraries_test.rb +2 -2
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_expressions_test.rb +5 -4
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_extensions_test.rb +4 -3
- 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 +32 -23
- data/lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/communication_request_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/coverage/coverage_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/coverage/coverage_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/coverage_group.rb +38 -0
- data/lib/davinci_dtr_test_kit/profiles/device_request/device_request_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/device_request/device_request_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/device_request_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/encounter/encounter_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/encounter/encounter_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/encounter_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/medication_request_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/nutrition_order_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_context_search.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_create.rb +26 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_patient_search.rb +55 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_read.rb +22 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_update.rb +26 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_validation.rb +37 -0
- data/lib/davinci_dtr_test_kit/profiles/questionnaire_response_group.rb +66 -0
- data/lib/davinci_dtr_test_kit/profiles/service_request/service_request_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/service_request/service_request_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/service_request_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/profiles/task/task_create.rb +26 -0
- data/lib/davinci_dtr_test_kit/profiles/task/task_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/task/task_update.rb +26 -0
- data/lib/davinci_dtr_test_kit/profiles/task/task_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/task_group.rb +52 -0
- data/lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_read.rb +29 -0
- data/lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_validation.rb +35 -0
- data/lib/davinci_dtr_test_kit/profiles/vision_prescription_group.rb +39 -0
- data/lib/davinci_dtr_test_kit/read_test.rb +22 -0
- data/lib/davinci_dtr_test_kit/tags.rb +5 -6
- data/lib/davinci_dtr_test_kit/update_test.rb +25 -0
- data/lib/davinci_dtr_test_kit/urls.rb +13 -10
- data/lib/davinci_dtr_test_kit/validation_test.rb +21 -5
- data/lib/davinci_dtr_test_kit/version.rb +1 -1
- data/lib/davinci_dtr_test_kit.rb +1 -1
- metadata +129 -24
- 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/ext/inferno_core/record_response_route.rb +0 -98
- data/lib/davinci_dtr_test_kit/ext/inferno_core/request.rb +0 -19
- data/lib/davinci_dtr_test_kit/ext/inferno_core/runnable.rb +0 -35
- data/lib/davinci_dtr_test_kit/mock_auth_server.rb +0 -145
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +0 -97
- data/lib/davinci_dtr_test_kit/mock_payer.rb +0 -123
- /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
@@ -14,25 +14,21 @@ module DaVinciDTRTestKit
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def cqf_reference_libraries
|
17
|
-
|
17
|
+
scratch[:cqf_reference_libraries] ||= Set.new
|
18
18
|
end
|
19
19
|
|
20
20
|
def library_urls
|
21
|
-
|
21
|
+
scratch[:library_urls] ||= Set.new
|
22
22
|
end
|
23
23
|
|
24
24
|
def library_names
|
25
|
-
|
25
|
+
scratch[:library_names] ||= Set.new
|
26
26
|
end
|
27
27
|
|
28
28
|
def found_questionnaire
|
29
29
|
@found_questionnaire ||= false
|
30
30
|
end
|
31
31
|
|
32
|
-
def found_bad_library_reference
|
33
|
-
@@found_bad_library_reference ||= false
|
34
|
-
end
|
35
|
-
|
36
32
|
def found_duplicate_library_name
|
37
33
|
@found_duplicate_library_name ||= false
|
38
34
|
end
|
@@ -52,97 +48,20 @@ module DaVinciDTRTestKit
|
|
52
48
|
extension_presence.each_key { |k| extension_presence[k] = false }
|
53
49
|
end
|
54
50
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
found_questionnaire = false
|
59
|
-
if resource.instance_of? Array
|
60
|
-
resource.each do |individual_resource|
|
61
|
-
next unless individual_resource.resourceType == 'QuestionnaireResponse'
|
62
|
-
|
63
|
-
individual_resource.contained.each_with_index do |questionnaire, q_index|
|
64
|
-
# Do out put parameters have a bundle?
|
65
|
-
next unless questionnaire.resourceType == 'Questionnaire'
|
66
|
-
|
67
|
-
# check the libraries first so references in questionnaires can be checked after
|
68
|
-
found_questionnaire = true
|
69
|
-
check_questionnaire_extensions(questionnaire, q_index)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
elsif resource.resourceType == 'Parameters'
|
73
|
-
resource.parameter.each do |param|
|
74
|
-
# Do out put parameters have a bundle?
|
75
|
-
next unless param.resource.resourceType == 'Bundle'
|
76
|
-
|
77
|
-
param.resource.entry.each_with_index do |entry, q_index|
|
78
|
-
# check questionnaire extensions
|
79
|
-
next unless entry.resource.resourceType == 'Questionnaire'
|
80
|
-
|
81
|
-
found_questionnaire = true
|
82
|
-
check_questionnaire_extensions(entry.resource, q_index)
|
83
|
-
## NEED TO FIGURE OUT HOW TO FAIL TEST WHEN POORLY FORMATTED EXPRESSIONS FOUND
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
51
|
+
def verify_questionnaire_extensions(questionnaires)
|
52
|
+
assert questionnaires&.any? && questionnaires.all? { |q| q.is_a? FHIR::Questionnaire }, 'No questionnaires found.'
|
53
|
+
questionnaires.each_with_index { |q, q_index| check_questionnaire_extensions(q, q_index) }
|
87
54
|
check_library_references
|
88
|
-
assert found_questionnaire, 'No questionnaires found.'
|
89
55
|
assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
|
90
56
|
assert cql_presence['variable'], 'Variable expression logic not written in CQL.'
|
91
57
|
assert cql_presence['launch_context'], 'Launch context expression logic not written in CQL.'
|
92
58
|
assert cql_presence['pop_context'], 'Population context expression logic not written in CQL.'
|
93
59
|
end
|
94
60
|
|
95
|
-
def questionnaire_items_test(response, final_cql_test)
|
96
|
-
resource = process_response(response)
|
97
|
-
assert !resource.nil?, 'Response is null or not a valid type.'
|
98
|
-
found_bundle = found_questionnaire = false
|
99
|
-
# are extensions present in any questionnaire?
|
100
|
-
if resource.instance_of? Array
|
101
|
-
resource.each_with_index do |individual_resource, q_index|
|
102
|
-
next unless individual_resource.resourceType == 'QuestionnaireResponse'
|
103
|
-
|
104
|
-
individual_resource.contained.each do |questionnaire|
|
105
|
-
# Do out put parameters have a bundle?
|
106
|
-
next unless questionnaire.resourceType == 'Questionnaire'
|
107
|
-
|
108
|
-
# check the libraries first so references in questionnaires can be checked after
|
109
|
-
found_questionnaire = true
|
110
|
-
check_questionnaire_items(questionnaire, q_index)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
elsif resource.resourceType == 'Parameters'
|
114
|
-
resource.parameter.each do |param|
|
115
|
-
# Do out put parameters have a bundle?
|
116
|
-
next unless param.resource.resourceType == 'Bundle'
|
117
|
-
|
118
|
-
found_bundle = true
|
119
|
-
# check the libraries first so references in questionnaires can be checked after
|
120
|
-
param.resource.entry.each_with_index do |entry, q_index|
|
121
|
-
if entry.resource.resourceType == 'Questionnaire'
|
122
|
-
found_questionnaire = true
|
123
|
-
check_questionnaire_items(entry.resource, q_index)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
assert found_bundle, 'No questionnaire bundles found.'
|
128
|
-
end
|
129
|
-
begin
|
130
|
-
assert found_questionnaire, 'No questionnaires found.'
|
131
|
-
assert !found_non_cql_expression, 'Found non-cql expression.'
|
132
|
-
assert !found_bad_library_reference, 'Found expression with no or incorrect reference to library name.'
|
133
|
-
assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
|
134
|
-
assert cql_presence['init_expression'], 'Initial expression logic not written in CQL.'
|
135
|
-
assert cql_presence['candidate_expression'], 'Candidate expression logic not written in CQL.'
|
136
|
-
assert cql_presence['context_expression'], 'Context expression logic not written in CQL.'
|
137
|
-
ensure
|
138
|
-
reset_cql_tests if final_cql_test
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
61
|
def check_questionnaire_extensions(questionnaire, q_index)
|
143
62
|
# are extensions present in this questionnaire?
|
144
63
|
found_launch_context = found_variable = found_pop_context = found_cqf_lib = false
|
145
|
-
cqf_count =
|
64
|
+
cqf_count = total_cqf_libs(questionnaire.extension)
|
146
65
|
misformatted_expressions = []
|
147
66
|
questionnaire.extension.each_with_index do |extension, index|
|
148
67
|
if extension.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext'
|
@@ -165,13 +84,35 @@ module DaVinciDTRTestKit
|
|
165
84
|
end
|
166
85
|
next unless extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library'
|
167
86
|
|
168
|
-
cqf_count += 1
|
169
87
|
cqf_reference_libraries.add(extension.valueCanonical)
|
170
88
|
found_cqf_lib = true
|
171
89
|
extension_presence['found_min_cqf_lib'] = true
|
172
90
|
|
173
91
|
check_for_cql(extension, '', index, q_index, extension.url)
|
174
92
|
end
|
93
|
+
add_launch_context_messages(found_launch_context, found_variable, found_pop_context, found_cqf_lib, q_index)
|
94
|
+
return if cqf_count < 1
|
95
|
+
|
96
|
+
add_formatting_messages(misformatted_expressions, q_index)
|
97
|
+
assert misformatted_expressions.compact.empty?, 'Expression in questionnaire misformatted.'
|
98
|
+
end
|
99
|
+
|
100
|
+
def verify_questionnaire_items(questionnaires, final_cql_test: false)
|
101
|
+
assert questionnaires&.any? && questionnaires.all? { |q| q.is_a? FHIR::Questionnaire }, 'No questionnaires found.'
|
102
|
+
questionnaires.each_with_index { |q, q_index| check_questionnaire_items(q, q_index) }
|
103
|
+
|
104
|
+
begin
|
105
|
+
assert !found_non_cql_expression, 'Found non-cql expression.'
|
106
|
+
assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
|
107
|
+
assert cql_presence['init_expression'], 'Initial expression logic not written in CQL.'
|
108
|
+
assert cql_presence['candidate_expression'], 'Candidate expression logic not written in CQL.'
|
109
|
+
assert cql_presence['context_expression'], 'Context expression logic not written in CQL.'
|
110
|
+
ensure
|
111
|
+
reset_cql_tests if final_cql_test
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_launch_context_messages(found_launch_context, found_variable, found_pop_context, found_cqf_lib, q_index)
|
175
116
|
unless found_launch_context
|
176
117
|
messages << { type: 'info',
|
177
118
|
message: format_markdown("[questionnaire #{q_index + 1}] included no launch context.") }
|
@@ -186,19 +127,44 @@ module DaVinciDTRTestKit
|
|
186
127
|
message: format_markdown("[questionnaire #{q_index + 1}]
|
187
128
|
included no item population context.") }
|
188
129
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
130
|
+
return if found_cqf_lib
|
131
|
+
|
132
|
+
messages << { type: 'info',
|
133
|
+
message: format_markdown("[questionnaire #{q_index + 1}]
|
192
134
|
included no cqf library.") }
|
193
|
-
|
194
|
-
return if cqf_count < 1
|
135
|
+
end
|
195
136
|
|
137
|
+
def add_formatting_messages(misformatted_expressions, q_index)
|
196
138
|
misformatted_expressions.compact.each do |idx|
|
197
139
|
messages << { type: 'info',
|
198
140
|
message: format_markdown("[expression #{idx + 1}] in [questionnaire #{q_index + 1}]
|
199
141
|
does not begin with a reference to an included library name.") }
|
200
142
|
end
|
201
|
-
|
143
|
+
end
|
144
|
+
|
145
|
+
def total_cqf_libs(extensions)
|
146
|
+
cqf_count = 0
|
147
|
+
extensions.each do |extension|
|
148
|
+
next unless extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library'
|
149
|
+
|
150
|
+
cqf_count += 1
|
151
|
+
end
|
152
|
+
cqf_count
|
153
|
+
end
|
154
|
+
|
155
|
+
def add_item_messages(found_item_expressions, q_index)
|
156
|
+
unless found_item_expressions['found_candidate_expression']
|
157
|
+
messages << { type: 'info',
|
158
|
+
message: format_markdown("[questionnaire #{q_index + 1}] included no candidate expression.") }
|
159
|
+
end
|
160
|
+
unless found_item_expressions['found_init_expression']
|
161
|
+
messages << { type: 'info',
|
162
|
+
message: format_markdown("[questionnaire #{q_index + 1}] included no initial expression.") }
|
163
|
+
end
|
164
|
+
return if found_item_expressions['found_context_expression']
|
165
|
+
|
166
|
+
messages << { type: 'info',
|
167
|
+
message: format_markdown("[questionnaire #{q_index + 1}] included no context expression.") }
|
202
168
|
end
|
203
169
|
|
204
170
|
def check_questionnaire_items(questionnaire, q_index)
|
@@ -206,13 +172,9 @@ module DaVinciDTRTestKit
|
|
206
172
|
found_item_expressions = { 'found_init_expression' => false,
|
207
173
|
'found_candidate_expression' => false,
|
208
174
|
'found_context_expression' => false }
|
209
|
-
cqf_count =
|
175
|
+
cqf_count = total_cqf_libs(questionnaire.extension)
|
210
176
|
misformatted_expressions = []
|
211
|
-
questionnaire.extension.each do |extension|
|
212
|
-
next unless extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library'
|
213
177
|
|
214
|
-
cqf_count += 1
|
215
|
-
end
|
216
178
|
# check questionnaire items
|
217
179
|
questionnaire.item.each_with_index do |item, index|
|
218
180
|
misformatted_expressions.concat(check_nested_items(item, index, q_index, found_item_expressions, item.linkId))
|
@@ -222,18 +184,8 @@ module DaVinciDTRTestKit
|
|
222
184
|
index, q_index, found_item_expressions, item.linkId)
|
223
185
|
end
|
224
186
|
end
|
225
|
-
|
226
|
-
|
227
|
-
message: format_markdown("[questionnaire #{q_index + 1}] included no candidate expression.") }
|
228
|
-
end
|
229
|
-
unless found_item_expressions['found_init_expression']
|
230
|
-
messages << { type: 'info',
|
231
|
-
message: format_markdown("[questionnaire #{q_index + 1}] included no initial expression.") }
|
232
|
-
end
|
233
|
-
unless found_item_expressions['found_context_expression']
|
234
|
-
messages << { type: 'info',
|
235
|
-
message: format_markdown("[questionnaire #{q_index + 1}] included no context expression.") }
|
236
|
-
end
|
187
|
+
add_item_messages(found_item_expressions, q_index)
|
188
|
+
# only care about formatting when there are multiple cqf libs
|
237
189
|
return if cqf_count < 1
|
238
190
|
|
239
191
|
misformatted_expressions.compact.to_set.each do |idx|
|
@@ -244,51 +196,43 @@ module DaVinciDTRTestKit
|
|
244
196
|
assert misformatted_expressions.compact.to_set.empty?, 'Expression in questionnaire misformatted.'
|
245
197
|
end
|
246
198
|
|
247
|
-
def
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
found_cql = found_elm = false
|
263
|
-
library_urls.add(entry.resource.url) unless entry.resource.url.nil?
|
264
|
-
entry.resource.content.each do |content|
|
265
|
-
if content.data.nil?
|
266
|
-
messages << { type: 'info',
|
267
|
-
message: format_markdown("[library #{index + 1}] content element included no data.") }
|
268
|
-
end
|
269
|
-
if content.contentType == 'text/cql'
|
270
|
-
found_cql = true
|
271
|
-
elsif content.contentType == 'application/elm+json'
|
272
|
-
found_elm = true
|
273
|
-
else
|
274
|
-
messages << { type: 'info',
|
275
|
-
message: format_markdown("[library #{index + 1}] has non-cql/elm content.") }
|
276
|
-
true
|
277
|
-
end
|
278
|
-
next unless library_names.include? entry.resource.name
|
279
|
-
|
280
|
-
found_duplicate_library_name = true
|
281
|
-
messages << { type: 'info', message: format_markdown("[library #{index + 1}] has a name,
|
282
|
-
#{entry.resource.name}, that is already included in the bundle.") }
|
283
|
-
assert !found_duplicate_library_name, 'Found duplicate library names - all names must be unique.'
|
284
|
-
end
|
285
|
-
library_names.add(entry.resource.name)
|
286
|
-
assert found_cql, "[library #{index + 1}] does not include CQL."
|
287
|
-
assert found_elm, "[library #{index + 1}] does not include ELM."
|
199
|
+
def evaluate_library(library)
|
200
|
+
found_cql = found_elm = false
|
201
|
+
library.content.each do |content|
|
202
|
+
if content.data.nil?
|
203
|
+
messages << { type: 'info',
|
204
|
+
message: format_markdown("[library #{library.url}] content element included no data.") }
|
205
|
+
end
|
206
|
+
if content.contentType == 'text/cql'
|
207
|
+
found_cql = true
|
208
|
+
elsif content.contentType == 'application/elm+json'
|
209
|
+
found_elm = true
|
210
|
+
else
|
211
|
+
messages << { type: 'info',
|
212
|
+
message: format_markdown("[library #{library.url}] has non-cql/elm content.") }
|
213
|
+
true
|
288
214
|
end
|
289
|
-
|
215
|
+
next unless library_names.include? library.name
|
216
|
+
|
217
|
+
found_duplicate_library_name = true
|
218
|
+
messages << { type: 'info', message: format_markdown("[library #{library.url}] has a name,
|
219
|
+
#{library.name}, that is already included in the bundle.") }
|
220
|
+
assert !found_duplicate_library_name, 'Found duplicate library names - all names must be unique.'
|
221
|
+
end
|
222
|
+
assert found_cql, "[library #{library.url}] does not include CQL."
|
223
|
+
assert found_elm, "[library #{library.url}] does not include ELM."
|
224
|
+
end
|
225
|
+
|
226
|
+
def check_libraries(questionnaire_bundles)
|
227
|
+
libraries = extract_libraries_from_bundles(questionnaire_bundles)
|
228
|
+
|
229
|
+
assert libraries.any?, 'No Libraries found.'
|
230
|
+
|
231
|
+
libraries.each do |lib|
|
232
|
+
library_urls.add(lib.url) unless lib.url.nil?
|
233
|
+
evaluate_library(lib)
|
234
|
+
library_names.add(lib.name)
|
290
235
|
end
|
291
|
-
assert found_bundle, 'No questionnaire bundles found.'
|
292
236
|
end
|
293
237
|
|
294
238
|
def check_library_references
|
@@ -364,24 +308,22 @@ module DaVinciDTRTestKit
|
|
364
308
|
end
|
365
309
|
end
|
366
310
|
|
367
|
-
def
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
return fhir_resource
|
379
|
-
end
|
380
|
-
end
|
381
|
-
return questionnaire_responses
|
382
|
-
end
|
311
|
+
def extract_contained_questionnaires(questionnaire_responses)
|
312
|
+
questionnaire_responses&.filter_map do |qr|
|
313
|
+
qr.contained&.filter { |resource| resource.is_a?(FHIR::Questionnaire) }
|
314
|
+
end&.flatten&.compact
|
315
|
+
end
|
316
|
+
|
317
|
+
def extract_questionnaires_from_bundles(questionnaire_bundles)
|
318
|
+
questionnaire_bundles.filter_map do |qb|
|
319
|
+
qb.entry.filter_map { |entry| entry.resource if entry.resource.is_a?(FHIR::Questionnaire) }
|
320
|
+
end&.flatten&.compact
|
321
|
+
end
|
383
322
|
|
384
|
-
|
323
|
+
def extract_libraries_from_bundles(questionnaire_bundles)
|
324
|
+
questionnaire_bundles.filter_map do |qb|
|
325
|
+
qb.entry.filter_map { |entry| entry.resource if entry&.resource.is_a?(FHIR::Library) }
|
326
|
+
end&.flatten&.compact
|
385
327
|
end
|
386
328
|
end
|
387
329
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DaVinciDTRTestKit
|
2
|
+
module CreateTest
|
3
|
+
def perform_create_test(create_resources, resource_type)
|
4
|
+
skip_if(create_resources.blank?, "No `#{resource_type}` resources to create provided, skipping test.")
|
5
|
+
assert_valid_json(create_resources)
|
6
|
+
create_resources_list = JSON.parse(create_resources)
|
7
|
+
skip_if(!create_resources_list.is_a?(Array), 'Resources to create not inputted in list format, skipping test.')
|
8
|
+
|
9
|
+
valid_create_resources =
|
10
|
+
create_resources_list
|
11
|
+
.compact_blank
|
12
|
+
.map { |resource| FHIR.from_contents(resource.to_json) }
|
13
|
+
.select { |resource| resource.resourceType == resource_type }
|
14
|
+
.select { |resource| resource_is_valid?(resource:) }
|
15
|
+
|
16
|
+
skip_if(valid_create_resources.blank?,
|
17
|
+
%(No valid #{resource_type} resources were provided to send in Create requests, skipping test.))
|
18
|
+
|
19
|
+
valid_create_resources.each do |create_resource|
|
20
|
+
fhir_create(create_resource)
|
21
|
+
assert_response_status(201)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -13,32 +13,38 @@ requirements and may change the test validation logic.
|
|
13
13
|
## Test Methodology
|
14
14
|
|
15
15
|
Inferno will simulate a DTR payer server that will response to
|
16
|
-
requests for questionnaires for the EHR under test to interact with.
|
16
|
+
requests for questionnaires for the EHR under test to interact with.
|
17
17
|
The EHR will be expected to initiate requests to Inferno to elicit responses. Over the
|
18
|
-
course of these interactions, Inferno will seek to observe conformant handling of
|
18
|
+
course of these interactions, Inferno will seek to observe conformant handling of
|
19
19
|
DTR workflows and requirements around the retrieval, completion, and storage of
|
20
20
|
questionnaires.
|
21
21
|
|
22
22
|
Tests within this suite are associated with specific questionnaires that the EHR will
|
23
23
|
demonstrate completion of. In each case, the EHR under test will initiate a request to
|
24
|
-
the payer server simulated by Inferno for a questionnaire using the
|
24
|
+
the payer server simulated by Inferno for a questionnaire using the
|
25
25
|
`$questionnaire-package` operation. Inferno will always return the specific questionnaire
|
26
|
-
for the test being executed regardless of the input provided by the EHR, though
|
27
|
-
|
28
|
-
|
26
|
+
for the test being executed regardless of the input provided by the EHR, though Inferno will
|
27
|
+
check that the input is conformant. The EHR will then be asked to complete the questionnaire,
|
28
|
+
including:
|
29
|
+
|
30
|
+
- Pre-populating answers based on directives in the questionnaire.
|
29
31
|
- Rendering the questionnaire for users and allowing them to make additional updates.
|
30
32
|
These tests can include specific directions on details to include in the completed
|
31
33
|
questionnaire.
|
34
|
+
- For adaptive questionnaires only, getting additional questions using the `$next-question`
|
35
|
+
operation until the questionnaire is complete.
|
32
36
|
- Storing the completed questionnaire for future use as a FHIR QuestionnaireResponse.
|
33
37
|
|
34
38
|
EHRs will be required to complete all questionnaires in the suite, which in aggregate
|
35
39
|
contain all questionnaire features that apps must support. Currently, the suite includes
|
36
40
|
one questionnaire:
|
37
|
-
1. A fictious "dinner" questionnaire created for these tests. It tests basic
|
38
|
-
item rendering and pre-population.
|
39
|
-
Additional questionnaires will be added in the future.
|
40
41
|
|
41
|
-
|
42
|
+
1. Standard and adaptive styles of a fictitious "dinner" questionnaire created for these tests.
|
43
|
+
They test basic item rendering, control flow, and pre-population.
|
44
|
+
|
45
|
+
Additional questionnaires covering further features will be added in the future.
|
46
|
+
|
47
|
+
All requests sent by the app will be checked
|
42
48
|
for conformance to the DTR IG requirements individually and used in aggregate to determine
|
43
49
|
whether required features and functionality are present. HL7® FHIR® resources are
|
44
50
|
validated with the Java validator using `tx.fhir.org` as the terminology server.
|
@@ -49,28 +55,28 @@ validated with the Java validator using `tx.fhir.org` as the terminology server.
|
|
49
55
|
|
50
56
|
In order to run these tests, EHRs must be configured to interact with Inferno's simulated
|
51
57
|
payer server endpoint. The endpoint will be `[URL prefix]/custom/dtr_full_ehr/fhir` where
|
52
|
-
`[URL prefix]` can be inferred from the URL of the test session which will be of the form
|
58
|
+
`[URL prefix]` can be inferred from the URL of the test session which will be of the form
|
53
59
|
`[URL prefix]/dtr_full_ehr/[session id]`.
|
54
60
|
|
55
61
|
In order for Inferno to associate requests sent to locations under these base URLs with this session,
|
56
|
-
it needs to know the bearer token that the EHR will send on requests, for which
|
62
|
+
it needs to know the bearer token that the EHR will send on requests, for which
|
57
63
|
there are two options.
|
58
64
|
|
59
65
|
1. If you want to choose your own bearer token, then
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
1. Select the "2. Basic Workflows" test from the list on the left (or other target test).
|
67
|
+
2. Click the '_Run All Tests_' button on the right.
|
68
|
+
3. In the "access_token" field, enter the bearer token that will be sent by the client
|
69
|
+
under test (as part of the Authorization header - `Bearer <provided value>`).
|
70
|
+
4. Click the '_Submit_' button at the bottom of the dialog.
|
65
71
|
2. If you want to use a client_id to obtain an access token, then
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
1. Click the '_Run All Tests_' button on the right.
|
73
|
+
2. Provide the EHR's registered id "client_id" field of the input (NOTE, Inferno
|
74
|
+
doesn't support the registration API, so this must be obtained from another
|
75
|
+
system or configured manually).
|
76
|
+
3. Click the '_Submit_' button at the bottom of the dialog.
|
77
|
+
4. Make a token request that includes the specified client id to the
|
78
|
+
`[URL prefix]/custom/dtr_full_ehr/mock_auth/token` endpoint to get
|
79
|
+
an access token to use on the request of the requests.
|
74
80
|
|
75
81
|
In either case, the tests will continue from that point. Further executions of tests under
|
76
82
|
this session will also use the selected bearer token.
|
@@ -85,21 +91,30 @@ to make requests against Inferno. This does not include the capability to render
|
|
85
91
|
questionnaires, but does have samples of correctly and incorrectly completed QuestionnaireResponses.
|
86
92
|
To run the tests using this approach:
|
87
93
|
|
94
|
+
#### Setup
|
88
95
|
1. Install [postman](https://www.postman.com/downloads/).
|
89
96
|
1. Import [this Postman collection](https://github.com/inferno-framework/davinci-dtr-test-kit/blob/main/config/DTR%20Full%20EHR%20Tests%20Postman%20Demo.postman_collection.json).
|
97
|
+
|
98
|
+
#### Startup
|
90
99
|
1. Start a Da Vinci DTR Full EHR Test Suite Session.
|
91
100
|
1. Update the postman collection configuration variables found by opening the "DTR Full EHR
|
92
101
|
Tests Postman Demo" collection and selecting the "Variables" tab.
|
93
|
-
- **base_url**: corresponds to the where the test suite session is running. Defaults to
|
94
|
-
|
95
|
-
|
102
|
+
- **base_url**: corresponds to the where the test suite session is running. Defaults to
|
103
|
+
`inferno.healthit.gov`. If running in another location, see guidance on the "Overview" tab
|
104
|
+
of the postman collection.
|
96
105
|
- **access_token**: note the "Current value" (update if desired) for use later.
|
97
|
-
|
106
|
+
|
107
|
+
#### Dinner Questionnaire (Standard)
|
108
|
+
|
109
|
+
For the standard (static) questionnaire demo, use the requests in the _Static Dinner_ folder in the
|
110
|
+
Postman collection.
|
111
|
+
|
112
|
+
1. Return to the Inferno test session and in the test list at the left, select _2 Static Questionnaire Workflow_.
|
98
113
|
1. Click the "Run All Tests" button in the upper right.
|
99
114
|
1. Add the **access_token** configured in postman to the Inferno input with the same name
|
100
115
|
1. Click the "Submit" button in Inferno.
|
101
116
|
1. Attest that the EHR has launched its DTR workflow in Inferno by clicking the link for the **true** response.
|
102
|
-
1. Once the next wait dialog has appeared within Inferno asking for a `$questionnaire-package`
|
117
|
+
1. Once the next wait dialog has appeared within Inferno asking for a `$questionnaire-package`
|
103
118
|
request, use postman to submit the "Questionnaire Package for Dinner (Static)" request. Confirm
|
104
119
|
that the response that looks similar to the "Example Working Response" in postman
|
105
120
|
and click the link to continue the tests.
|
@@ -107,21 +122,64 @@ To run the tests using this approach:
|
|
107
122
|
with an actual EHR implementation. To see what a valid QuestionnaireResponse looks like, see
|
108
123
|
the "Sample QuestionnaireResponse for Dinner (Static) ..." request in postman.
|
109
124
|
|
125
|
+
#### Dinner Questionnaire (Adaptive)
|
126
|
+
|
127
|
+
For the adaptive questionnaire demo, use the requests in the _Adaptive Dinner_ folder in the
|
128
|
+
Postman collection.
|
129
|
+
|
130
|
+
1. Return to the Inferno test session and in the test list at the left, select _3 Adaptive Questionnaire Workflow_.
|
131
|
+
1. Click the "Run All Tests" button in the upper right.
|
132
|
+
1. Add the **access_token** configured in postman to the Inferno input with the same name (if not already present)
|
133
|
+
1. Click the "Submit" button in Inferno.
|
134
|
+
1. Attest that the EHR has launched its DTR workflow in Inferno by clicking the link for the **true** response.
|
135
|
+
1. Once the **Adaptive Questionnaire Retrieval** wait dialog has appeared within Inferno asking
|
136
|
+
for `$questionnaire-package` and `$next-question`
|
137
|
+
requests, use postman to submit the "Questionnaire Package for Dinner" request followed by the
|
138
|
+
"Initial Next Question" request. Confirm
|
139
|
+
that the response that looks similar to the "Example Response" in postman
|
140
|
+
and click the link to continue the tests.
|
141
|
+
1. Attest to the next several attestation wait dialogs as desired to get a sense for what is involved
|
142
|
+
in testing with an actual EHR implementation.
|
143
|
+
1. Once the **Follow-up Next Question Request** wait dialog has appeared within Inferno asking for
|
144
|
+
another `$next-question` request, use postman to submit the "Second Next Question" request. Confirm
|
145
|
+
that the response that looks similar to the "Example Response" in postman
|
146
|
+
and click the link to continue the tests.
|
147
|
+
1. Once the **Last Next Question Request** wait dialog has appeared within Inferno asking for
|
148
|
+
another `$next-question` request, use postman to submit the "Final Next Question" request. Confirm
|
149
|
+
that the response that looks similar to the "Example Response" in postman
|
150
|
+
and click the link to continue the tests.
|
151
|
+
|
110
152
|
## Limitations
|
111
153
|
|
112
154
|
The DTR IG is a complex specification and these tests currently validate conformance to only
|
113
155
|
a subset of IG requirements. Future versions of the test suite will test further
|
114
156
|
features. A few specific features of interest are listed below.
|
115
157
|
|
116
|
-
###
|
158
|
+
### Questionnaire Response Verification
|
159
|
+
|
160
|
+
Currently, these test kits do not have enough information about the data stored on
|
161
|
+
the EHR to evaluate whether CQL evaluation populated data correctly. However, Inferno
|
162
|
+
does ask testers to make sure that the target patient meets certain requirements and
|
163
|
+
directs them to perform certain actions while filling out forms that allow Inferno to
|
164
|
+
check that calculation is occuring and that the system is correctly keeping track of
|
165
|
+
items that were pre-populated. This approach may change in future versions of these tests.
|
166
|
+
|
167
|
+
### Questionnaire Response Access
|
168
|
+
|
169
|
+
For standard (static) questionnaires, Full EHRs are not required by the DTR specification
|
170
|
+
to store or expose the completed form as a FHIR QuestionnaireResponse instance, though they
|
171
|
+
are required to store the form in some way and be able to send the QuestionnaireResponse
|
172
|
+
representation to other systems. Currently, testers are required to provide a
|
173
|
+
QuestionnaireResponse as an input to the tests once they have completed their workflow.
|
174
|
+
Future versions of these tests will provide additional options for making that information
|
175
|
+
available that are more in-line with expected system capabilities.
|
117
176
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
mechanical check. Some level of mechanical checks are expected to be added in the future.
|
177
|
+
For adaptive questionnaires, the completed QuestionnaireResponse will be present in the
|
178
|
+
last `$next-question` invocation by the EHR, so this limitation does not apply to those
|
179
|
+
cases.
|
122
180
|
|
123
181
|
### Questionnaire Feature Coverage
|
124
182
|
|
125
183
|
Not all questionnaire features that are must support within the DTR IG are currently represented
|
126
|
-
in questionnaires tested by the IG.
|
127
|
-
|
184
|
+
in questionnaires tested by the IG. Additional questionnaires testing additional features will
|
185
|
+
be added in the future.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
The Da Vinci DTR Test Kit Light EHR Suite validates the conformance of SMART apps
|
2
|
+
to the STU 2 version of the HL7® FHIR®
|
3
|
+
[Da Vinci Documentation Templates and Rules (DTR) Implementation Guide](https://hl7.org/fhir/us/davinci-dtr/STU2/).
|
4
|
+
|
5
|
+
## Scope
|
6
|
+
|
7
|
+
These tests are a **DRAFT** intended to allow app implementers to perform
|
8
|
+
preliminary checks of their systems against DTR IG requirements and [provide
|
9
|
+
feedback](https://github.com/inferno-framework/davinci-dtr-test-kit/issues)
|
10
|
+
on the tests. Future versions of these tests may validate other
|
11
|
+
requirements and may change the test validation logic.
|
12
|
+
|
13
|
+
## Test Methodology
|
14
|
+
|
15
|
+
Inferno will simulate a DTR SMART App that will connect to the DTR Light EHR system under test. The tester will need to launch Inferno using either an EHR launch or a Standalone launch. Once the connection between Inferno's simulated DTR SMART App and the DTR Light EHR under test is established, tests within this suite will make FHIR API requests corresponding to capabilities required by the [Light DTR EHR Capability Statement](https://hl7.org/fhir/us/davinci-dtr/STU2/CapabilityStatement-light-dtr-ehr) and check that the EHR's responses are conformant.
|
16
|
+
|
17
|
+
## Running the Tests
|
18
|
+
|
19
|
+
If you would like to try out the tests but don't have a DTR Light EHR implementation, you can run these tests against the [public instance of the Inferno Reference Server](https://inferno.healthit.gov/reference-server/r4/) by using the Inferno Reference Server preset in the test suite. In order to get the Inferno Reference Server to do an EHR launch, navigate to https://inferno.healthit.gov/reference-server/app/app-launch and use https://inferno.healthit.gov/suites/custom/smart/launch as the App Launch URL. When using the Inferno Reference Server preset for the DTR Light EHR test suite, note that the sample patient used for testing (`dtr_bundle_patient_pat015.json`) is focused on DTR-specific data and does not have the complete set of US Core data needed to pass all the US Core tests. In addition, this preset does not test the `create` or `update` tests for DTR QuestionnaireResponse resources and PAS Task resources.
|
20
|
+
|
21
|
+
## Limitations
|
22
|
+
|
23
|
+
The DTR IG is a complex specification and these tests currently validate conformance to only
|
24
|
+
a subset of IG requirements. Future versions of the test suite will test further
|
25
|
+
features.
|
26
|
+
|
27
|
+
## DTR 2.0.1 Corrections
|
28
|
+
|
29
|
+
The DTR 2.0.1 version of the [Light EHR CapabilityStatement](http://hl7.org/fhir/us/davinci-dtr/CapabilityStatement/light-dtr-ehr) includes two pieces of missing or misleading information that have been corrected:
|
30
|
+
|
31
|
+
- The 2.0.1 CapabilityStatement indicates that support for the [Coverage resource type](https://hl7.org/fhir/us/davinci-dtr/STU2/CapabilityStatement-light-dtr-ehr.html#coverage) is required when the [QuestionnaireResponse resource type was intended](https://build.fhir.org/ig/HL7/davinci-dtr/CapabilityStatement-light-dtr-ehr-311.html#questionnaireresponse) (note specifically that the `context` search parameters are not present on the Coverage resource type but is on the QuestionnaireResponse resource type).
|
32
|
+
- The 2.0.1 CapabilityStatement does not indicate a target profile for the [Task resource type](https://hl7.org/fhir/us/davinci-dtr/STU2/CapabilityStatement-light-dtr-ehr.html#task) but the current version [clarifies](https://build.fhir.org/ig/HL7/davinci-dtr/CapabilityStatement-light-dtr-ehr-311.html#task) that the [PAS Task Profile](http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-task) is intended.
|
33
|
+
|
34
|
+
This test suite verifies systems according to these corrections. Additionally, it verifies the `read` interaction for the Coverage resource type.
|