davinci_dtr_test_kit 0.13.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 -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 +11 -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 +109 -20
- 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
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: davinci_dtr_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Naden
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-12-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: inferno_core
|
@@ -54,6 +54,34 @@ dependencies:
|
|
54
54
|
- - "~>"
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: 0.4.4
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: tls_test_kit
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - '='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.2.2
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - '='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 0.2.2
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: us_core_test_kit
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.0
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 0.9.0
|
57
85
|
description: Test Kit for the Da Vinci Documentation Templates and Rules (DTR) FHIR
|
58
86
|
Implementation Guide
|
59
87
|
email:
|
@@ -67,22 +95,30 @@ files:
|
|
67
95
|
- lib/davinci_dtr_test_kit/auth_groups/oauth2_authentication_group.rb
|
68
96
|
- lib/davinci_dtr_test_kit/auth_groups/token_request_test.rb
|
69
97
|
- lib/davinci_dtr_test_kit/auth_groups/token_validation_test.rb
|
98
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_completion_group.rb
|
99
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_followup_questions_group.rb
|
100
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_test.rb
|
101
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_validation_test.rb
|
102
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_retrieval_group.rb
|
103
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_response_validation_test.rb
|
104
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_dinner_questionnaire_workflow_group.rb
|
105
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_initial_retrieval_group.rb
|
106
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_request_test.rb
|
107
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_initial_retrieval_group.rb
|
108
|
+
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_request_test.rb
|
70
109
|
- lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group.rb
|
71
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_questionnaire_package_request_test.rb
|
72
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_conformance_test.rb
|
73
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_dinner_static_questionnaire_response_correctness_test.rb
|
74
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_launch_attestation_test.rb
|
75
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_attestation_test.rb
|
76
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_prepopulation_override_attestation_test.rb
|
77
110
|
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group.rb
|
78
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_rendering_enabled_questions_attestation_test.rb
|
79
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_store_attestation_test.rb
|
80
111
|
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb
|
81
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_prepopulation_attestation_test.rb
|
82
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_prepopulation_override_attestation_test.rb
|
83
|
-
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_response_save_test.rb
|
84
112
|
- lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb
|
85
|
-
- lib/davinci_dtr_test_kit/client_groups/
|
113
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_launch_attestation_test.rb
|
114
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_prepopulation_attestation_test.rb
|
115
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_prepopulation_override_attestation_test.rb
|
116
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_package_request_test.rb
|
117
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_conformance_test.rb
|
118
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_questionnaire_response_correctness_test.rb
|
119
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_rendering_enabled_questions_attestation_test.rb
|
120
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_saving_questionnaire_response_group.rb
|
121
|
+
- lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_store_attestation_test.rb
|
86
122
|
- lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_package_group.rb
|
87
123
|
- lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_attestation_test.rb
|
88
124
|
- lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_group.rb
|
@@ -93,7 +129,13 @@ files:
|
|
93
129
|
- lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb
|
94
130
|
- lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb
|
95
131
|
- lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb
|
132
|
+
- lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_prepopulation_attestation_test.rb
|
133
|
+
- lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_prepopulation_override_attestation_test.rb
|
134
|
+
- lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_questionnaire_response_save_test.rb
|
135
|
+
- lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_rendering_enabled_questions_attestation_test.rb
|
136
|
+
- lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_saving_questionnaire_response_group.rb
|
96
137
|
- lib/davinci_dtr_test_kit/cql_test.rb
|
138
|
+
- lib/davinci_dtr_test_kit/create_test.rb
|
97
139
|
- lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md
|
98
140
|
- lib/davinci_dtr_test_kit/docs/dtr_light_ehr_suite_description_v201.md
|
99
141
|
- lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md
|
@@ -104,9 +146,21 @@ files:
|
|
104
146
|
- lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb
|
105
147
|
- lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb
|
106
148
|
- lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb
|
107
|
-
- lib/davinci_dtr_test_kit/
|
108
|
-
- lib/davinci_dtr_test_kit/
|
109
|
-
- lib/davinci_dtr_test_kit/
|
149
|
+
- lib/davinci_dtr_test_kit/endpoints/cors.rb
|
150
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_authorization.rb
|
151
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_authorization/authorize_endpoint.rb
|
152
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_authorization/simple_token_endpoint.rb
|
153
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_authorization/token_endpoint.rb
|
154
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_ehr.rb
|
155
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_ehr/fhir_get_endpoint.rb
|
156
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_ehr/questionnaire_response_endpoint.rb
|
157
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer.rb
|
158
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb
|
159
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb
|
160
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_endpoint.rb
|
161
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_proxy_endpoint.rb
|
162
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_endpoint.rb
|
163
|
+
- lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_proxy_endpoint.rb
|
110
164
|
- lib/davinci_dtr_test_kit/fixture_loader.rb
|
111
165
|
- lib/davinci_dtr_test_kit/fixtures.rb
|
112
166
|
- lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json
|
@@ -117,9 +171,6 @@ files:
|
|
117
171
|
- lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_response_dinner_order_static.json
|
118
172
|
- lib/davinci_dtr_test_kit/fixtures/respiratory_assist_device/pre_populated_questionnaire_response.json
|
119
173
|
- lib/davinci_dtr_test_kit/fixtures/respiratory_assist_device/questionnaire_package.json
|
120
|
-
- lib/davinci_dtr_test_kit/mock_auth_server.rb
|
121
|
-
- lib/davinci_dtr_test_kit/mock_ehr.rb
|
122
|
-
- lib/davinci_dtr_test_kit/mock_payer.rb
|
123
174
|
- lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_libraries_test.rb
|
124
175
|
- lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_expressions_test.rb
|
125
176
|
- lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_extensions_test.rb
|
@@ -141,7 +192,45 @@ files:
|
|
141
192
|
- lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_test.rb
|
142
193
|
- lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb
|
143
194
|
- lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb
|
195
|
+
- lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_read.rb
|
196
|
+
- lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_validation.rb
|
197
|
+
- lib/davinci_dtr_test_kit/profiles/communication_request_group.rb
|
198
|
+
- lib/davinci_dtr_test_kit/profiles/coverage/coverage_read.rb
|
199
|
+
- lib/davinci_dtr_test_kit/profiles/coverage/coverage_validation.rb
|
200
|
+
- lib/davinci_dtr_test_kit/profiles/coverage_group.rb
|
201
|
+
- lib/davinci_dtr_test_kit/profiles/device_request/device_request_read.rb
|
202
|
+
- lib/davinci_dtr_test_kit/profiles/device_request/device_request_validation.rb
|
203
|
+
- lib/davinci_dtr_test_kit/profiles/device_request_group.rb
|
204
|
+
- lib/davinci_dtr_test_kit/profiles/encounter/encounter_read.rb
|
205
|
+
- lib/davinci_dtr_test_kit/profiles/encounter/encounter_validation.rb
|
206
|
+
- lib/davinci_dtr_test_kit/profiles/encounter_group.rb
|
207
|
+
- lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_read.rb
|
208
|
+
- lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_validation.rb
|
209
|
+
- lib/davinci_dtr_test_kit/profiles/medication_request_group.rb
|
210
|
+
- lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_read.rb
|
211
|
+
- lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_validation.rb
|
212
|
+
- lib/davinci_dtr_test_kit/profiles/nutrition_order_group.rb
|
213
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_context_search.rb
|
214
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_create.rb
|
215
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_patient_search.rb
|
216
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_read.rb
|
217
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_update.rb
|
218
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_validation.rb
|
219
|
+
- lib/davinci_dtr_test_kit/profiles/questionnaire_response_group.rb
|
220
|
+
- lib/davinci_dtr_test_kit/profiles/service_request/service_request_read.rb
|
221
|
+
- lib/davinci_dtr_test_kit/profiles/service_request/service_request_validation.rb
|
222
|
+
- lib/davinci_dtr_test_kit/profiles/service_request_group.rb
|
223
|
+
- lib/davinci_dtr_test_kit/profiles/task/task_create.rb
|
224
|
+
- lib/davinci_dtr_test_kit/profiles/task/task_read.rb
|
225
|
+
- lib/davinci_dtr_test_kit/profiles/task/task_update.rb
|
226
|
+
- lib/davinci_dtr_test_kit/profiles/task/task_validation.rb
|
227
|
+
- lib/davinci_dtr_test_kit/profiles/task_group.rb
|
228
|
+
- lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_read.rb
|
229
|
+
- lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_validation.rb
|
230
|
+
- lib/davinci_dtr_test_kit/profiles/vision_prescription_group.rb
|
231
|
+
- lib/davinci_dtr_test_kit/read_test.rb
|
144
232
|
- lib/davinci_dtr_test_kit/tags.rb
|
233
|
+
- lib/davinci_dtr_test_kit/update_test.rb
|
145
234
|
- lib/davinci_dtr_test_kit/urls.rb
|
146
235
|
- lib/davinci_dtr_test_kit/validation_test.rb
|
147
236
|
- lib/davinci_dtr_test_kit/version.rb
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'hanami/controller'
|
2
|
-
|
3
|
-
module Inferno
|
4
|
-
module DSL
|
5
|
-
# A base class for creating routes with custom response logic. Requests and responses are tagged and saved.
|
6
|
-
# @private
|
7
|
-
# @see Inferno::DSL::Runnable#resume_test_route
|
8
|
-
class RecordResponseRoute < Hanami::Action
|
9
|
-
include Import[
|
10
|
-
requests_repo: 'inferno.repositories.requests',
|
11
|
-
results_repo: 'inferno.repositories.results',
|
12
|
-
test_runs_repo: 'inferno.repositories.test_runs',
|
13
|
-
tests_repo: 'inferno.repositories.tests'
|
14
|
-
]
|
15
|
-
|
16
|
-
def self.call(...)
|
17
|
-
new.call(...)
|
18
|
-
end
|
19
|
-
|
20
|
-
# @private
|
21
|
-
def test_run_identifier_block
|
22
|
-
self.class.singleton_class.instance_variable_get(:@test_run_identifier_block)
|
23
|
-
end
|
24
|
-
|
25
|
-
# @private
|
26
|
-
def build_response_block
|
27
|
-
self.class.singleton_class.instance_variable_get(:@build_response_block)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @private
|
31
|
-
def tags
|
32
|
-
self.class.singleton_class.instance_variable_get(:@tags)
|
33
|
-
end
|
34
|
-
|
35
|
-
# @private
|
36
|
-
def resumes?(test)
|
37
|
-
instance_exec(test, &self.class.singleton_class.instance_variable_get(:@resumes))
|
38
|
-
end
|
39
|
-
|
40
|
-
# @private
|
41
|
-
def find_test_run(test_run_identifier)
|
42
|
-
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
43
|
-
end
|
44
|
-
|
45
|
-
# @private
|
46
|
-
def find_waiting_result(test_run)
|
47
|
-
results_repo.find_waiting_result(test_run_id: test_run.id)
|
48
|
-
end
|
49
|
-
|
50
|
-
# @private
|
51
|
-
def update_result(waiting_result)
|
52
|
-
results_repo.update_result(waiting_result.id, 'pass')
|
53
|
-
end
|
54
|
-
|
55
|
-
# @private
|
56
|
-
def persist_request(request, test_run, waiting_result, test)
|
57
|
-
requests_repo.create(
|
58
|
-
request.to_hash.merge(
|
59
|
-
test_session_id: test_run.test_session_id,
|
60
|
-
result_id: waiting_result.id,
|
61
|
-
name: test.config.request_name(test.incoming_request_name),
|
62
|
-
tags:
|
63
|
-
)
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
|
-
# @private
|
68
|
-
def find_test(waiting_result)
|
69
|
-
tests_repo.find(waiting_result.test_id)
|
70
|
-
end
|
71
|
-
|
72
|
-
# @private
|
73
|
-
def handle(req, res)
|
74
|
-
request = Inferno::Entities::Request.from_hanami_request(req)
|
75
|
-
|
76
|
-
test_run_identifier = instance_exec(request, &test_run_identifier_block)
|
77
|
-
|
78
|
-
test_run = find_test_run(test_run_identifier)
|
79
|
-
|
80
|
-
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
81
|
-
|
82
|
-
waiting_result = find_waiting_result(test_run)
|
83
|
-
test = find_test(waiting_result)
|
84
|
-
|
85
|
-
test_runs_repo.mark_as_no_longer_waiting(test_run.id) if resumes? test
|
86
|
-
|
87
|
-
update_result(waiting_result) if resumes? test
|
88
|
-
|
89
|
-
instance_exec(request, test, waiting_result, &build_response_block)
|
90
|
-
|
91
|
-
Inferno::Entities::Request.to_hanami_response(request, res)
|
92
|
-
persist_request(request, test_run, waiting_result, test)
|
93
|
-
|
94
|
-
Jobs.perform(Jobs::ResumeTestRun, test_run.id) if resumes? test
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Inferno
|
2
|
-
module Entities
|
3
|
-
class Request
|
4
|
-
def self.to_hanami_response(request, response)
|
5
|
-
response.status = request.status
|
6
|
-
response.body = request.response_body
|
7
|
-
request.response_headers.each do |header|
|
8
|
-
response.headers[header.name] = header.value
|
9
|
-
end
|
10
|
-
|
11
|
-
response
|
12
|
-
end
|
13
|
-
|
14
|
-
def response_headers=(headers_hash)
|
15
|
-
headers.concat(headers_hash.map { |key, value| Header.new(name: key.to_s, value:, type: 'response') })
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require_relative 'record_response_route'
|
2
|
-
|
3
|
-
module Inferno
|
4
|
-
module DSL
|
5
|
-
module Runnable
|
6
|
-
PRE_FLIGHT_HANDLER = proc do
|
7
|
-
[
|
8
|
-
200,
|
9
|
-
{
|
10
|
-
'Access-Control-Allow-Origin' => '*',
|
11
|
-
'Access-Control-Allow-Headers' => 'Content-Type, Authorization'
|
12
|
-
},
|
13
|
-
['']
|
14
|
-
]
|
15
|
-
end
|
16
|
-
|
17
|
-
def allow_cors(*paths)
|
18
|
-
paths.each do |path|
|
19
|
-
route(:options, path, PRE_FLIGHT_HANDLER)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def record_response_route(method, path, tags, build_response, resumes: ->(_) { true }, &block)
|
24
|
-
route_class = Class.new(Inferno::DSL::RecordResponseRoute) do |klass|
|
25
|
-
klass.singleton_class.instance_variable_set(:@build_response_block, build_response)
|
26
|
-
klass.singleton_class.instance_variable_set(:@test_run_identifier_block, block)
|
27
|
-
klass.singleton_class.instance_variable_set(:@tags, Array.wrap(tags))
|
28
|
-
klass.singleton_class.instance_variable_set(:@resumes, resumes)
|
29
|
-
end
|
30
|
-
|
31
|
-
route(method, path, route_class)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,228 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'urls'
|
4
|
-
|
5
|
-
module DaVinciDTRTestKit
|
6
|
-
module MockAuthServer
|
7
|
-
AUTHORIZED_PRACTITIONER_ID = 'pra1234' # Must exist on the FHIR_REFERENCE_SERVER (env var)
|
8
|
-
|
9
|
-
RSA_PRIVATE_KEY = OpenSSL::PKey::RSA.generate(2048)
|
10
|
-
RSA_PUBLIC_KEY = RSA_PRIVATE_KEY.public_key
|
11
|
-
SUPPORTED_SCOPES = ['launch', 'patient/*.rs', 'user/*.rs', 'offline_access', 'openid', 'fhirUser'].freeze
|
12
|
-
|
13
|
-
def requests_repo
|
14
|
-
@requests_repo ||= Inferno::Repositories::Requests.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def auth_server_jwks(_env)
|
18
|
-
response_body = {
|
19
|
-
keys: [
|
20
|
-
{
|
21
|
-
kty: 'RSA',
|
22
|
-
alg: 'RS256',
|
23
|
-
n: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.n.to_s(2), padding: false),
|
24
|
-
e: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.e.to_s(2), padding: false),
|
25
|
-
use: 'sig'
|
26
|
-
}
|
27
|
-
]
|
28
|
-
}.to_json
|
29
|
-
|
30
|
-
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
31
|
-
end
|
32
|
-
|
33
|
-
def ehr_smart_config(env)
|
34
|
-
base_url = env_base_url(env, SMART_CONFIG_PATH)
|
35
|
-
response_body =
|
36
|
-
{
|
37
|
-
authorization_endpoint: base_url + EHR_AUTHORIZE_PATH,
|
38
|
-
token_endpoint: base_url + EHR_TOKEN_PATH,
|
39
|
-
token_endpoint_auth_methods_supported: ['private_key_jwt'],
|
40
|
-
token_endpoint_auth_signing_alg_values_supported: ['RS256'],
|
41
|
-
grant_types_supported: ['authorization_code'],
|
42
|
-
scopes_supported: SUPPORTED_SCOPES,
|
43
|
-
response_types_supported: ['code'],
|
44
|
-
code_challenge_methods_supported: ['S256'],
|
45
|
-
capabilities: [
|
46
|
-
'launch-ehr',
|
47
|
-
'permission-patient',
|
48
|
-
'permission-user',
|
49
|
-
'client-public',
|
50
|
-
'client-confidential-symmetric',
|
51
|
-
'client-confidential-asymmetric'
|
52
|
-
]
|
53
|
-
}.to_json
|
54
|
-
|
55
|
-
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
56
|
-
end
|
57
|
-
|
58
|
-
def ehr_openid_config(env)
|
59
|
-
base_url = env_base_url(env, OPENID_CONFIG_PATH)
|
60
|
-
response_body = {
|
61
|
-
issuer: base_url + FHIR_BASE_PATH,
|
62
|
-
authorization_endpoint: base_url + EHR_AUTHORIZE_PATH,
|
63
|
-
token_endpoint: base_url + EHR_TOKEN_PATH,
|
64
|
-
jwks_uri: base_url + JKWS_PATH,
|
65
|
-
response_types_supported: ['id_token'],
|
66
|
-
subject_types_supported: ['public'],
|
67
|
-
id_token_signing_alg_values_supported: ['RS256']
|
68
|
-
}.to_json
|
69
|
-
[200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]]
|
70
|
-
end
|
71
|
-
|
72
|
-
def ehr_authorize(request, _test = nil, _test_result = nil)
|
73
|
-
# Authorization requests can bet GET or POST
|
74
|
-
params = params_hash(request)
|
75
|
-
if params['redirect_uri'].present?
|
76
|
-
redirect_uri = "#{params['redirect_uri']}?" \
|
77
|
-
"code=#{SecureRandom.hex}&" \
|
78
|
-
"state=#{params['state']}"
|
79
|
-
request.status = 302
|
80
|
-
request.response_headers = { 'Location' => redirect_uri }
|
81
|
-
else
|
82
|
-
request.status = 400
|
83
|
-
request.response_headers = { 'Content-Type': 'application/json' }
|
84
|
-
request.response_body = FHIR::OperationOutcome.new(
|
85
|
-
issue: FHIR::OperationOutcome::Issue.new(severity: 'fatal', code: 'required',
|
86
|
-
details: FHIR::CodeableConcept.new(
|
87
|
-
text: 'No redirect_uri provided'
|
88
|
-
))
|
89
|
-
).to_json
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def ehr_token_response(request, _test = nil, test_result = nil)
|
94
|
-
client_id = extract_client_id_from_token_request(request)
|
95
|
-
access_token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
|
96
|
-
granted_scopes = SUPPORTED_SCOPES & requested_scopes(test_result.test_session_id)
|
97
|
-
|
98
|
-
response = { access_token:, scope: granted_scopes.join(' '), token_type: 'bearer', expires_in: 3600 }
|
99
|
-
|
100
|
-
if granted_scopes.include?('openid')
|
101
|
-
response.merge!(id_token: create_id_token(request, client_id, fhir_user: granted_scopes.include?('fhirUser')))
|
102
|
-
end
|
103
|
-
|
104
|
-
fhir_context_input = find_test_input(test_result, 'smart_fhir_context')
|
105
|
-
fhir_context_input_value = fhir_context_input['value'] if fhir_context_input
|
106
|
-
begin
|
107
|
-
fhir_context = JSON.parse(fhir_context_input_value)
|
108
|
-
rescue StandardError
|
109
|
-
fhir_context = nil
|
110
|
-
end
|
111
|
-
response.merge!(fhirContext: fhir_context) if fhir_context
|
112
|
-
|
113
|
-
smart_patient_input = find_test_input(test_result, 'smart_patient_id')
|
114
|
-
smart_patient_input_value = smart_patient_input['value'] if smart_patient_input.present?
|
115
|
-
response.merge!(patient: smart_patient_input_value) if smart_patient_input_value
|
116
|
-
|
117
|
-
request.response_body = response.to_json
|
118
|
-
request.response_headers = {
|
119
|
-
'Cache-Control' => 'no-store',
|
120
|
-
'Pragma' => 'no-cache',
|
121
|
-
'Access-Control-Allow-Origin' => '*'
|
122
|
-
}
|
123
|
-
request.status = 200
|
124
|
-
end
|
125
|
-
|
126
|
-
def payer_token_response(request, _test = nil, _test_result = nil)
|
127
|
-
# Placeholder for a more complete mock token endpoint
|
128
|
-
request.response_body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 3600 }.to_json
|
129
|
-
request.status = 200
|
130
|
-
end
|
131
|
-
|
132
|
-
def extract_client_id_from_token_request(request)
|
133
|
-
# Public client || confidential client asymmetric || confidential client symmetric
|
134
|
-
extract_client_id_from_form_params(request) ||
|
135
|
-
extract_client_id_from_client_assertion(request) ||
|
136
|
-
extract_client_id_from_basic_auth(request)
|
137
|
-
end
|
138
|
-
|
139
|
-
def extract_client_id_from_form_params(request)
|
140
|
-
URI.decode_www_form(request.request_body).to_h['client_id']
|
141
|
-
end
|
142
|
-
|
143
|
-
def extract_client_id_from_client_assertion(request)
|
144
|
-
encoded_jwt = URI.decode_www_form(request.request_body).to_h['client_assertion']
|
145
|
-
return unless encoded_jwt.present?
|
146
|
-
|
147
|
-
jwt_payload =
|
148
|
-
begin
|
149
|
-
JWT.decode(encoded_jwt, nil, false)&.first # skip signature verification
|
150
|
-
rescue StandardError
|
151
|
-
nil
|
152
|
-
end
|
153
|
-
|
154
|
-
jwt_payload['iss'] || jwt_payload['sub'] if jwt_payload.present?
|
155
|
-
end
|
156
|
-
|
157
|
-
def extract_client_id_from_basic_auth(request)
|
158
|
-
encoded_credentials = request.request_header('Authorization')&.value&.split&.last
|
159
|
-
return unless encoded_credentials.present?
|
160
|
-
|
161
|
-
decoded_credentials = Base64.decode64(encoded_credentials)
|
162
|
-
decoded_credentials&.split(':')&.first
|
163
|
-
end
|
164
|
-
|
165
|
-
def extract_client_id_from_query_params(request)
|
166
|
-
request.query_parameters['client_id']
|
167
|
-
end
|
168
|
-
|
169
|
-
def extract_client_id_from_bearer_token(request)
|
170
|
-
token = extract_bearer_token(request)
|
171
|
-
jwt =
|
172
|
-
begin
|
173
|
-
JWT.decode(token, nil, false)
|
174
|
-
rescue StandardError
|
175
|
-
nil
|
176
|
-
end
|
177
|
-
jwt&.first&.dig('inferno_client_id')
|
178
|
-
end
|
179
|
-
|
180
|
-
# Header expected to be a bearer token of the form "Bearer: <token>"
|
181
|
-
def extract_bearer_token(request)
|
182
|
-
request.request_header('Authorization')&.value&.split&.last
|
183
|
-
end
|
184
|
-
|
185
|
-
def extract_token_from_query_params(request)
|
186
|
-
request.query_parameters['token']
|
187
|
-
end
|
188
|
-
|
189
|
-
def create_id_token(request, client_id, fhir_user: false)
|
190
|
-
# No point in mocking an identity provider, just always use known Practitioner as the authorized user
|
191
|
-
suite_base_url = request.url.split(EHR_TOKEN_PATH).first
|
192
|
-
id_token_hash = {
|
193
|
-
iss: suite_base_url + FHIR_BASE_PATH,
|
194
|
-
sub: AUTHORIZED_PRACTITIONER_ID,
|
195
|
-
aud: client_id,
|
196
|
-
exp: Time.now.to_i + (24 * 60 * 60), # 24 hrs
|
197
|
-
iat: Time.now.to_i
|
198
|
-
}
|
199
|
-
id_token_hash.merge!(fhirUser: "#{suite_base_url}/fhir/Practitioner/#{AUTHORIZED_PRACTITIONER_ID}") if fhir_user
|
200
|
-
|
201
|
-
JWT.encode(id_token_hash, RSA_PRIVATE_KEY, 'RS256')
|
202
|
-
end
|
203
|
-
|
204
|
-
def requested_scopes(test_session_id)
|
205
|
-
auth_request = requests_repo.tagged_requests(test_session_id, [EHR_AUTHORIZE_TAG]).last
|
206
|
-
return [] unless auth_request
|
207
|
-
|
208
|
-
scope_str = params_hash(auth_request)&.dig('scope')
|
209
|
-
scope_str ? URI.decode_www_form_component(scope_str).split : []
|
210
|
-
end
|
211
|
-
|
212
|
-
def find_test_input(test_result, input_name)
|
213
|
-
JSON.parse(test_result.input_json)&.find { |input| input['name'] == input_name }
|
214
|
-
end
|
215
|
-
|
216
|
-
def params_hash(request)
|
217
|
-
request.verb == 'get' ? request.query_parameters : URI.decode_www_form(request.request_body)&.to_h
|
218
|
-
end
|
219
|
-
|
220
|
-
def env_base_url(env, endpoint_path)
|
221
|
-
protocol = env['rack.url_scheme']
|
222
|
-
host = env['HTTP_HOST']
|
223
|
-
path = env['REQUEST_PATH'] || env['PATH_INFO']
|
224
|
-
path.gsub!(%r{#{endpoint_path}(/)?}, '')
|
225
|
-
"#{protocol}://#{host + path}"
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'urls'
|
4
|
-
|
5
|
-
module DaVinciDTRTestKit
|
6
|
-
module MockEHR
|
7
|
-
RESOURCE_SERVER_BASE = ENV.fetch('FHIR_REFERENCE_SERVER')
|
8
|
-
RESOURCE_SERVER_BEARER_TOKEN = 'SAMPLE_TOKEN'
|
9
|
-
|
10
|
-
RESPONSE_HEADERS = { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }.freeze
|
11
|
-
|
12
|
-
def resource_server_client
|
13
|
-
return @resource_server_client if @resource_server_client
|
14
|
-
|
15
|
-
client = FHIR::Client.new(RESOURCE_SERVER_BASE)
|
16
|
-
client.set_bearer_token(RESOURCE_SERVER_BEARER_TOKEN)
|
17
|
-
@resource_server_client = client
|
18
|
-
end
|
19
|
-
|
20
|
-
def metadata_handler(_env)
|
21
|
-
cs = resource_server_client.capability_statement
|
22
|
-
if cs.present?
|
23
|
-
[200, RESPONSE_HEADERS, [cs.to_json]]
|
24
|
-
else
|
25
|
-
[500, {}, ['Unexpected error occurred while fetching metadata']]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def get_fhir_resource(request, _test = nil, test_result = nil)
|
30
|
-
fhir_class, id = fhir_class_and_id_from_url(request.url)
|
31
|
-
request.response_headers = RESPONSE_HEADERS
|
32
|
-
|
33
|
-
if fhir_class.nil?
|
34
|
-
request.status = 400
|
35
|
-
request.response_headers = { 'Content-Type': 'application/json' }
|
36
|
-
request.response_body = FHIR::OperationOutcome.new(
|
37
|
-
issue: FHIR::OperationOutcome::Issue.new(severity: 'warning', code: 'not-supported',
|
38
|
-
details: FHIR::CodeableConcept.new(
|
39
|
-
text: 'No recognized resource type in URL'
|
40
|
-
))
|
41
|
-
).to_json
|
42
|
-
return
|
43
|
-
end
|
44
|
-
|
45
|
-
# Respond with user-inputted resource if there is one that matches the request
|
46
|
-
ehr_bundle = ehr_input_bundle(test_result)
|
47
|
-
if id.present? && ehr_bundle.present?
|
48
|
-
matching_resource = find_resource_in_bundle(ehr_bundle, fhir_class, id)
|
49
|
-
if matching_resource.present?
|
50
|
-
request.status = 200
|
51
|
-
request.response_headers = { 'Content-Type': 'application/json' }
|
52
|
-
request.response_body = matching_resource.to_json
|
53
|
-
return
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Proxy resource request to the reference server
|
58
|
-
response = if id.present?
|
59
|
-
resource_server_client.read(fhir_class, id)
|
60
|
-
else
|
61
|
-
resource_server_client.search(fhir_class, search: { parameters: request.query_parameters })
|
62
|
-
end
|
63
|
-
request.status = response.code
|
64
|
-
request.response_body = response.body
|
65
|
-
end
|
66
|
-
|
67
|
-
def questionnaire_response_response(request, _test = nil, _test_result = nil)
|
68
|
-
request.status = 201
|
69
|
-
request.response_headers = RESPONSE_HEADERS
|
70
|
-
request.response_body = request.request_body
|
71
|
-
end
|
72
|
-
|
73
|
-
def ehr_input_bundle(test_result)
|
74
|
-
ehr_bundle_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'ehr_bundle' }
|
75
|
-
ehr_bundle_input_value = ehr_bundle_input_value = ehr_bundle_input['value'] if ehr_bundle_input.present?
|
76
|
-
ehr_bundle = FHIR.from_contents(ehr_bundle_input_value) if ehr_bundle_input_value.present?
|
77
|
-
ehr_bundle if ehr_bundle.is_a?(FHIR::Bundle)
|
78
|
-
rescue StandardError
|
79
|
-
nil
|
80
|
-
end
|
81
|
-
|
82
|
-
def find_resource_in_bundle(bundle, fhir_class, id)
|
83
|
-
bundle.entry&.find do |entry|
|
84
|
-
entry.resource.is_a?(fhir_class) && entry.resource&.id == id
|
85
|
-
end&.resource
|
86
|
-
end
|
87
|
-
|
88
|
-
# Pull resource type class and ID from url
|
89
|
-
# e.g. http://example.org/fhir/Patient/123 -> [FHIR::Patient, '123']
|
90
|
-
# @private
|
91
|
-
def fhir_class_and_id_from_url(url)
|
92
|
-
path = url.split('?').first.split('/fhir/').second
|
93
|
-
path.sub!(%r{/$}, '')
|
94
|
-
resource_type, id = path.split('/')
|
95
|
-
|
96
|
-
begin
|
97
|
-
fhir_class = FHIR.const_get(resource_type)
|
98
|
-
rescue NameError
|
99
|
-
fhir_class = nil
|
100
|
-
end
|
101
|
-
|
102
|
-
[fhir_class, id]
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|