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,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
+ }