davinci_dtr_test_kit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/davinci_dtr_test_kit/auth_groups/oauth2_authentication_group.rb +51 -0
  4. data/lib/davinci_dtr_test_kit/auth_groups/token_request_test.rb +25 -0
  5. data/lib/davinci_dtr_test_kit/auth_groups/token_validation_test.rb +13 -0
  6. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group.rb +20 -0
  7. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_questionnaire_response_save_test.rb +31 -0
  8. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb +89 -0
  9. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/prepopulation_attestation_test.rb +29 -0
  10. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/prepopulation_override_attestation_test.rb +30 -0
  11. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/rendering_enabled_questions_attestation_test.rb +30 -0
  12. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_full_ehr_questionnaire_workflow_group.rb +19 -0
  13. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_package_group.rb +16 -0
  14. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_attestation_test.rb +32 -0
  15. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_group.rb +14 -0
  16. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_response_group.rb +23 -0
  17. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_response_save_test.rb +31 -0
  18. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_smart_app_questionnaire_workflow_group.rb +22 -0
  19. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_test.rb +36 -0
  20. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_package_request_validation_test.rb +35 -0
  21. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +28 -0
  22. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +30 -0
  23. data/lib/davinci_dtr_test_kit/cql_test.rb +387 -0
  24. data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +127 -0
  25. data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +118 -0
  26. data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +55 -0
  27. data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +39 -0
  28. data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +104 -0
  29. data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +180 -0
  30. data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +85 -0
  31. data/lib/davinci_dtr_test_kit/ext/inferno_core/record_response_route.rb +98 -0
  32. data/lib/davinci_dtr_test_kit/ext/inferno_core/request.rb +19 -0
  33. data/lib/davinci_dtr_test_kit/ext/inferno_core/runnable.rb +35 -0
  34. data/lib/davinci_dtr_test_kit/fixture_loader.rb +99 -0
  35. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +170 -0
  36. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +175 -0
  37. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +140 -0
  38. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json +95 -0
  39. data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_dinner_order_static.json +283 -0
  40. data/lib/davinci_dtr_test_kit/fixtures/dinner_static/questionnaire_response_dinner_order_static.json +170 -0
  41. data/lib/davinci_dtr_test_kit/fixtures/pre_populated_questionnaire_response.json +581 -0
  42. data/lib/davinci_dtr_test_kit/fixtures/questionnaire_package.json +2121 -0
  43. data/lib/davinci_dtr_test_kit/fixtures.rb +65 -0
  44. data/lib/davinci_dtr_test_kit/mock_ehr.rb +72 -0
  45. data/lib/davinci_dtr_test_kit/mock_payer.rb +142 -0
  46. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_libraries_test.rb +19 -0
  47. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_expressions_test.rb +20 -0
  48. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_extensions_test.rb +19 -0
  49. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +20 -0
  50. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_extensions_test.rb +19 -0
  51. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_group.rb +88 -0
  52. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_test.rb +41 -0
  53. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_request_validation_test.rb +44 -0
  54. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_bundles_validation_test.rb +40 -0
  55. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_search_validation_test.rb +42 -0
  56. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +49 -0
  57. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_request_validation_test.rb +61 -0
  58. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_complete_test.rb +17 -0
  59. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_validation_test.rb +43 -0
  60. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_static_group.rb +51 -0
  61. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_libraries_test.rb +19 -0
  62. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_expressions_test.rb +20 -0
  63. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_extensions_test.rb +19 -0
  64. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_test.rb +33 -0
  65. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_request_validation_test.rb +46 -0
  66. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +50 -0
  67. data/lib/davinci_dtr_test_kit/tags.rb +8 -0
  68. data/lib/davinci_dtr_test_kit/urls.rb +50 -0
  69. data/lib/davinci_dtr_test_kit/validation_test.rb +72 -0
  70. data/lib/davinci_dtr_test_kit/version.rb +5 -0
  71. data/lib/davinci_dtr_test_kit.rb +4 -0
  72. metadata +132 -0
@@ -0,0 +1,65 @@
1
+ require_relative 'fixture_loader'
2
+
3
+ module DaVinciDTRTestKit
4
+ module Fixtures
5
+ DATA_REQUIREMENT_ANSWERS = { 'RAD Prepopulation' => '3.1' }.freeze
6
+
7
+ def get_questionnaire_package_for_group_id(group_id)
8
+ FixtureLoader.instance.questionnaire_package_for_group_id(group_id)
9
+ end
10
+
11
+ def find_questionnaire_instance_for_test_id(test_id)
12
+ canonical_url = find_questionnaire_canonical_for_test_id(test_id)
13
+ return unless canonical_url.present?
14
+
15
+ package = get_questionnaire_packcage_for_canonical(canonical_url)
16
+ return unless package.present?
17
+
18
+ questionnaire = nil
19
+ package.entry.find do |entry|
20
+ questionnaire = entry.resource if entry.resource.is_a?(FHIR::Questionnaire)
21
+ end
22
+ questionnaire
23
+ end
24
+
25
+ def find_questionnaire_canonical_for_test_id(test_id)
26
+ canonical_url = nil
27
+
28
+ # test_id is of the form [suite id]-[group id 1]-...-[group id n]-[test id]
29
+ groups = test_id.split('-')[1..-2] # first is suite, last is test, we want groups
30
+ groups.each do |one_group_id|
31
+ next if canonical_url.present?
32
+
33
+ canonical_url = get_questionnaire_canonical_for_group_id(one_group_id)
34
+ end
35
+
36
+ canonical_url
37
+ end
38
+
39
+ def get_questionnaire_canonical_for_group_id(group_id)
40
+ FixtureLoader.instance.questionnaire_canonical_for_group_id(group_id)
41
+ end
42
+
43
+ def get_questionnaire_packcage_for_canonical(url)
44
+ FixtureLoader.instance.questionnaire_package_for_canonical(url)
45
+ end
46
+
47
+ def find_questionnaire_response_for_test_id(test_id)
48
+ questionnaire_response = nil
49
+
50
+ # test_id is of the form [suite id]-[group id 1]-...-[group id n]-[test id]
51
+ groups = test_id.split('-')[1..-2] # first is suite, last is test, we want groups
52
+ groups.each do |one_group_id|
53
+ next if questionnaire_response.present?
54
+
55
+ questionnaire_response = get_questionnaire_response_for_group_id(one_group_id)
56
+ end
57
+
58
+ questionnaire_response
59
+ end
60
+
61
+ def get_questionnaire_response_for_group_id(group_id)
62
+ FixtureLoader.instance.questionnaire_response_for_group_id(group_id)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaVinciDTRTestKit
4
+ module MockEHR
5
+ RESOURCE_SERVER_BASE = ENV.fetch('FHIR_REFERENCE_SERVER')
6
+ RESOURCE_SERVER_BEARER_TOKEN = 'SAMPLE_TOKEN'
7
+
8
+ RESPONSE_HEADERS = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }.freeze
9
+
10
+ def resource_server_client
11
+ return @resource_server_client if @resource_server_client
12
+
13
+ client = FHIR::Client.new(RESOURCE_SERVER_BASE)
14
+ client.set_bearer_token(RESOURCE_SERVER_BEARER_TOKEN)
15
+ @resource_server_client = client
16
+ end
17
+
18
+ def metadata_handler(_env)
19
+ cs = resource_server_client.capability_statement
20
+ if cs.present?
21
+ [200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [cs.to_json]]
22
+ else
23
+ [500, {}, ['Unexpected error occurred while fetching metadata']]
24
+ end
25
+ end
26
+
27
+ def get_fhir_resource(request, _test = nil, _test_result = nil)
28
+ resource_type, id = resource_type_and_id_from_url(request.url)
29
+ request.response_headers = RESPONSE_HEADERS
30
+
31
+ begin
32
+ fhir_class = FHIR.const_get(resource_type)
33
+ rescue NameError
34
+ resource_type = nil
35
+ end
36
+
37
+ if resource_type.present?
38
+ response = if id.present?
39
+ resource_server_client.read(fhir_class, id)
40
+ else
41
+ resource_server_client.search(fhir_class, search: { parameters: request.query_parameters })
42
+ end
43
+ request.status = response.code
44
+ request.response_body = response.body
45
+ else
46
+ request.status = 400
47
+ request.response_headers = { 'Content-Type': 'application/json' }
48
+ request.response_body = FHIR::OperationOutcome.new(
49
+ issue: FHIR::OperationOutcome::Issue.new(severity: 'warning', code: 'not-supported',
50
+ details: FHIR::CodeableConcept.new(
51
+ text: 'No recognized resource type in URL'
52
+ ))
53
+ ).to_json
54
+ end
55
+ end
56
+
57
+ def questionnaire_response_response(request, _test = nil, _test_result = nil)
58
+ request.status = 201
59
+ request.response_headers = RESPONSE_HEADERS
60
+ request.response_body = request.request_body
61
+ end
62
+
63
+ # Pull resource type and ID from url
64
+ # e.g. http://example.org/fhir/Patient/123 -> ['Patient', '123']
65
+ # @private
66
+ def resource_type_and_id_from_url(url)
67
+ path = url.split('?').first.split('/fhir/').second
68
+ path.sub!(%r{/$}, '')
69
+ path.split('/')
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'fixtures'
4
+
5
+ module DaVinciDTRTestKit
6
+ module MockPayer
7
+ include Fixtures
8
+
9
+ RESPONSE_HEADERS = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }.freeze
10
+
11
+ def token_response(request, _test = nil, _test_result = nil)
12
+ # Placeholder for a more complete mock token endpoint
13
+ request.response_body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json
14
+ request.status = 200
15
+ end
16
+
17
+ def questionnaire_package_response(request, _test = nil, test_result = nil)
18
+ request.status = 200
19
+ request.response_headers = RESPONSE_HEADERS
20
+ request.response_body = build_package_questionnaire_response(request, test_result.test_id).to_json
21
+ end
22
+
23
+ def payer_questionnaire_response(request, _test = nil, test_result = nil)
24
+ endpoint_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'custom_endpoint' }
25
+ url_input = JSON.parse(test_result.input_json).find { |input| input['name'] == 'url' }
26
+ client = FHIR::Client.new(url_input['value'])
27
+ client.default_json
28
+ endpoint = endpoint_input['value'].nil? ? '/Questionnaire/$questionnaire-package' : endpoint_input['value']
29
+ payer_response = client.send(:post, endpoint, JSON.parse(request.request_body),
30
+ { 'Content-Type' => 'application/json' })
31
+
32
+ request.status = 200
33
+ request.response_headers = RESPONSE_HEADERS
34
+ request.response_body = payer_response.response[:body].to_s
35
+ end
36
+
37
+ def questionnaire_next_response(request, _test = nil, test_result = nil)
38
+ url_endpoint = JSON.parse(test_result.input_json).find { |input| input['name'] == 'url' }
39
+ client = FHIR::Client.new(url_endpoint['value'])
40
+ client.default_json
41
+ payer_response = client.send(:post, '/Questionnaire/$next-question', JSON.parse(request.request_body),
42
+ { 'Content-Type' => 'application/json' })
43
+
44
+ request.status = 200
45
+ request.response_headers = RESPONSE_HEADERS
46
+
47
+ request.response_body = payer_response.response[:body]
48
+ end
49
+
50
+ def extract_client_id(request)
51
+ URI.decode_www_form(request.request_body).to_h['client_id']
52
+ end
53
+
54
+ # Header expected to be a bearer token of the form "Bearer: <token>"
55
+ def extract_bearer_token(request)
56
+ request.request_header('Authorization')&.value&.split&.last
57
+ end
58
+
59
+ def extract_token_from_query_params(request)
60
+ request.query_parameters['token']
61
+ end
62
+
63
+ def test_resumes?(test)
64
+ !test.config.options[:accepts_multiple_requests]
65
+ end
66
+
67
+ def build_package_questionnaire_response(request, test_id)
68
+ test_questionnaire_canonical = find_questionnaire_canonical_for_test_id(test_id)
69
+ test_questionnaire_loaded = false
70
+
71
+ bundles = []
72
+ issues = []
73
+
74
+ # first try the parameters - load the questionnaire specified by the questionnaire parameter
75
+ input_parameters = FHIR.from_contents(request.request_body)
76
+ input_parameters.parameter.each do |one_parameter|
77
+ next unless one_parameter.name == 'questionnaire'
78
+ next unless one_parameter.valueCanonical
79
+
80
+ # don't load test questionnaire if it is also specified explicitly
81
+ test_questionnaire_loaded = true if one_parameter.valueCanonical == test_questionnaire_canonical
82
+
83
+ add_questionnaire_canonical_to_response(one_parameter.valueCanonical, bundles, issues)
84
+ end
85
+
86
+ unless test_questionnaire_loaded
87
+ if test_questionnaire_canonical
88
+ add_questionnaire_canonical_to_response(test_questionnaire_canonical, bundles, issues)
89
+
90
+ elsif bundles.empty?
91
+ # no questionnaire for this test ...
92
+ operation_outcome_issue = FHIR::OperationOutcome::Issue.new
93
+ operation_outcome_issue.severity = 'error'
94
+ operation_outcome_issue.code = 'business-rule'
95
+ details = FHIR::CodeableConcept.new
96
+ details.text = "no questionnaire found for test #{test_id}"
97
+ operation_outcome_issue.details = details
98
+ issues << operation_outcome_issue
99
+ end
100
+ end
101
+
102
+ build_package_questionnaire_response_from_lists(bundles, issues)
103
+ end
104
+
105
+ def add_questionnaire_canonical_to_response(questionnaire_canonical, bundles, issues)
106
+ questionnaire_bundle = get_questionnaire_packcage_for_canonical(questionnaire_canonical)
107
+
108
+ if questionnaire_bundle
109
+ bundles << questionnaire_bundle
110
+ else
111
+ operation_outcome_issue = FHIR::OperationOutcome::Issue.new
112
+ operation_outcome_issue.severity = 'warning'
113
+ operation_outcome_issue.code = 'value'
114
+ details = FHIR::CodeableConcept.new
115
+ details.text = "Questionnaire Canonical #{questionnaire_canonical} does not exist"
116
+ operation_outcome_issue.details = details
117
+ issues << operation_outcome_issue
118
+ end
119
+ end
120
+
121
+ def build_package_questionnaire_response_from_lists(bundles, issues)
122
+ response = FHIR::Parameters.new
123
+ bundles.each do |one_bundle|
124
+ return_param = FHIR::Parameters::Parameter.new
125
+ return_param.name = 'return'
126
+ return_param.resource = one_bundle
127
+ response.parameter << return_param
128
+ end
129
+
130
+ unless issues.empty?
131
+ outcome = FHIR::OperationOutcome.new
132
+ outcome.issue = issues
133
+ outcome_param = FHIR::Parameters::Parameter.new
134
+ outcome_param.name = 'outcome'
135
+ outcome_param.resource = outcome
136
+ response.parameter << outcome_param
137
+ end
138
+
139
+ response
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../cql_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormLibrariesTest < Inferno::Test
4
+ include DaVinciDTRTestKit::CQLTest
5
+
6
+ id :dtr_v201_payer_adaptive_form_libraries_test
7
+ title 'Parameters contain libraries necessary for pre-population'
8
+ description %(
9
+ Inferno check that the payer response contains no duplicate library names
10
+ and that libraries contain cql and elm data.
11
+ )
12
+
13
+ run do
14
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
15
+ skip_if scratch[:adaptive_responses].nil?, 'No questionnaire bundle returned.'
16
+ check_libraries(scratch[:adaptive_responses])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../cql_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormExpressionsTest < Inferno::Test
4
+ include DaVinciDTRTestKit::CQLTest
5
+
6
+ id :dtr_v201_payer_adaptive_form_expressions_test
7
+ title 'Questionnaire(s) contains items with expressions necessary for pre-population'
8
+ description %(
9
+ Inferno checks that the payer server response has appropriate expressions and that expressions are
10
+ written in cql.
11
+ )
12
+
13
+ run do
14
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
15
+ skip_if scratch[:adaptive_responses].nil?, 'No questionnaire bundle returned.'
16
+ questionnaire_items_test(scratch[:adaptive_responses], final_cql_test: false)
17
+ scratch[:adaptive_responses] = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../cql_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormExtensionsTest < Inferno::Test
4
+ include DaVinciDTRTestKit::CQLTest
5
+
6
+ id :dtr_v201_payer_adaptive_form_extensions_test
7
+ title 'Questionnaire(s) contains extensions necessary for pre-population'
8
+ description %(
9
+ Inferno checks that the payer server response has appropriate extensions and references to libraries within
10
+ those extensions.
11
+ )
12
+
13
+ run do
14
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
15
+ skip_if scratch[:adaptive_responses].nil?, 'No questionnaire bundle returned.'
16
+ questionnaire_extensions_test(scratch[:adaptive_responses])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../cql_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerStaticFormExpressionsTest < Inferno::Test
4
+ include DaVinciDTRTestKit::CQLTest
5
+
6
+ id :dtr_v201_payer_adaptive_next_form_expressions_test
7
+ title 'Questionnaire(s) contains items with expressions necessary for pre-population'
8
+ description %(
9
+ Inferno checks that the payer server response has appropriate expressions and that expressions are
10
+ written in cql.
11
+ )
12
+
13
+ run do
14
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
15
+ skip_if scratch[:next_responses].nil?, 'No questionnaires returned.'
16
+ questionnaire_items_test(scratch[:next_responses], final_cql_test: true)
17
+ scratch[:next_responses] = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../cql_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerStaticFormExtensionsTest < Inferno::Test
4
+ include DaVinciDTRTestKit::CQLTest
5
+
6
+ id :dtr_v201_payer_adaptive_next_form_extensions_test
7
+ title 'Questionnaire(s) contains extensions necessary for pre-population'
8
+ description %(
9
+ Inferno checks that the payer server response has appropriate extensions and references to libraries within
10
+ those extensions.
11
+ )
12
+
13
+ run do
14
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
15
+ skip_if scratch[:next_responses].nil?, 'No questionnaires returned.'
16
+ questionnaire_extensions_test(scratch[:next_responses])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'payer_server_adaptive_request_test'
2
+ require_relative 'payer_server_adaptive_request_validation_test'
3
+ require_relative 'payer_server_adaptive_response_bundles_validation_test'
4
+ require_relative 'payer_server_adaptive_response_search_validation_test'
5
+ require_relative 'payer_server_adaptive_response_validation_test'
6
+ require_relative 'payer_server_next_request_validation_test'
7
+ require_relative 'payer_server_next_response_validation_test'
8
+ require_relative 'payer_server_next_response_complete_test'
9
+ require_relative 'adaptive_form_libraries_test'
10
+ require_relative 'adaptive_form_questionnaire_extensions_test'
11
+ require_relative 'adaptive_form_questionnaire_expressions_test'
12
+ require_relative 'adaptive_next_questionnaire_extensions_test'
13
+ require_relative 'adaptive_next_questionnaire_expressions_test'
14
+
15
+ module DaVinciDTRTestKit
16
+ class DTRPayerServerAdaptiveQuestionnairePackageGroup < Inferno::TestGroup
17
+ title 'Adaptive Questionnaire Retrieval'
18
+ description %(
19
+
20
+ ## Background
21
+
22
+ These tests validate the ability of the Payer Server to provide an adaptive questionnaire
23
+ following requests from the DTR Client. Resources are validated as specified
24
+ in the DTR v2.0.1 Implementation Guide.
25
+
26
+ There are several input options, which correspond to different workflows. No inputs are explicitly required,
27
+ but all inputs for at least one work flow must be provided to complete testing (see below).
28
+
29
+ ## Testing Work Flow Options
30
+
31
+ - Enter the `FHIR Server Base Url` and `Access Token` if you are connecting a client that will provide
32
+ inferno with requests to be tested and sent to the server under test. These inputs must align with
33
+ the configuration of the DTR client being used to provide requests. Optionally,
34
+ an `Endpoint for a Particular Adaptive Resource` can also be provided, which should include the ID
35
+ of the resource of interest (e.g., `/Questionnaire/HomeOxygenTherapyAdditional/$questionnaire-package`).
36
+
37
+ - Enter the `Initial Adaptive Questionnaire Request` and a set of `Next Question Requests`, in addition to the
38
+ `FHIR Server Base Url` pointing to the payer server,
39
+ to provide the json requests manually, rather than relying on a DTR client.
40
+ )
41
+ id :payer_server_adaptive_questionnaire
42
+ run_as_group
43
+
44
+ input :initial_adaptive_questionnaire_request,
45
+ optional: true,
46
+ title: 'Initial Adaptive Questionnaire Request',
47
+ description: 'Manual Flow',
48
+ type: 'textarea'
49
+
50
+ input :next_question_requests,
51
+ optional: true,
52
+ title: 'Next Question Requests',
53
+ description: 'Manual Flow',
54
+ type: 'textarea'
55
+
56
+ input_order :retrieval_method,
57
+ :url,
58
+ :custom_endpoint,
59
+ :access_token,
60
+ :initial_adaptive_questionnaire_request,
61
+ :next_question_requests,
62
+ :credentials
63
+
64
+ # receive client request
65
+ test from: :payer_server_questionnaire_request,
66
+ receives_request: :client_questionnaire_package
67
+
68
+ # optionally validate client request
69
+ test from: :payer_server_adaptive_questionnaire_request_validation
70
+
71
+ # pass request to payer server, validate questionnaire response
72
+ test from: :payer_server_adaptive_response_validation_test
73
+ test from: :dtr_v201_payer_adaptive_form_libraries_test
74
+ test from: :dtr_v201_payer_adaptive_form_extensions_test
75
+ test from: :dtr_v201_payer_adaptive_form_expressions_test
76
+ test from: :payer_server_adaptive_response_bundles_validation_test
77
+ test from: :payer_server_adaptive_response_search_validation_test
78
+
79
+ # optionally validate the client request
80
+ test from: :payer_server_next_request_validation
81
+
82
+ # pass request to payer server, validate adaptive questionnaire response
83
+ test from: :payer_server_next_response_validation_test
84
+ test from: :dtr_v201_payer_adaptive_next_form_extensions_test
85
+ test from: :dtr_v201_payer_adaptive_next_form_expressions_test
86
+ test from: :payer_server_adaptive_completion_test
87
+ end
88
+ end
@@ -0,0 +1,41 @@
1
+ require_relative '../urls'
2
+
3
+ module DaVinciDTRTestKit
4
+ class AdaptiveFormTest < Inferno::Test
5
+ include URLs
6
+ title 'Confirm the client completes the DTR Adaptive Questionnaire work flow'
7
+ description %(
8
+ Inferno will wait for a DTR questionnaire package request from the client. Upon receipt, Inferno will generate and
9
+ send a response.
10
+ )
11
+ id :payer_server_questionnaire_request
12
+ config options: { accepts_multiple_requests: true }
13
+
14
+ run do
15
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
16
+ pass_if !(initial_adaptive_questionnaire_request.nil? || next_question_requests.nil?),
17
+ 'Proceeding with manually provided resources.'
18
+ skip_if access_token.nil?, 'Please provide an access token or all request resources as inputs.'
19
+ wait(
20
+ identifier: access_token,
21
+ message: %(
22
+ **Adaptive Form Testing**
23
+
24
+ Invoke the DTR Questionnaire Package operation by sending a POST request to
25
+
26
+ `#{questionnaire_package_url}`
27
+
28
+ and Next Question operations by sending POST requests to
29
+
30
+ `#{next_url}`
31
+
32
+
33
+ A set of questionnaire packages generated by Inferno will be returned. Each of the following tests
34
+ will validate all resources, marking messages in the order they are received.
35
+
36
+ **[click here](#{resume_pass_url}?token=#{access_token})** when the adaptive forms have been completed.
37
+ )
38
+ )
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../validation_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormRequestTest < Inferno::Test
4
+ include URLs
5
+ include DaVinciDTRTestKit::ValidationTest
6
+ title '[USER INPUT VALIDATION] Questionnaire Package request is valid'
7
+ description %(
8
+ This test validates the conformance of the client's request to the
9
+ [DTR Questionnaire Package Input Parameters](http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters)
10
+ structure.
11
+
12
+ It verifies the presence of mandatory elements and that elements with required bindings contain appropriate
13
+ values. CodeableConcept element bindings will fail if none of their codings have a code/system belonging
14
+ to the bound ValueSet. Quantity, Coding, and code element bindings will fail if their code/system are not found in
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
+ )
20
+ id :payer_server_adaptive_questionnaire_request_validation
21
+
22
+ run do
23
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
24
+ if initial_adaptive_questionnaire_request.nil?
25
+ resources = load_tagged_requests(QUESTIONNAIRE_TAG)
26
+ using_manual_entry = false
27
+ else
28
+ resources = initial_adaptive_questionnaire_request
29
+ using_manual_entry = true
30
+ end
31
+ skip_if resources.nil?, 'No request resources to validate.'
32
+ perform_request_validation_test(
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
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../validation_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormResponseBundlesTest < Inferno::Test
4
+ include DaVinciDTRTestKit::ValidationTest
5
+ id :payer_server_adaptive_response_bundles_validation_test
6
+ title 'Validate that the adaptive response contains valid Questionnaire Bundle resources'
7
+ description %(
8
+ This test ensures that the payer's response includes a resource that conforms to the the
9
+ [DTR Quesitonnaire Bundle](http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle)
10
+ structure.
11
+
12
+ It verifies the presence of mandatory elements and that elements with required bindings contain appropriate
13
+ values. CodeableConcept element bindings will fail if none of their codings have a code/system belonging
14
+ to the bound ValueSet. Quantity, Coding, and code element bindings will fail if their code/system are not found in
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
+ )
20
+
21
+ run do
22
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
23
+ test_passed = false
24
+ profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle'
25
+ assert !scratch[:adaptive_responses].nil?, 'No resources to validate.'
26
+ scratch[:adaptive_responses].each_with_index do |resource, index|
27
+ fhir_resource = FHIR.from_contents(resource.response[:body])
28
+ fhir_resource.parameter.each do |param|
29
+ resource_is_valid = validate_resource(param.resource, :bundle, profile_url, index)
30
+ test_passed = true if resource_is_valid
31
+ rescue StandardError
32
+ next
33
+ end
34
+ end
35
+ raise tests_failed[profile_url][0] if !test_passed && !tests_failed[profile_url].blank?
36
+
37
+ messages.clear if test_passed
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../validation_test'
2
+ module DaVinciDTRTestKit
3
+ class PayerAdaptiveFormResponseSearchTest < Inferno::Test
4
+ include DaVinciDTRTestKit::ValidationTest
5
+ id :payer_server_adaptive_response_search_validation_test
6
+ title 'Validate that the adaptive response contains valid a Adaptive Form Search resource'
7
+ description %(
8
+ This test validates the conformance of the payer's response to the
9
+ [DTR Questionnaire for Adaptive Form Search](http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt-search)
10
+ structure.
11
+
12
+ It verifies the presence of mandatory elements and that elements with required bindings contain appropriate
13
+ values. CodeableConcept element bindings will fail if none of their codings have a code/system belonging
14
+ to the bound ValueSet. Quantity, Coding, and code element bindings will fail if their code/system are not found in
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
+ )
20
+
21
+ run do
22
+ skip_if retrieval_method == 'Static', 'Performing only static flow tests - only one flow is required.'
23
+ test_passed = false
24
+ profile_url = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt-search'
25
+ assert !scratch[:adaptive_responses].nil?, 'No resources to validate.'
26
+ scratch[:adaptive_responses].each_with_index do |resource, index|
27
+ fhir_resource = FHIR.from_contents(resource.response[:body])
28
+ fhir_resource.parameter.each do |param|
29
+ param.resource.entry.each do |entry|
30
+ resource_is_valid = validate_resource(entry.resource, :questionnaire, profile_url, index)
31
+ test_passed = true if resource_is_valid
32
+ end
33
+ rescue StandardError
34
+ next
35
+ end
36
+ end
37
+ raise tests_failed[profile_url][0] if !test_passed && !tests_failed[profile_url].blank?
38
+
39
+ messages.clear if test_passed
40
+ end
41
+ end
42
+ end