davinci_dtr_test_kit 0.13.0 → 0.14.1
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 -38
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb +13 -16
- 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/{dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_conformance_test.rb → full_ehr/dtr_full_ehr_questionnaire_response_conformance_test.rb} +7 -3
- data/lib/davinci_dtr_test_kit/client_groups/{dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_correctness_test.rb → full_ehr/dtr_full_ehr_questionnaire_response_correctness_test.rb} +14 -7
- 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 +5 -1
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +12 -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 +37 -140
- 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 +15 -6
- 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 +67 -2
- data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +9 -20
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +18 -10
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +32 -59
- 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/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 +24 -1
- 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 +6 -6
- 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_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 -23
- 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_response_validation_test.rb +32 -25
- 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 -7
- data/lib/davinci_dtr_test_kit/update_test.rb +25 -0
- data/lib/davinci_dtr_test_kit/validation_test.rb +19 -4
- data/lib/davinci_dtr_test_kit/version.rb +1 -1
- metadata +110 -21
- 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 -228
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +0 -105
- data/lib/davinci_dtr_test_kit/mock_payer.rb +0 -100
@@ -10,6 +10,7 @@ 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
|
+
config options: { accepts_multiple_requests: true }
|
13
14
|
input :smart_app_launch,
|
14
15
|
type: 'radio',
|
15
16
|
title: 'SMART App Launch',
|
@@ -20,38 +21,34 @@ module DaVinciDTRTestKit
|
|
20
21
|
input :launch_uri,
|
21
22
|
optional: true,
|
22
23
|
description: 'Required if "Launch from Inferno" is selected'
|
23
|
-
input :
|
24
|
+
input :resp_smart_patient_id,
|
24
25
|
optional: true,
|
25
26
|
title: 'SMART App Launch Patient ID (Respiratory Assist Device)',
|
26
27
|
type: 'text',
|
27
28
|
description: %(
|
28
|
-
Patient instance
|
29
|
-
Launch.
|
29
|
+
Patient instance ID to be provided by Inferno as the patient as a part of the SMART App Launch.
|
30
30
|
),
|
31
31
|
default: 'pat015'
|
32
|
-
input :
|
32
|
+
input :resp_smart_fhir_context,
|
33
33
|
optional: true,
|
34
34
|
title: 'SMART App Launch fhirContext (Respiratory Assist Device)',
|
35
35
|
type: 'textarea',
|
36
36
|
description: %(
|
37
|
-
References to be provided by Inferno as the
|
37
|
+
References to be provided by Inferno as the fhirContext as a part of the SMART App
|
38
38
|
Launch. These references help determine the behavior of the app. Referenced instances
|
39
39
|
may be provided in the "EHR-available resources" input.
|
40
40
|
),
|
41
41
|
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
|
42
42
|
{ reference: 'DeviceRequest/devreqe0470' }])
|
43
|
-
input :
|
43
|
+
input :resp_ehr_bundle,
|
44
44
|
optional: true,
|
45
45
|
title: 'EHR-available resources (Respiratory Assist Device)',
|
46
46
|
type: 'textarea',
|
47
47
|
description: %(
|
48
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
|
50
|
-
instance present will be available for retrieval from Inferno at the endpoint
|
51
|
-
|
52
|
-
```
|
53
|
-
[fhir-base]/[resource type]/[instance id]
|
54
|
-
```
|
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
|
+
<fhir-base>/<resource type>/<instance id>
|
55
52
|
)
|
56
53
|
|
57
54
|
def example_client_jwt_payload_part
|
@@ -61,19 +58,19 @@ module DaVinciDTRTestKit
|
|
61
58
|
run do
|
62
59
|
# validate relevant inputs and provide warnings if they are bad
|
63
60
|
warning do
|
64
|
-
if
|
65
|
-
assert_valid_json(
|
61
|
+
if resp_smart_fhir_context
|
62
|
+
assert_valid_json(resp_smart_fhir_context,
|
66
63
|
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
|
67
64
|
the access token response.')
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
71
68
|
warning do
|
72
|
-
if
|
73
|
-
assert_valid_json(
|
69
|
+
if resp_ehr_bundle
|
70
|
+
assert_valid_json(resp_ehr_bundle,
|
74
71
|
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
|
75
72
|
will be available to access from Inferno.')
|
76
|
-
assert(FHIR.from_contents(
|
73
|
+
assert(FHIR.from_contents(resp_ehr_bundle).is_a?(FHIR::Bundle),
|
77
74
|
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
|
78
75
|
will be available to access from Inferno.')
|
79
76
|
end
|
@@ -117,7 +114,7 @@ module DaVinciDTRTestKit
|
|
117
114
|
an `Authorization` header with value:
|
118
115
|
|
119
116
|
```
|
120
|
-
Bearer
|
117
|
+
Bearer eyJhbGciOiJub25lIn0.#{example_client_jwt_payload_part}.
|
121
118
|
```
|
122
119
|
|
123
120
|
### Continuing the Tests
|
@@ -14,11 +14,15 @@ module DaVinciDTRTestKit
|
|
14
14
|
to the DTR Questionnaire Response resource profile.
|
15
15
|
)
|
16
16
|
|
17
|
+
def profile_url
|
18
|
+
config.options[:qr_profile_url]
|
19
|
+
end
|
20
|
+
|
17
21
|
run do
|
18
22
|
assert request.url == questionnaire_response_url,
|
19
23
|
"Request made to wrong URL: #{request.url}. Should instead be to #{questionnaire_response_url}"
|
20
24
|
|
21
|
-
verify_basic_conformance(request.request_body)
|
25
|
+
verify_basic_conformance(request.request_body, profile_url)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require_relative '../../dtr_questionnaire_response_validation'
|
4
2
|
require_relative '../../fixtures'
|
5
3
|
|
@@ -27,9 +25,18 @@ module DaVinciDTRTestKit
|
|
27
25
|
questionnaire_response_json = request.request_body
|
28
26
|
check_is_questionnaire_response(questionnaire_response_json)
|
29
27
|
questionnaire_response = FHIR.from_contents(questionnaire_response_json)
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
if config.options[:adaptive]
|
29
|
+
questionnaire = questionnaire_response.contained.find { |res| res.resourceType == 'Questionnaire' }
|
30
|
+
assert questionnaire, 'Adaptive QuestionnaireResponse must have a contained Questionnaire resource.'
|
31
|
+
check_origin_sources(questionnaire.item, questionnaire_response.item, expected_overrides: ['PBD.2'])
|
32
|
+
required_link_ids = extract_required_link_ids(questionnaire.item)
|
33
|
+
check_answer_presence(questionnaire_response.item, required_link_ids)
|
34
|
+
assert(messages.none? { |m| m[:type] == 'error' }, 'QuestionnaireResponse is not correct, see error message(s)')
|
35
|
+
else
|
36
|
+
questionnaire = Fixtures.questionnaire_for_test(id)
|
37
|
+
response_template = Fixtures.questionnaire_response_for_test(id)
|
38
|
+
validate_questionnaire_pre_population(questionnaire, response_template, questionnaire_response)
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
35
42
|
end
|
@@ -1,27 +1,27 @@
|
|
1
|
+
require 'securerandom'
|
1
2
|
require_relative '../../urls'
|
2
3
|
|
3
4
|
module DaVinciDTRTestKit
|
4
|
-
class
|
5
|
+
class DTRSmartAppPrepopulationAttestationTest < Inferno::Test
|
5
6
|
include URLs
|
6
7
|
|
7
|
-
id :
|
8
|
+
id :dtr_smart_app_prepopulation_attestation
|
8
9
|
title 'Check that the client pre-populates the questionnaire (Attestation)'
|
9
10
|
description %(
|
10
11
|
Validate that pre-population of patient name information occurs as expected.
|
11
12
|
)
|
12
|
-
input :client_id
|
13
|
-
|
14
13
|
run do
|
14
|
+
random_id = SecureRandom.uuid
|
15
15
|
wait(
|
16
|
-
identifier:
|
16
|
+
identifier: random_id,
|
17
17
|
message: %(
|
18
18
|
I attest that the client application pre-populates the following questions with the respective values:
|
19
19
|
- Last Name: Oster
|
20
20
|
- First Name: William
|
21
21
|
|
22
|
-
[Click here](#{resume_pass_url}?client_id=#{
|
22
|
+
[Click here](#{resume_pass_url}?client_id=#{random_id}) if the above statement is **true**.
|
23
23
|
|
24
|
-
[Click here](#{resume_fail_url}?client_id=#{
|
24
|
+
[Click here](#{resume_fail_url}?client_id=#{random_id}) if the above statement is **false**.
|
25
25
|
)
|
26
26
|
)
|
27
27
|
end
|
@@ -1,28 +1,29 @@
|
|
1
|
+
require 'securerandom'
|
1
2
|
require_relative '../../urls'
|
2
3
|
|
3
4
|
module DaVinciDTRTestKit
|
4
|
-
class
|
5
|
+
class DTRSmartAppPrepopulationOverrideAttestationTest < Inferno::Test
|
5
6
|
include URLs
|
6
7
|
|
7
|
-
id :
|
8
|
+
id :dtr_smart_app_prepopulation_override_attestation
|
8
9
|
title 'Validate the user can override pre-populated data (Attestation)'
|
9
10
|
description %(
|
10
11
|
Validate that the user can edit a pre-populated item and replace it with another value.
|
11
12
|
)
|
12
|
-
input :client_id
|
13
13
|
|
14
14
|
run do
|
15
|
+
random_id = SecureRandom.uuid
|
15
16
|
wait(
|
16
|
-
identifier:
|
17
|
+
identifier: random_id,
|
17
18
|
message: %(
|
18
19
|
I attest that
|
19
20
|
|
20
21
|
1. The client pre-populated an answer for question 'Location'.
|
21
22
|
2. I have changed the answer to a different value.
|
22
23
|
|
23
|
-
[Click here](#{resume_pass_url}?client_id=#{
|
24
|
+
[Click here](#{resume_pass_url}?client_id=#{random_id}) if the above statement is **true**.
|
24
25
|
|
25
|
-
[Click here](#{resume_fail_url}?client_id=#{
|
26
|
+
[Click here](#{resume_fail_url}?client_id=#{random_id}) if the above statement is **false**.
|
26
27
|
)
|
27
28
|
)
|
28
29
|
end
|
@@ -1,30 +1,40 @@
|
|
1
1
|
require_relative '../../urls'
|
2
2
|
|
3
3
|
module DaVinciDTRTestKit
|
4
|
-
class
|
4
|
+
class DTRSmartAppQuestionnaireResponseSaveTest < Inferno::Test
|
5
5
|
include URLs
|
6
6
|
|
7
|
-
id :
|
7
|
+
id :dtr_smart_app_questionnaire_response_save
|
8
8
|
title 'Save the QuestionnaireResponse after completing it'
|
9
9
|
description %(
|
10
10
|
Inferno, acting as the EHR, will wait for a request to save the QuestionnaireResponse from the client.
|
11
11
|
)
|
12
12
|
input :client_id
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def prompt
|
15
|
+
if config.options[:adaptive]
|
16
|
+
'Store the completed questionnaire back into the EHR.'
|
17
|
+
else
|
18
|
+
<<~DESCRIPTION
|
18
19
|
Complete the questionnaire, leaving the following items unmodified, because a subsequent test will expect
|
19
20
|
their pre-populated values:
|
20
21
|
|
21
22
|
- First Name
|
22
23
|
- Last Name
|
24
|
+
DESCRIPTION
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
run do
|
29
|
+
wait(
|
30
|
+
identifier: client_id,
|
31
|
+
message: <<~MESSAGE
|
32
|
+
#{prompt}
|
23
33
|
|
24
34
|
Inferno will wait for a POST request at:
|
25
35
|
|
26
36
|
`#{questionnaire_response_url}`
|
27
|
-
|
37
|
+
MESSAGE
|
28
38
|
)
|
29
39
|
end
|
30
40
|
end
|
@@ -1,28 +1,28 @@
|
|
1
|
+
require 'securerandom'
|
1
2
|
require_relative '../../urls'
|
2
3
|
|
3
4
|
module DaVinciDTRTestKit
|
4
|
-
class
|
5
|
+
class DTRSmartAppRenderingEnabledQuestionsAttestationTest < Inferno::Test
|
5
6
|
include URLs
|
6
7
|
|
7
|
-
id :
|
8
|
+
id :dtr_smart_app_rendering_enabled_questions_attestation
|
8
9
|
title 'Check that the client renders enabled questions appropriately (Attestation)'
|
9
10
|
description %(
|
10
11
|
Validate that the rendering of the questionnaire includes only the "What would you like on..."
|
11
12
|
question appropriate for the dinner selection, if made.
|
12
13
|
)
|
13
|
-
input :client_id
|
14
|
-
|
15
14
|
run do
|
15
|
+
random_id = SecureRandom.uuid
|
16
16
|
wait(
|
17
|
-
identifier:
|
17
|
+
identifier: random_id,
|
18
18
|
message: %(
|
19
19
|
I attest that the client application does not display any "What would you like on..."
|
20
20
|
questions until I have selected a dinner choice and then only displays the
|
21
21
|
"What would you like on..." question relevant for the dinner request:
|
22
22
|
|
23
|
-
[Click here](#{resume_pass_url}?client_id=#{
|
23
|
+
[Click here](#{resume_pass_url}?client_id=#{random_id}) if the above statement is **true**.
|
24
24
|
|
25
|
-
[Click here](#{resume_fail_url}?client_id=#{
|
25
|
+
[Click here](#{resume_fail_url}?client_id=#{random_id}) if the above statement is **false**.
|
26
26
|
)
|
27
27
|
)
|
28
28
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'dtr_smart_app_questionnaire_response_save_test'
|
2
|
+
require_relative '../shared/dtr_questionnaire_response_basic_conformance_test'
|
3
|
+
require_relative '../shared/dtr_questionnaire_response_pre_population_test'
|
4
|
+
|
5
|
+
module DaVinciDTRTestKit
|
6
|
+
class DTRSmartAppSavingQuestionnaireResponseGroup < Inferno::TestGroup
|
7
|
+
id :dtr_smart_app_saving_questionnaire_response
|
8
|
+
title 'Saving the QuestionnaireResponse'
|
9
|
+
description %(
|
10
|
+
The tester will complete the questionnaire such that a QuestionnaireResponse is stored
|
11
|
+
back into Inferno's EHR endpoint. The stored QuestionnaireResponse will be evaluated for
|
12
|
+
conformance, completeness, and correct indicators on pre-populated and manually-overriden
|
13
|
+
items.
|
14
|
+
)
|
15
|
+
run_as_group
|
16
|
+
|
17
|
+
# Test 1: wait for a QuestionnaireResponse
|
18
|
+
test from: :dtr_smart_app_questionnaire_response_save,
|
19
|
+
receives_request: :questionnaire_response_save
|
20
|
+
# Test 2: validate basic conformance of the QuestionnaireResponse
|
21
|
+
test from: :dtr_questionnaire_response_basic_conformance,
|
22
|
+
uses_request: :questionnaire_response_save
|
23
|
+
# Test 3: validate workflow-specific details such as pre-population and overrides
|
24
|
+
test from: :dtr_questionnaire_response_pre_population,
|
25
|
+
uses_request: :questionnaire_response_save
|
26
|
+
end
|
27
|
+
end
|
@@ -48,53 +48,10 @@ module DaVinciDTRTestKit
|
|
48
48
|
extension_presence.each_key { |k| extension_presence[k] = false }
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
next unless individual_resource.resourceType == 'QuestionnaireResponse'
|
55
|
-
|
56
|
-
individual_resource.contained.each_with_index do |questionnaire, q_index|
|
57
|
-
# Do out put parameters have a bundle?
|
58
|
-
next unless questionnaire.resourceType == 'Questionnaire'
|
59
|
-
|
60
|
-
# check the libraries first so references in questionnaires can be checked after
|
61
|
-
found_questionnaire = true
|
62
|
-
check_questionnaire_extensions(questionnaire, q_index)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
found_questionnaire
|
66
|
-
end
|
67
|
-
|
68
|
-
def evaluate_parameters_extensions(resource)
|
69
|
-
found_questionnaire = false
|
70
|
-
resource.parameter.each do |param|
|
71
|
-
# Do out put parameters have a bundle?
|
72
|
-
next unless param.resource.resourceType == 'Bundle'
|
73
|
-
|
74
|
-
param.resource.entry.each_with_index do |entry, q_index|
|
75
|
-
# check questionnaire extensions
|
76
|
-
next unless entry.resource.resourceType == 'Questionnaire'
|
77
|
-
|
78
|
-
found_questionnaire = true
|
79
|
-
check_questionnaire_extensions(entry.resource, q_index)
|
80
|
-
## NEED TO FIGURE OUT HOW TO FAIL TEST WHEN POORLY FORMATTED EXPRESSIONS FOUND
|
81
|
-
end
|
82
|
-
end
|
83
|
-
found_questionnaire
|
84
|
-
end
|
85
|
-
|
86
|
-
# extensions
|
87
|
-
def questionnaire_extensions_test(response)
|
88
|
-
resource = process_response(response)
|
89
|
-
assert !resource.nil?, 'Response is null or not a valid type.'
|
90
|
-
found_questionnaire = false
|
91
|
-
if resource.instance_of? Array
|
92
|
-
found_questionnaire = evaluate_responses_extensions(resource)
|
93
|
-
elsif resource.resourceType == 'Parameters'
|
94
|
-
found_questionnaire = evaluate_parameters_extensions(resource)
|
95
|
-
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) }
|
96
54
|
check_library_references
|
97
|
-
assert found_questionnaire, 'No questionnaires found.'
|
98
55
|
assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
|
99
56
|
assert cql_presence['variable'], 'Variable expression logic not written in CQL.'
|
100
57
|
assert cql_presence['launch_context'], 'Launch context expression logic not written in CQL.'
|
@@ -140,53 +97,11 @@ module DaVinciDTRTestKit
|
|
140
97
|
assert misformatted_expressions.compact.empty?, 'Expression in questionnaire misformatted.'
|
141
98
|
end
|
142
99
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
resource.each_with_index do |individual_resource, q_index|
|
147
|
-
next unless individual_resource.resourceType == 'QuestionnaireResponse'
|
148
|
-
|
149
|
-
individual_resource.contained.each do |questionnaire|
|
150
|
-
next unless questionnaire.resourceType == 'Questionnaire'
|
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) }
|
151
103
|
|
152
|
-
# check the libraries first so references in questionnaires can be checked after
|
153
|
-
found_questionnaire = true
|
154
|
-
check_questionnaire_items(questionnaire, q_index)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
found_questionnaire
|
158
|
-
end
|
159
|
-
|
160
|
-
def evaluate_parameters_items(resource)
|
161
|
-
found_bundle = found_questionnaire = false
|
162
|
-
resource.parameter.each do |param|
|
163
|
-
next unless param.resource.resourceType == 'Bundle'
|
164
|
-
|
165
|
-
found_bundle = true
|
166
|
-
# check the libraries first so references in questionnaires can be checked after
|
167
|
-
param.resource.entry.each_with_index do |entry, q_index|
|
168
|
-
if entry.resource.resourceType == 'Questionnaire'
|
169
|
-
found_questionnaire = true
|
170
|
-
check_questionnaire_items(entry.resource, q_index)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
[found_bundle, found_questionnaire]
|
175
|
-
end
|
176
|
-
|
177
|
-
def questionnaire_items_test(response, final_cql_test)
|
178
|
-
resource = process_response(response)
|
179
|
-
assert !resource.nil?, 'Response is null or not a valid type.'
|
180
|
-
found_questionnaire = false
|
181
|
-
# are extensions present in any questionnaire?
|
182
|
-
if resource.instance_of? Array
|
183
|
-
found_questionnaire = evaluate_responses_items(resource)
|
184
|
-
elsif resource.resourceType == 'Parameters'
|
185
|
-
found_bundle, found_questionnaire = evaluate_parameters_items(resource)
|
186
|
-
assert found_bundle, 'No questionnaire bundles found.'
|
187
|
-
end
|
188
104
|
begin
|
189
|
-
assert found_questionnaire, 'No questionnaires found.'
|
190
105
|
assert !found_non_cql_expression, 'Found non-cql expression.'
|
191
106
|
assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
|
192
107
|
assert cql_presence['init_expression'], 'Initial expression logic not written in CQL.'
|
@@ -281,12 +196,12 @@ module DaVinciDTRTestKit
|
|
281
196
|
assert misformatted_expressions.compact.to_set.empty?, 'Expression in questionnaire misformatted.'
|
282
197
|
end
|
283
198
|
|
284
|
-
def evaluate_library(
|
199
|
+
def evaluate_library(library)
|
285
200
|
found_cql = found_elm = false
|
286
|
-
|
201
|
+
library.content.each do |content|
|
287
202
|
if content.data.nil?
|
288
203
|
messages << { type: 'info',
|
289
|
-
message: format_markdown("[library #{
|
204
|
+
message: format_markdown("[library #{library.url}] content element included no data.") }
|
290
205
|
end
|
291
206
|
if content.contentType == 'text/cql'
|
292
207
|
found_cql = true
|
@@ -294,42 +209,30 @@ module DaVinciDTRTestKit
|
|
294
209
|
found_elm = true
|
295
210
|
else
|
296
211
|
messages << { type: 'info',
|
297
|
-
message: format_markdown("[library #{
|
212
|
+
message: format_markdown("[library #{library.url}] has non-cql/elm content.") }
|
298
213
|
true
|
299
214
|
end
|
300
|
-
next unless library_names.include?
|
215
|
+
next unless library_names.include? library.name
|
301
216
|
|
302
217
|
found_duplicate_library_name = true
|
303
|
-
messages << { type: 'info', message: format_markdown("[library #{
|
304
|
-
#{
|
218
|
+
messages << { type: 'info', message: format_markdown("[library #{library.url}] has a name,
|
219
|
+
#{library.name}, that is already included in the bundle.") }
|
305
220
|
assert !found_duplicate_library_name, 'Found duplicate library names - all names must be unique.'
|
306
221
|
end
|
307
|
-
assert found_cql, "[library #{
|
308
|
-
assert found_elm, "[library #{
|
222
|
+
assert found_cql, "[library #{library.url}] does not include CQL."
|
223
|
+
assert found_elm, "[library #{library.url}] does not include ELM."
|
309
224
|
end
|
310
225
|
|
311
|
-
def check_libraries(
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
found_bundle = true
|
321
|
-
# check the libraries first so references in questionnaires can be checked after
|
322
|
-
param.resource.entry.each_with_index do |entry, index|
|
323
|
-
next unless entry.resource.resourceType == 'Library'
|
324
|
-
|
325
|
-
found_libraries = true
|
326
|
-
library_urls.add(entry.resource.url) unless entry.resource.url.nil?
|
327
|
-
evaluate_library(entry, index)
|
328
|
-
library_names.add(entry.resource.name)
|
329
|
-
end
|
330
|
-
assert found_libraries, 'No Libraries found.'
|
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)
|
331
235
|
end
|
332
|
-
assert found_bundle, 'No questionnaire bundles found.'
|
333
236
|
end
|
334
237
|
|
335
238
|
def check_library_references
|
@@ -405,28 +308,22 @@ module DaVinciDTRTestKit
|
|
405
308
|
end
|
406
309
|
end
|
407
310
|
|
408
|
-
def
|
409
|
-
questionnaire_responses
|
410
|
-
|
411
|
-
|
412
|
-
questionnaire_responses << fhir_resource if fhir_resource.resourceType == 'QuestionnaireResponse'
|
413
|
-
next unless resource.instance_of? Inferno::Entities::Request
|
414
|
-
|
415
|
-
if fhir_resource.resourceType == 'Questionnaire' || fhir_resource.resourceType == 'Parameters'
|
416
|
-
return fhir_resource
|
417
|
-
end
|
418
|
-
end
|
419
|
-
questionnaire_responses
|
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
|
420
315
|
end
|
421
316
|
|
422
|
-
def
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
end
|
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
|
428
322
|
|
429
|
-
|
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
|
430
327
|
end
|
431
328
|
end
|
432
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
|