davinci_dtr_test_kit 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,85 @@
1
+ require_relative 'ext/inferno_core/runnable'
2
+ require_relative 'ext/inferno_core/record_response_route'
3
+ require_relative 'ext/inferno_core/request'
4
+ require_relative 'auth_groups/oauth2_authentication_group'
5
+ require_relative 'client_groups/resp_assist_device/dtr_smart_app_questionnaire_workflow_group'
6
+ require_relative 'client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group'
7
+ require_relative 'client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group'
8
+ require_relative 'mock_payer'
9
+ require_relative 'mock_ehr'
10
+ require_relative 'version'
11
+
12
+ module DaVinciDTRTestKit
13
+ class DTRSmartAppSuite < Inferno::TestSuite
14
+ extend MockPayer
15
+ extend MockEHR
16
+
17
+ id :dtr_smart_app
18
+ title 'Da Vinci DTR SMART App Test Suite'
19
+ description File.read(File.join(__dir__, 'docs', 'dtr_smart_app_suite_description_v201.md'))
20
+
21
+ version VERSION
22
+
23
+ # All FHIR validation requsets will use this FHIR validator
24
+ validator do
25
+ url ENV.fetch('VALIDATOR_URL')
26
+ end
27
+
28
+ allow_cors QUESTIONNAIRE_PACKAGE_PATH, QUESTIONNAIRE_RESPONSE_PATH, FHIR_RESOURCE_PATH, FHIR_SEARCH_PATH
29
+
30
+ route(:get, '/fhir/metadata', method(:metadata_handler))
31
+
32
+ record_response_route :post, TOKEN_PATH, 'dtr_auth', method(:token_response) do |request|
33
+ DTRSmartAppSuite.extract_client_id(request)
34
+ end
35
+
36
+ record_response_route :post, QUESTIONNAIRE_PACKAGE_PATH, QUESTIONNAIRE_PACKAGE_TAG,
37
+ method(:questionnaire_package_response), resumes: ->(_) { false } do |request|
38
+ DTRSmartAppSuite.extract_bearer_token(request)
39
+ end
40
+
41
+ record_response_route :post, QUESTIONNAIRE_RESPONSE_PATH, 'dtr_smart_app_questionnaire_response',
42
+ method(:questionnaire_response_response) do |request|
43
+ DTRSmartAppSuite.extract_bearer_token(request)
44
+ end
45
+
46
+ record_response_route :get, FHIR_RESOURCE_PATH, SMART_APP_EHR_REQUEST_TAG, method(:get_fhir_resource),
47
+ resumes: ->(_) { false } do |request|
48
+ DTRSmartAppSuite.extract_bearer_token(request)
49
+ end
50
+
51
+ record_response_route :get, FHIR_SEARCH_PATH, SMART_APP_EHR_REQUEST_TAG, method(:get_fhir_resource),
52
+ resumes: ->(_) { false } do |request|
53
+ DTRSmartAppSuite.extract_bearer_token(request)
54
+ end
55
+
56
+ resume_test_route :get, RESUME_PASS_PATH do |request|
57
+ DTRSmartAppSuite.extract_token_from_query_params(request)
58
+ end
59
+
60
+ resume_test_route :get, RESUME_FAIL_PATH, result: 'fail' do |request|
61
+ DTRSmartAppSuite.extract_token_from_query_params(request)
62
+ end
63
+
64
+ group from: :oauth2_authentication
65
+ group do
66
+ id :dtr_smart_app_basic_workflows
67
+ title 'Basic Workflows'
68
+ description %(
69
+ Tests in this group validate that the client can complete basic DTR workflows
70
+ )
71
+
72
+ group from: :dtr_smart_app_static_dinner_questionnaire_workflow
73
+ # group from: :dtr_smart_app_adaptive_dinner_questionnaire_workflow - TODO
74
+ end
75
+ group do
76
+ id :dtr_smart_app_questionnaire_functionality
77
+ title 'Questionnaire Functionality Coverage'
78
+ description %(
79
+ Tests in this group validate that the client can complete additional DTR workflows
80
+ covering additional must support features of questionnaires.
81
+ )
82
+ group from: :dtr_smart_app_questionnaire_workflow
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,98 @@
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
@@ -0,0 +1,19 @@
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
@@ -0,0 +1,35 @@
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
@@ -0,0 +1,99 @@
1
+ require 'singleton'
2
+ require 'fhir_models'
3
+
4
+ module DaVinciDTRTestKit
5
+ class FixtureLoader
6
+ include Singleton
7
+
8
+ def initialize
9
+ # list of lists
10
+ # - first entry is the path to a file containing a Questionnaire Bundle (not Parameters)
11
+ # - second entry is the path to a file containing a Populated QuestionnaireResponse
12
+ # for use in validation.
13
+ # - third entry is a list of group id within which this questionnaire should be used and
14
+ # will be returned for any $questionnaire-package calls. This association of a questionnaire
15
+ # with a specific test is Inferno's simulated version of payer business logic.
16
+ questionnaires_to_load =
17
+ [
18
+ [
19
+ 'fixtures/questionnaire_package.json',
20
+ 'fixtures/pre_populated_questionnaire_response.json',
21
+ ['dtr_smart_app_questionnaire_workflow', 'dtr_full_ehr_questionnaire_workflow']
22
+ ],
23
+ [
24
+ 'fixtures/dinner_static/questionnaire_dinner_order_static.json',
25
+ 'fixtures/dinner_static/questionnaire_response_dinner_order_static.json',
26
+ ['dtr_smart_app_static_dinner_questionnaire_workflow']
27
+ ],
28
+ [
29
+ 'fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json',
30
+ '',
31
+ ['dtr_smart_app_adaptive_dinner_questionnaire_workflow']
32
+ ]
33
+ ]
34
+
35
+ questionnaires_to_load.each do |questionnaire_details|
36
+ init_questionnaire_package_and_response(questionnaire_details[0], questionnaire_details[1],
37
+ questionnaire_details[2])
38
+ end
39
+ end
40
+
41
+ def canonical_to_questionnaire_package_map
42
+ @canonical_to_questionnaire_package_map ||= {}
43
+ end
44
+
45
+ def questionnaire_package_for_canonical(url)
46
+ @canonical_to_questionnaire_package_map[url]
47
+ end
48
+
49
+ def group_id_to_questionnaire_canonical_map
50
+ @group_id_to_questionnaire_canonical_map ||= {}
51
+ end
52
+
53
+ def questionnaire_canonical_for_group_id(group_id)
54
+ group_id_to_questionnaire_canonical_map[group_id]
55
+ end
56
+
57
+ def questionnaire_package_for_group_id(group_id)
58
+ canonical = questionnaire_canonical_for_group_id(group_id)
59
+ return unless canonical
60
+
61
+ @canonical_to_questionnaire_package_map[canonical]
62
+ end
63
+
64
+ def group_id_to_questionnaire_response_map
65
+ @group_id_to_questionnaire_response_map ||= {}
66
+ end
67
+
68
+ def questionnaire_response_for_group_id(group_id)
69
+ group_id_to_questionnaire_response_map[group_id]
70
+ end
71
+
72
+ def init_questionnaire_package_and_response(package_file, response_file = nil, covered_groups = nil)
73
+ package_json = File.read(File.join(__dir__, package_file))
74
+ package = FHIR.from_contents(package_json)
75
+ url = get_url_for_questionnaire(package)
76
+
77
+ canonical_to_questionnaire_package_map[url] = package if url
78
+ covered_groups&.each do |group|
79
+ group_id_to_questionnaire_canonical_map[group] = url
80
+ end
81
+
82
+ if response_file.present?
83
+ response_json = File.read(File.join(__dir__, response_file))
84
+ response = FHIR.from_contents(response_json)
85
+
86
+ covered_groups&.each do |group|
87
+ group_id_to_questionnaire_response_map[group] = response
88
+ end
89
+
90
+ end
91
+
92
+ package
93
+ end
94
+
95
+ def get_url_for_questionnaire(questionnaire_bundle)
96
+ questionnaire_bundle.entry[0].resource.url
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,170 @@
1
+ {
2
+ "resourceType": "Questionnaire",
3
+ "id": "DinnerOrderAdaptive",
4
+ "meta": {
5
+ "profile": [
6
+ "http://hl7.org/fhir/StructureDefinition/cqf-questionnaire",
7
+ "http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt"
8
+ ]
9
+ },
10
+ "extension": [
11
+ {
12
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-questionnaireAdaptive",
13
+ "valueBoolean": true
14
+ },
15
+ {
16
+ "url": "http://hl7.org/fhir/StructureDefinition/cqf-library",
17
+ "valueCanonical": "https://madie.cms.gov/Library/DTRTest"
18
+ }
19
+ ],
20
+ "name": "DinnerOrderAdaptive",
21
+ "title": "Dinner Order (Adaptive)",
22
+ "status": "draft",
23
+ "subjectType": [
24
+ "Patient"
25
+ ],
26
+ "date": "2024-05-06",
27
+ "publisher": "Inferno",
28
+ "item": [
29
+ {
30
+ "extension": [
31
+ {
32
+ "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
33
+ "valueCodeableConcept": {
34
+ "coding": [
35
+ {
36
+ "system": "http://hl7.org/fhir/questionnaire-item-control",
37
+ "code": "gtable"
38
+ }
39
+ ]
40
+ }
41
+ }
42
+ ],
43
+ "linkId": "PBD",
44
+ "text": "Patient Information",
45
+ "type": "group",
46
+ "item": [
47
+ {
48
+ "extension": [
49
+ {
50
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
51
+ "valueExpression": {
52
+ "language": "text/cql",
53
+ "expression": "\"DTRTest\".LastName"
54
+ }
55
+ }
56
+ ],
57
+ "linkId": "PBD.1",
58
+ "text": "Last Name:",
59
+ "type": "string",
60
+ "required": true
61
+ },
62
+ {
63
+ "extension": [
64
+ {
65
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
66
+ "valueExpression": {
67
+ "language": "text/cql",
68
+ "expression": "\"DTRTest\".FirstName"
69
+ }
70
+ }
71
+ ],
72
+ "linkId": "PBD.2",
73
+ "text": "First Name:",
74
+ "type": "string",
75
+ "required": true
76
+ }
77
+ ]
78
+ },
79
+ {
80
+ "extension": [
81
+ {
82
+ "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
83
+ "valueCodeableConcept": {
84
+ "coding": [
85
+ {
86
+ "system": "http://hl7.org/fhir/questionnaire-item-control",
87
+ "code": "gtable"
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ ],
93
+ "linkId": "LOC",
94
+ "text": "Patient's Location",
95
+ "type": "group",
96
+ "item": [
97
+ {
98
+ "extension": [
99
+ {
100
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
101
+ "valueExpression": {
102
+ "language": "text/cql",
103
+ "expression": "\"DTRTest\".FirstLocationDescription"
104
+ }
105
+ }
106
+ ],
107
+ "linkId": "LOC.1",
108
+ "text": "Location",
109
+ "type": "string",
110
+ "required": true
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ "linkId": "3",
116
+ "text": "Dinner Order",
117
+ "type": "group",
118
+ "item": [
119
+ {
120
+ "linkId": "3.1",
121
+ "text": "What would you like for dinner?",
122
+ "type": "choice",
123
+ "required": true,
124
+ "answerOption": [
125
+ {
126
+ "valueCoding": {
127
+ "code": "Hamburger"
128
+ }
129
+ },
130
+ {
131
+ "valueCoding": {
132
+ "code": "Bean Burrito"
133
+ }
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "linkId": "3.2.b",
139
+ "text": "What would you like on your bean burrito?",
140
+ "type": "choice",
141
+ "required": false,
142
+ "repeats": true,
143
+ "answerOption": [
144
+ {
145
+ "valueCoding": {
146
+ "code": "Cheese"
147
+ }
148
+ },
149
+ {
150
+ "valueCoding": {
151
+ "code": "Pico de Gallo"
152
+ }
153
+ },
154
+ {
155
+ "valueCoding": {
156
+ "code": "Guacamole"
157
+ }
158
+ }
159
+ ]
160
+ },
161
+ {
162
+ "linkId": "3.3",
163
+ "text": "Any special requests?",
164
+ "type": "string",
165
+ "required": false
166
+ }
167
+ ]
168
+ }
169
+ ]
170
+ }
@@ -0,0 +1,175 @@
1
+ {
2
+ "resourceType": "Questionnaire",
3
+ "id": "DinnerOrderAdaptive",
4
+ "meta": {
5
+ "profile": [
6
+ "http://hl7.org/fhir/StructureDefinition/cqf-questionnaire",
7
+ "http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaire-adapt"
8
+ ]
9
+ },
10
+ "extension": [
11
+ {
12
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-questionnaireAdaptive",
13
+ "valueBoolean": true
14
+ },
15
+ {
16
+ "url": "http://hl7.org/fhir/StructureDefinition/cqf-library",
17
+ "valueCanonical": "https://madie.cms.gov/Library/DTRTest"
18
+ }
19
+ ],
20
+ "name": "DinnerOrderAdaptive",
21
+ "title": "Dinner Order (Adaptive)",
22
+ "status": "draft",
23
+ "subjectType": [
24
+ "Patient"
25
+ ],
26
+ "date": "2024-05-06",
27
+ "publisher": "Inferno",
28
+ "item": [
29
+ {
30
+ "extension": [
31
+ {
32
+ "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
33
+ "valueCodeableConcept": {
34
+ "coding": [
35
+ {
36
+ "system": "http://hl7.org/fhir/questionnaire-item-control",
37
+ "code": "gtable"
38
+ }
39
+ ]
40
+ }
41
+ }
42
+ ],
43
+ "linkId": "PBD",
44
+ "text": "Patient Information",
45
+ "type": "group",
46
+ "item": [
47
+ {
48
+ "extension": [
49
+ {
50
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
51
+ "valueExpression": {
52
+ "language": "text/cql",
53
+ "expression": "\"DTRTest\".LastName"
54
+ }
55
+ }
56
+ ],
57
+ "linkId": "PBD.1",
58
+ "text": "Last Name:",
59
+ "type": "string",
60
+ "required": true
61
+ },
62
+ {
63
+ "extension": [
64
+ {
65
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
66
+ "valueExpression": {
67
+ "language": "text/cql",
68
+ "expression": "\"DTRTest\".FirstName"
69
+ }
70
+ }
71
+ ],
72
+ "linkId": "PBD.2",
73
+ "text": "First Name:",
74
+ "type": "string",
75
+ "required": true
76
+ }
77
+ ]
78
+ },
79
+ {
80
+ "extension": [
81
+ {
82
+ "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
83
+ "valueCodeableConcept": {
84
+ "coding": [
85
+ {
86
+ "system": "http://hl7.org/fhir/questionnaire-item-control",
87
+ "code": "gtable"
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ ],
93
+ "linkId": "LOC",
94
+ "text": "Patient's Location",
95
+ "type": "group",
96
+ "item": [
97
+ {
98
+ "extension": [
99
+ {
100
+ "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression",
101
+ "valueExpression": {
102
+ "language": "text/cql",
103
+ "expression": "\"DTRTest\".FirstLocationDescription"
104
+ }
105
+ }
106
+ ],
107
+ "linkId": "LOC.1",
108
+ "text": "Location",
109
+ "type": "string",
110
+ "required": true
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ "linkId": "3",
116
+ "text": "Dinner Order",
117
+ "type": "group",
118
+ "item": [
119
+ {
120
+ "linkId": "3.1",
121
+ "text": "What would you like for dinner?",
122
+ "type": "choice",
123
+ "required": true,
124
+ "answerOption": [
125
+ {
126
+ "valueCoding": {
127
+ "code": "Hamburger"
128
+ }
129
+ },
130
+ {
131
+ "valueCoding": {
132
+ "code": "Bean Burrito"
133
+ }
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "linkId": "3.2.a",
139
+ "text": "What would you like on your hamburger?",
140
+ "type": "choice",
141
+ "required": false,
142
+ "repeats": true,
143
+ "answerOption": [
144
+ {
145
+ "valueCoding": {
146
+ "code": "Ketchup"
147
+ }
148
+ },
149
+ {
150
+ "valueCoding": {
151
+ "code": "Mustard"
152
+ }
153
+ },
154
+ {
155
+ "valueCoding": {
156
+ "code": "Pickels"
157
+ }
158
+ },
159
+ {
160
+ "valueCoding": {
161
+ "code": "Tomato"
162
+ }
163
+ }
164
+ ]
165
+ },
166
+ {
167
+ "linkId": "3.3",
168
+ "text": "Any special requests?",
169
+ "type": "string",
170
+ "required": false
171
+ }
172
+ ]
173
+ }
174
+ ]
175
+ }