davinci_dtr_test_kit 0.11.0 → 0.12.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/auth_groups/token_request_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_questionnaire_package_request_test.rb +52 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_launch_attestation_test.rb +28 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_attestation_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_override_attestation_test.rb +27 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_representation_attestation_test.rb +33 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group.rb +81 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_rendering_enabled_questions_attestation_test.rb +30 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_store_attestation_test.rb +29 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb +134 -0
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/{prepopulation_attestation_test.rb → dtr_smart_app_prepopulation_attestation_test.rb} +2 -2
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/{prepopulation_override_attestation_test.rb → dtr_smart_app_prepopulation_override_attestation_test.rb} +2 -2
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/{dtr_questionnaire_response_save_test.rb → dtr_smart_app_questionnaire_response_save_test.rb} +2 -2
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb +13 -13
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/{rendering_enabled_questions_attestation_test.rb → dtr_smart_app_rendering_enabled_questions_attestation_test.rb} +2 -2
- data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_resp_questionnaire_package_request_test.rb +64 -27
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +1 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md +127 -0
- data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +2 -2
- data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +4 -12
- data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +2 -2
- data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +1 -1
- data/lib/davinci_dtr_test_kit/fixture_loader.rb +1 -1
- data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +1 -1
- data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_dinner_order_static.json +1 -1
- data/lib/davinci_dtr_test_kit/mock_auth_server.rb +25 -15
- data/lib/davinci_dtr_test_kit/mock_ehr.rb +8 -3
- data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +1 -1
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb +10 -19
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_bundles_validation_test.rb +6 -6
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_search_validation_test.rb +6 -6
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +16 -18
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_request_validation_test.rb +6 -7
- data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_validation_test.rb +3 -1
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb +9 -20
- data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +7 -14
- data/lib/davinci_dtr_test_kit/validation_test.rb +8 -9
- data/lib/davinci_dtr_test_kit/version.rb +1 -1
- data/lib/davinci_dtr_test_kit.rb +1 -1
- metadata +18 -9
- data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_dinner_questionnaire_package_request_test.rb +0 -97
@@ -10,39 +10,76 @@ module DaVinciDTRTestKit
|
|
10
10
|
Inferno will wait for a DTR questionnaire package request from the client. Upon receipt, Inferno will generate and
|
11
11
|
send a response.
|
12
12
|
)
|
13
|
-
input :smart_app_launch,
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
input :smart_app_launch,
|
14
|
+
type: 'radio',
|
15
|
+
title: 'SMART App Launch',
|
16
|
+
description: 'How will the DTR SMART App launch?',
|
17
|
+
options: { list_options: [{ label: 'EHR Launch from Inferno', value: 'ehr' },
|
18
|
+
{ label: 'Standalone Launch', value: 'standalone' }] }
|
17
19
|
input :client_id
|
18
|
-
input :launch_uri,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
20
|
+
input :launch_uri,
|
21
|
+
optional: true,
|
22
|
+
description: 'Required if "Launch from Inferno" is selected'
|
23
|
+
input :smart_patient_id,
|
24
|
+
optional: true,
|
25
|
+
title: 'SMART App Launch Patient ID (Respiratory Assist Device)',
|
26
|
+
type: 'text',
|
27
|
+
description: %(
|
28
|
+
Patient instance `id` to be provided by Inferno as the `patient` as a part of the SMART App
|
29
|
+
Launch.
|
30
|
+
),
|
31
|
+
default: 'pat015'
|
32
|
+
input :smart_fhir_context,
|
33
|
+
optional: true,
|
34
|
+
title: 'SMART App Launch fhirContext (Respiratory Assist Device)',
|
35
|
+
type: 'textarea',
|
36
|
+
description: %(
|
37
|
+
References to be provided by Inferno as the `fhirContext` as a part of the SMART App
|
38
|
+
Launch. These references help determine the behavior of the app. Referenced instances
|
39
|
+
may be provided in the "EHR-available resources" input.
|
40
|
+
),
|
41
|
+
default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
|
42
|
+
{ reference: 'DeviceRequest/devreqe0470' }])
|
43
|
+
input :ehr_bundle,
|
44
|
+
optional: true,
|
45
|
+
title: 'EHR-available resources (Respiratory Assist Device)',
|
46
|
+
type: 'textarea',
|
47
|
+
description: %(
|
48
|
+
Resources available from the EHR needed to drive the respiratory assist device workflow.
|
49
|
+
Formatted as a FHIR bundle that contains resources, each with an `id` property populated. Each
|
50
|
+
instance present will be available for retrieval from Inferno at the endpoint
|
51
|
+
|
52
|
+
```
|
53
|
+
[fhir-base]/[resource type]/[instance id]
|
54
|
+
```
|
55
|
+
)
|
39
56
|
|
40
57
|
def example_client_jwt_payload_part
|
41
58
|
Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
|
42
59
|
end
|
43
60
|
|
44
61
|
run do
|
45
|
-
|
62
|
+
# validate relevant inputs and provide warnings if they are bad
|
63
|
+
warning do
|
64
|
+
if smart_fhir_context
|
65
|
+
assert_valid_json(smart_fhir_context,
|
66
|
+
'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
|
67
|
+
the access token response.')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
warning do
|
72
|
+
if ehr_bundle
|
73
|
+
assert_valid_json(ehr_bundle,
|
74
|
+
'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
|
75
|
+
will be available to access from Inferno.')
|
76
|
+
assert(FHIR.from_contents(ehr_bundle).is_a?(FHIR::Bundle),
|
77
|
+
'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
|
78
|
+
will be available to access from Inferno.')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
launch_prompt = if smart_app_launch == 'ehr'
|
46
83
|
%(Launch the DTR SMART App from Inferno by right clicking
|
47
84
|
[this link](#{launch_uri}?iss=#{fhir_base_url}&launch=#{launch_uri})
|
48
85
|
and selecting or "Open in new window" or "Open in new tab".)
|
@@ -58,7 +95,7 @@ module DaVinciDTRTestKit
|
|
58
95
|
|
59
96
|
#{launch_prompt}
|
60
97
|
|
61
|
-
#{inferno_prompt_cont if smart_app_launch == '
|
98
|
+
#{inferno_prompt_cont if smart_app_launch == 'ehr'}
|
62
99
|
|
63
100
|
Then, Inferno will expect the SMART App to invoke the DTR Questionnaire Package operation by sending a POST
|
64
101
|
request to
|
@@ -29,7 +29,7 @@ module DaVinciDTRTestKit
|
|
29
29
|
assert input_params.present?, 'Request does not contain a recognized FHIR object'
|
30
30
|
assert_resource_type(:parameters, resource: input_params)
|
31
31
|
assert_valid_resource(resource: input_params,
|
32
|
-
profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters')
|
32
|
+
profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters|2.0.1')
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -22,7 +22,7 @@ module DaVinciDTRTestKit
|
|
22
22
|
assert_resource_type(:questionnaire_response, resource: questionnaire_response)
|
23
23
|
|
24
24
|
assert_valid_resource(resource: questionnaire_response,
|
25
|
-
profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaireresponse')
|
25
|
+
profile_url: 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaireresponse|2.0.1')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
The Da Vinci DTR Test Kit Full 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 payer server that will response to
|
16
|
+
requests for questionnaires for the EHR under test to interact with.
|
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
|
19
|
+
DTR workflows and requirements around the retrieval, completion, and storage of
|
20
|
+
questionnaires.
|
21
|
+
|
22
|
+
Tests within this suite are associated with specific questionnaires that the EHR will
|
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
|
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 it must
|
27
|
+
be conformant. The EHR will then be asked to complete the questionnaire, including
|
28
|
+
- Pre-populating answers based on directives in the questionnaire
|
29
|
+
- Rendering the questionnaire for users and allowing them to make additional updates.
|
30
|
+
These tests can include specific directions on details to include in the completed
|
31
|
+
questionnaire.
|
32
|
+
- Storing the completed questionnaire for future use as a FHIR QuestionnaireResponse.
|
33
|
+
|
34
|
+
EHRs will be required to complete all questionnaires in the suite, which in aggregate
|
35
|
+
contain all questionnaire features that apps must support. Currently, the suite includes
|
36
|
+
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
|
+
All requests sent by the app will be checked
|
42
|
+
for conformance to the DTR IG requirements individually and used in aggregate to determine
|
43
|
+
whether required features and functionality are present. HL7® FHIR® resources are
|
44
|
+
validated with the Java validator using `tx.fhir.org` as the terminology server.
|
45
|
+
|
46
|
+
## Running the Tests
|
47
|
+
|
48
|
+
### Quick Start
|
49
|
+
|
50
|
+
In order to run these tests, EHRs must be configured to interact with Inferno's simulated
|
51
|
+
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
|
53
|
+
`[URL prefix]/dtr_full_ehr/[session id]`.
|
54
|
+
|
55
|
+
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
|
57
|
+
there are two options.
|
58
|
+
|
59
|
+
1. If you want to choose your own bearer token, then
|
60
|
+
1. Select the "2. Basic Workflows" test from the list on the left (or other target test).
|
61
|
+
2. Click the '*Run All Tests*' button on the right.
|
62
|
+
3. In the "access_token" field, enter the bearer token that will be sent by the client
|
63
|
+
under test (as part of the Authorization header - `Bearer <provided value>`).
|
64
|
+
4. Click the '*Submit*' button at the bottom of the dialog.
|
65
|
+
2. If you want to use a client_id to obtain an access token, then
|
66
|
+
1. Click the '*Run All Tests*' button on the right.
|
67
|
+
2. Provide the EHR's registered id "client_id" field of the input (NOTE, Inferno
|
68
|
+
doesn't support the registration API, so this must be obtained from another
|
69
|
+
system or configured manually).
|
70
|
+
3. Click the '*Submit*' button at the bottom of the dialog.
|
71
|
+
4. Make a token request that includes the specified client id to the
|
72
|
+
`[URL prefix]/custom/dtr_full_ehr/mock_auth/token` endpoint to get
|
73
|
+
an access token to use on the request of the requests.
|
74
|
+
|
75
|
+
In either case, the tests will continue from that point. Further executions of tests under
|
76
|
+
this session will also use the selected bearer token.
|
77
|
+
|
78
|
+
Note: authentication options for these tests have not been finalized and are subject to change.
|
79
|
+
|
80
|
+
### Postman-based Demo
|
81
|
+
|
82
|
+
If you do not have a DTR Full EHR but would like to try the tests out, you can use
|
83
|
+
[this Postman collection](https://github.com/inferno-framework/davinci-dtr-test-kit/blob/main/config/DTR%20Full%20EHR%20Tests%20Postman%20Demo.postman_collection.json)
|
84
|
+
to make requests against Inferno. This does not include the capability to render and complete the
|
85
|
+
questionnaires, but does have samples of correctly and incorrectly completed QuestionnaireResponses.
|
86
|
+
To run the tests using this approach:
|
87
|
+
|
88
|
+
1. Install [postman](https://www.postman.com/downloads/).
|
89
|
+
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).
|
90
|
+
1. Start a Da Vinci DTR Full EHR Test Suite Session.
|
91
|
+
1. Update the postman collection configuration variables found by opening the "DTR Full EHR
|
92
|
+
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
|
+
`inferno.healthit.gov`. If running in another location, see guidance on the "Overview" tab
|
95
|
+
of the postman collection.
|
96
|
+
- **access_token**: note the "Current value" (update if desired) for use later.
|
97
|
+
1. Return to Inferno and in the test list at the left, select *2 Static Questionnaire Workflow*.
|
98
|
+
1. Click the "Run All Tests" button in the upper right.
|
99
|
+
1. Add the **access_token** configured in postman to the Inferno input with the same name
|
100
|
+
1. Click the "Submit" button in Inferno.
|
101
|
+
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`
|
103
|
+
request, use postman to submit the "Questionnaire Package for Dinner (Static)" request. Confirm
|
104
|
+
that the response that looks similar to the "Example Working Response" in postman
|
105
|
+
and click the link to continue the tests.
|
106
|
+
1. Attest to the remainder of the tests as desired to get a sense for what is involved in testing
|
107
|
+
with an actual EHR implementation. To see what a valid QuestionnaireResponse looks like, see
|
108
|
+
the "Sample QuestionnaireResponse for Dinner (Static) ..." request in postman.
|
109
|
+
|
110
|
+
## Limitations
|
111
|
+
|
112
|
+
The DTR IG is a complex specification and these tests currently validate conformance to only
|
113
|
+
a subset of IG requirements. Future versions of the test suite will test further
|
114
|
+
features. A few specific features of interest are listed below.
|
115
|
+
|
116
|
+
### Heavy Reliance on Attestations
|
117
|
+
|
118
|
+
Currently, these test kits do not have access to the QuestionnaireResponse and so validation
|
119
|
+
that the EHR performed CQL calculations and generated a conformant QuestionnaireResponse
|
120
|
+
based on pre-population and manual answers is left to a user attestation rather than a
|
121
|
+
mechanical check. Some level of mechanical checks are expected to be added in the future.
|
122
|
+
|
123
|
+
### Questionnaire Feature Coverage
|
124
|
+
|
125
|
+
Not all questionnaire features that are must support within the DTR IG are currently represented
|
126
|
+
in questionnaires tested by the IG. Adaptive questionnaires are a notable omission.
|
127
|
+
Additional questionnaires testing additional features will be added in the future.
|
@@ -81,9 +81,9 @@ If you would like to try out the tests but don't have a DTR payer server impleme
|
|
81
81
|
you can run these tests against the DTR SMART Client test suite included in this test kit
|
82
82
|
using the following steps:
|
83
83
|
1. Start an Inferno session of the Da Vinci DTR SMART App Test Suite.
|
84
|
-
1. Select test
|
84
|
+
1. Select test 1.1.1 *Retrieving the Static Questionnaire* from the menu on the left.
|
85
85
|
1. Click the "Run All Tests" button in the upper right.
|
86
|
-
1. In the "
|
86
|
+
1. In the "SMART App Launch" select `Standalone Launch` and in the "client_id" input, put `sample`.
|
87
87
|
1. Click the "submit" button in the dialog that appears. The client tests will now be waiting for requests.
|
88
88
|
1. Start an Inferno session of the DTR Payer Server test suite.
|
89
89
|
1. Select test 1 *Static Questionnaire Package Retrieval* from the menu on the left.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative 'ext/inferno_core/runnable'
|
2
2
|
require_relative 'ext/inferno_core/record_response_route'
|
3
3
|
require_relative 'ext/inferno_core/request'
|
4
|
-
require_relative 'client_groups/
|
4
|
+
require_relative 'client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group'
|
5
5
|
require_relative 'auth_groups/oauth2_authentication_group'
|
6
6
|
require_relative 'mock_payer'
|
7
7
|
require_relative 'version'
|
@@ -9,19 +9,11 @@ require_relative 'version'
|
|
9
9
|
module DaVinciDTRTestKit
|
10
10
|
class DTRFullEHRSuite < Inferno::TestSuite
|
11
11
|
extend MockPayer
|
12
|
+
extend MockAuthServer
|
12
13
|
|
13
14
|
id :dtr_full_ehr
|
14
15
|
title 'Da Vinci DTR Full EHR Test Suite'
|
15
|
-
description
|
16
|
-
# Da Vinci DTR Full EHR Test Suite
|
17
|
-
|
18
|
-
This suite validates that an EHR or other application can act
|
19
|
-
as a full DTR application requesting questionnaires from a
|
20
|
-
payer server and using local data to complete and store them.
|
21
|
-
Inferno will act as payer server returning questionnaires
|
22
|
-
in response to queries from the system under test and validating
|
23
|
-
that they can be completed as expected.
|
24
|
-
)
|
16
|
+
description File.read(File.join(__dir__, 'docs', 'dtr_full_ehr_suite_description_v201.md'))
|
25
17
|
|
26
18
|
version VERSION
|
27
19
|
|
@@ -74,6 +66,6 @@ module DaVinciDTRTestKit
|
|
74
66
|
end
|
75
67
|
|
76
68
|
group from: :oauth2_authentication
|
77
|
-
group from: :
|
69
|
+
group from: :dtr_full_ehr_static_dinner_questionnaire_workflow
|
78
70
|
end
|
79
71
|
end
|
@@ -88,7 +88,7 @@ module DaVinciDTRTestKit
|
|
88
88
|
end
|
89
89
|
|
90
90
|
origin_extension = find_extension(target_item_answer,
|
91
|
-
'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/information-origin')
|
91
|
+
'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/information-origin|2.0.1')
|
92
92
|
source_extension = find_extension(origin_extension, 'source')
|
93
93
|
|
94
94
|
unless source_extension.present?
|
@@ -134,7 +134,7 @@ module DaVinciDTRTestKit
|
|
134
134
|
|
135
135
|
# check origin.source extension
|
136
136
|
origin_extension = find_extension(answer,
|
137
|
-
'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/information-origin')
|
137
|
+
'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/information-origin|2.0.1')
|
138
138
|
source_extension = find_extension(origin_extension, 'source')
|
139
139
|
|
140
140
|
if source_extension.present?
|
@@ -61,7 +61,7 @@ module DaVinciDTRTestKit
|
|
61
61
|
DTRSmartAppSuite.extract_client_id_from_query_params(request)
|
62
62
|
end
|
63
63
|
|
64
|
-
record_response_route :post, EHR_AUTHORIZE_PATH, '
|
64
|
+
record_response_route :post, EHR_AUTHORIZE_PATH, 'dtr_smart_app_ehr_authorize', method(:ehr_authorize),
|
65
65
|
resumes: ->(_) { false } do |request|
|
66
66
|
DTRSmartAppSuite.extract_client_id_from_form_params(request)
|
67
67
|
end
|
@@ -23,7 +23,7 @@ module DaVinciDTRTestKit
|
|
23
23
|
[
|
24
24
|
'fixtures/dinner_static/questionnaire_dinner_order_static.json',
|
25
25
|
'fixtures/dinner_static/questionnaire_response_dinner_order_static.json',
|
26
|
-
['dtr_smart_app_static_dinner_questionnaire_workflow']
|
26
|
+
['dtr_smart_app_static_dinner_questionnaire_workflow', 'dtr_full_ehr_static_dinner_questionnaire_workflow']
|
27
27
|
],
|
28
28
|
[
|
29
29
|
'fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json',
|
@@ -60,22 +60,20 @@ module DaVinciDTRTestKit
|
|
60
60
|
token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
|
61
61
|
response = { access_token: token, token_type: 'bearer', expires_in: 3600 }
|
62
62
|
test_input = JSON.parse(test_result.input_json)
|
63
|
-
smart_app_launch_input = test_input.find { |input| input['name'] == 'smart_app_launch' }
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
fhir_context = fhir_context_input_value
|
69
|
-
|
70
|
-
|
71
|
-
|
64
|
+
fhir_context_input = test_input.find { |input| input['name'] == 'smart_fhir_context' }
|
65
|
+
fhir_context_input_value = fhir_context_input['value'] if fhir_context_input.present?
|
66
|
+
begin
|
67
|
+
fhir_context = JSON.parse(fhir_context_input_value)
|
68
|
+
rescue StandardError
|
69
|
+
fhir_context = nil
|
70
|
+
end
|
71
|
+
response.merge!({ fhirContext: fhir_context }) if fhir_context
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
smart_patient_input = test_input.find { |input| input['name'] == 'smart_patient_id' }
|
74
|
+
smart_patient_input_value = smart_patient_input['value'] if smart_patient_input.present?
|
75
|
+
response.merge!({ patient: smart_patient_input_value }) if smart_patient_input_value
|
76
76
|
|
77
|
-
response.merge!({ patient: smart_patient, fhirContext: fhir_context })
|
78
|
-
end
|
79
77
|
request.response_body = response.to_json
|
80
78
|
request.response_headers = { 'Access-Control-Allow-Origin' => '*' }
|
81
79
|
request.status = 200
|
@@ -102,7 +100,13 @@ module DaVinciDTRTestKit
|
|
102
100
|
encoded_jwt = URI.decode_www_form(request.request_body).to_h['client_assertion']
|
103
101
|
return unless encoded_jwt.present?
|
104
102
|
|
105
|
-
jwt_payload =
|
103
|
+
jwt_payload =
|
104
|
+
begin
|
105
|
+
JWT.decode(encoded_jwt, nil, false)&.first # skip signature verification
|
106
|
+
rescue StandardError
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
106
110
|
jwt_payload['iss'] || jwt_payload['sub'] if jwt_payload.present?
|
107
111
|
end
|
108
112
|
|
@@ -120,7 +124,13 @@ module DaVinciDTRTestKit
|
|
120
124
|
|
121
125
|
def extract_client_id_from_bearer_token(request)
|
122
126
|
token = extract_bearer_token(request)
|
123
|
-
|
127
|
+
jwt =
|
128
|
+
begin
|
129
|
+
JWT.decode(token, nil, false)
|
130
|
+
rescue StandardError
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
jwt&.first&.dig('inferno_client_id')
|
124
134
|
end
|
125
135
|
|
126
136
|
# Header expected to be a bearer token of the form "Bearer: <token>"
|
@@ -49,9 +49,14 @@ module DaVinciDTRTestKit
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# Respond with user-inputted resource if there is one that matches the request
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
begin
|
53
|
+
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'ehr_bundle' }
|
54
|
+
ehr_bundle_input_value = ehr_bundle_input_value = ehr_bundle_input['value'] if ehr_bundle_input.present?
|
55
|
+
ehr_bundle = FHIR.from_contents(ehr_bundle_input_value) if ehr_bundle_input_value.present?
|
56
|
+
rescue StandardError
|
57
|
+
ehr_bundle = nil
|
58
|
+
end
|
59
|
+
|
55
60
|
if id.present? && ehr_bundle.present? && ehr_bundle.is_a?(FHIR::Bundle)
|
56
61
|
matching_resource = ehr_bundle.entry&.find do |entry|
|
57
62
|
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
|
data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb
CHANGED
@@ -6,7 +6,7 @@ module DaVinciDTRTestKit
|
|
6
6
|
id :dtr_v201_payer_adaptive_next_form_expressions_test
|
7
7
|
title 'Questionnaire(s) contains items with expressions necessary for pre-population'
|
8
8
|
description %(
|
9
|
-
Inferno checks that the payer server response has appropriate expressions and that expressions are
|
9
|
+
Inferno checks that the payer server response to $next-question operation has appropriate expressions and that expressions are
|
10
10
|
written in cql.
|
11
11
|
)
|
12
12
|
|
data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb
CHANGED
@@ -3,7 +3,7 @@ module DaVinciDTRTestKit
|
|
3
3
|
class PayerAdaptiveFormRequestTest < Inferno::Test
|
4
4
|
include URLs
|
5
5
|
include DaVinciDTRTestKit::ValidationTest
|
6
|
-
title '
|
6
|
+
title 'User Input Validation: Questionnaire Package request is valid'
|
7
7
|
description %(
|
8
8
|
This test validates the conformance of the client's request to the
|
9
9
|
[DTR Questionnaire Package Input Parameters](http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters)
|
@@ -13,32 +13,23 @@ module DaVinciDTRTestKit
|
|
13
13
|
values. CodeableConcept element bindings will fail if none of their codings have a code/system belonging
|
14
14
|
to the bound ValueSet. Quantity, Coding, and code element bindings will fail if their code/system are not found in
|
15
15
|
the valueset.
|
16
|
-
|
17
|
-
This test may process multiple resources, labeling messages with the corresponding tested resources
|
18
|
-
in the order that they were received.
|
19
16
|
)
|
20
17
|
id :payer_server_adaptive_questionnaire_request_validation
|
21
18
|
|
22
19
|
run do
|
23
20
|
skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
|
21
|
+
profile_with_version = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters|2.0.1'
|
24
22
|
if initial_adaptive_questionnaire_request.nil?
|
25
|
-
|
26
|
-
|
23
|
+
requests = load_tagged_requests(QUESTIONNAIRE_TAG)
|
24
|
+
skip_if requests.blank?, 'No request resource received from the client.'
|
25
|
+
# making the assumption that only one request was made here - if there were multiple, we are only validating the first
|
26
|
+
resource_is_valid?(resource: FHIR.from_contents(requests[0].request[:body]), profile_url: profile_with_version)
|
27
27
|
else
|
28
|
-
|
29
|
-
|
28
|
+
request = FHIR.from_contents(initial_adaptive_questionnaire_request)
|
29
|
+
resource_is_valid?(resource: request, profile_url: profile_with_version)
|
30
30
|
end
|
31
|
-
|
32
|
-
|
33
|
-
resources,
|
34
|
-
:parameters,
|
35
|
-
'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters',
|
36
|
-
questionnaire_package_url,
|
37
|
-
using_manual_entry
|
38
|
-
)
|
39
|
-
rescue Inferno::Exceptions::AssertionException => e
|
40
|
-
msg = e.message.to_s.strip
|
41
|
-
skip msg
|
31
|
+
errors_found = messages.any? { |message| message[:type] == 'error' }
|
32
|
+
skip_if errors_found, "Resource does not conform to the profile #{profile_with_version}"
|
42
33
|
end
|
43
34
|
end
|
44
35
|
end
|
@@ -20,21 +20,21 @@ module DaVinciDTRTestKit
|
|
20
20
|
|
21
21
|
run do
|
22
22
|
skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
|
23
|
-
test_passed =
|
24
|
-
profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle'
|
23
|
+
test_passed = true
|
24
|
+
profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle|2.0.1'
|
25
25
|
assert !scratch[:adaptive_responses].nil?, 'No resources to validate.'
|
26
26
|
scratch[:adaptive_responses].each_with_index do |resource, index|
|
27
27
|
fhir_resource = FHIR.from_contents(resource.response[:body])
|
28
28
|
fhir_resource.parameter.each do |param|
|
29
29
|
resource_is_valid = validate_resource(param.resource, :bundle, profile_url, index)
|
30
|
-
test_passed =
|
30
|
+
test_passed = false unless resource_is_valid
|
31
31
|
rescue StandardError
|
32
32
|
next
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
if !test_passed && !tests_failed[profile_url].blank?
|
36
|
+
assert test_passed, "Not all returned resources conform to the profile: #{profile_url}"
|
37
|
+
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -20,23 +20,23 @@ module DaVinciDTRTestKit
|
|
20
20
|
|
21
21
|
run do
|
22
22
|
skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
|
23
|
-
test_passed =
|
24
|
-
profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt-search'
|
23
|
+
test_passed = true
|
24
|
+
profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt-search|2.0.1'
|
25
25
|
assert !scratch[:adaptive_responses].nil?, 'No resources to validate.'
|
26
26
|
scratch[:adaptive_responses].each_with_index do |resource, index|
|
27
27
|
fhir_resource = FHIR.from_contents(resource.response[:body])
|
28
28
|
fhir_resource.parameter.each do |param|
|
29
29
|
param.resource.entry.each do |entry|
|
30
30
|
resource_is_valid = validate_resource(entry.resource, :questionnaire, profile_url, index)
|
31
|
-
test_passed =
|
31
|
+
test_passed = false unless resource_is_valid
|
32
32
|
end
|
33
33
|
rescue StandardError
|
34
34
|
next
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
if !test_passed && !tests_failed[profile_url].blank?
|
38
|
+
assert test_passed, "Not all returned resources conform to the profile: #{profile_url}"
|
39
|
+
end
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|