davinci_dtr_test_kit 0.13.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_completion_group.rb +23 -0
  3. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_followup_questions_group.rb +26 -0
  4. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_test.rb +93 -0
  5. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_request_validation_test.rb +62 -0
  6. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_next_question_retrieval_group.rb +23 -0
  7. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_adaptive_questionnaire_response_validation_test.rb +66 -0
  8. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_dinner_questionnaire_workflow_group.rb +76 -0
  9. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_initial_retrieval_group.rb +27 -0
  10. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_full_ehr_adaptive_questionnaire_request_test.rb +63 -0
  11. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_initial_retrieval_group.rb +24 -0
  12. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_adaptive_questionnaire_request_test.rb +148 -0
  13. data/lib/davinci_dtr_test_kit/client_groups/dinner_adaptive/dtr_smart_app_questionnaire_workflow_group.rb +75 -0
  14. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_full_ehr_questionnaire_workflow_group.rb +22 -38
  15. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_dinner_questionnaire_package_request_test.rb +13 -16
  16. data/lib/davinci_dtr_test_kit/client_groups/dinner_static/dtr_smart_app_questionnaire_workflow_group.rb +9 -31
  17. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_launch_attestation_test.rb +7 -6
  18. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_prepopulation_attestation_test.rb +7 -7
  19. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_prepopulation_override_attestation_test.rb +7 -7
  20. 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
  21. 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
  22. 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
  23. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_rendering_enabled_questions_attestation_test.rb +7 -7
  24. data/lib/davinci_dtr_test_kit/client_groups/full_ehr/dtr_full_ehr_saving_questionnaire_response_group.rb +29 -0
  25. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → full_ehr}/dtr_full_ehr_store_attestation_test.rb +7 -7
  26. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_questionnaire_rendering_attestation_test.rb +7 -6
  27. data/lib/davinci_dtr_test_kit/client_groups/resp_assist_device/dtr_resp_questionnaire_package_request_test.rb +15 -18
  28. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_basic_conformance_test.rb +5 -1
  29. data/lib/davinci_dtr_test_kit/client_groups/shared/dtr_questionnaire_response_pre_population_test.rb +12 -5
  30. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_prepopulation_attestation_test.rb +7 -7
  31. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_prepopulation_override_attestation_test.rb +7 -6
  32. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_questionnaire_response_save_test.rb +17 -7
  33. data/lib/davinci_dtr_test_kit/client_groups/{dinner_static → smart_app}/dtr_smart_app_rendering_enabled_questions_attestation_test.rb +7 -7
  34. data/lib/davinci_dtr_test_kit/client_groups/smart_app/dtr_smart_app_saving_questionnaire_response_group.rb +27 -0
  35. data/lib/davinci_dtr_test_kit/cql_test.rb +37 -140
  36. data/lib/davinci_dtr_test_kit/create_test.rb +25 -0
  37. data/lib/davinci_dtr_test_kit/docs/dtr_full_ehr_suite_description_v201.md +95 -37
  38. data/lib/davinci_dtr_test_kit/docs/dtr_light_ehr_suite_description_v201.md +15 -6
  39. data/lib/davinci_dtr_test_kit/docs/dtr_payer_server_suite_description_v201.md +32 -29
  40. data/lib/davinci_dtr_test_kit/docs/dtr_smart_app_suite_description_v201.md +48 -32
  41. data/lib/davinci_dtr_test_kit/dtr_full_ehr_suite.rb +13 -17
  42. data/lib/davinci_dtr_test_kit/dtr_light_ehr_suite.rb +67 -2
  43. data/lib/davinci_dtr_test_kit/dtr_payer_server_suite.rb +9 -20
  44. data/lib/davinci_dtr_test_kit/dtr_questionnaire_response_validation.rb +18 -10
  45. data/lib/davinci_dtr_test_kit/dtr_smart_app_suite.rb +32 -59
  46. data/lib/davinci_dtr_test_kit/endpoints/cors.rb +20 -0
  47. data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/authorize_endpoint.rb +32 -0
  48. data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/simple_token_endpoint.rb +19 -0
  49. data/lib/davinci_dtr_test_kit/endpoints/mock_authorization/token_endpoint.rb +116 -0
  50. data/lib/davinci_dtr_test_kit/endpoints/mock_authorization.rb +83 -0
  51. data/lib/davinci_dtr_test_kit/endpoints/mock_ehr/fhir_get_endpoint.rb +95 -0
  52. data/lib/davinci_dtr_test_kit/endpoints/mock_ehr/questionnaire_response_endpoint.rb +22 -0
  53. data/lib/davinci_dtr_test_kit/endpoints/mock_ehr.rb +25 -0
  54. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +11 -0
  55. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +11 -0
  56. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_endpoint.rb +162 -0
  57. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/next_question_proxy_endpoint.rb +36 -0
  58. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_endpoint.rb +62 -0
  59. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/questionnaire_package_proxy_endpoint.rb +38 -0
  60. data/lib/davinci_dtr_test_kit/endpoints/mock_payer.rb +36 -0
  61. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +10 -2
  62. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +10 -2
  63. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +10 -2
  64. data/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json +4 -3
  65. data/lib/davinci_dtr_test_kit/fixtures.rb +24 -1
  66. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_libraries_test.rb +2 -2
  67. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_expressions_test.rb +4 -3
  68. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_form_questionnaire_extensions_test.rb +3 -2
  69. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_expressions_test.rb +6 -6
  70. data/lib/davinci_dtr_test_kit/payer_server_groups/adaptive_next_questionnaire_extensions_test.rb +6 -5
  71. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_group.rb +2 -2
  72. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_bundles_validation_test.rb +6 -9
  73. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_search_validation_test.rb +15 -12
  74. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_adaptive_response_validation_test.rb +33 -23
  75. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_complete_test.rb +4 -4
  76. data/lib/davinci_dtr_test_kit/payer_server_groups/payer_server_next_response_validation_test.rb +16 -12
  77. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_libraries_test.rb +2 -2
  78. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_expressions_test.rb +5 -4
  79. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_questionnaire_extensions_test.rb +4 -3
  80. data/lib/davinci_dtr_test_kit/payer_server_groups/static_form_response_validation_test.rb +32 -25
  81. data/lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_read.rb +29 -0
  82. data/lib/davinci_dtr_test_kit/profiles/communication_request/communication_request_validation.rb +35 -0
  83. data/lib/davinci_dtr_test_kit/profiles/communication_request_group.rb +39 -0
  84. data/lib/davinci_dtr_test_kit/profiles/coverage/coverage_read.rb +29 -0
  85. data/lib/davinci_dtr_test_kit/profiles/coverage/coverage_validation.rb +35 -0
  86. data/lib/davinci_dtr_test_kit/profiles/coverage_group.rb +38 -0
  87. data/lib/davinci_dtr_test_kit/profiles/device_request/device_request_read.rb +29 -0
  88. data/lib/davinci_dtr_test_kit/profiles/device_request/device_request_validation.rb +35 -0
  89. data/lib/davinci_dtr_test_kit/profiles/device_request_group.rb +39 -0
  90. data/lib/davinci_dtr_test_kit/profiles/encounter/encounter_read.rb +29 -0
  91. data/lib/davinci_dtr_test_kit/profiles/encounter/encounter_validation.rb +35 -0
  92. data/lib/davinci_dtr_test_kit/profiles/encounter_group.rb +39 -0
  93. data/lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_read.rb +29 -0
  94. data/lib/davinci_dtr_test_kit/profiles/medication_request/medication_request_validation.rb +35 -0
  95. data/lib/davinci_dtr_test_kit/profiles/medication_request_group.rb +39 -0
  96. data/lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_read.rb +29 -0
  97. data/lib/davinci_dtr_test_kit/profiles/nutrition_order/nutrition_order_validation.rb +35 -0
  98. data/lib/davinci_dtr_test_kit/profiles/nutrition_order_group.rb +39 -0
  99. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_context_search.rb +35 -0
  100. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_create.rb +26 -0
  101. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_patient_search.rb +55 -0
  102. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_read.rb +22 -0
  103. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_update.rb +26 -0
  104. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response/questionnaire_response_validation.rb +37 -0
  105. data/lib/davinci_dtr_test_kit/profiles/questionnaire_response_group.rb +66 -0
  106. data/lib/davinci_dtr_test_kit/profiles/service_request/service_request_read.rb +29 -0
  107. data/lib/davinci_dtr_test_kit/profiles/service_request/service_request_validation.rb +35 -0
  108. data/lib/davinci_dtr_test_kit/profiles/service_request_group.rb +39 -0
  109. data/lib/davinci_dtr_test_kit/profiles/task/task_create.rb +26 -0
  110. data/lib/davinci_dtr_test_kit/profiles/task/task_read.rb +29 -0
  111. data/lib/davinci_dtr_test_kit/profiles/task/task_update.rb +26 -0
  112. data/lib/davinci_dtr_test_kit/profiles/task/task_validation.rb +35 -0
  113. data/lib/davinci_dtr_test_kit/profiles/task_group.rb +52 -0
  114. data/lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_read.rb +29 -0
  115. data/lib/davinci_dtr_test_kit/profiles/vision_prescription/vision_prescription_validation.rb +35 -0
  116. data/lib/davinci_dtr_test_kit/profiles/vision_prescription_group.rb +39 -0
  117. data/lib/davinci_dtr_test_kit/read_test.rb +22 -0
  118. data/lib/davinci_dtr_test_kit/tags.rb +5 -7
  119. data/lib/davinci_dtr_test_kit/update_test.rb +25 -0
  120. data/lib/davinci_dtr_test_kit/validation_test.rb +19 -4
  121. data/lib/davinci_dtr_test_kit/version.rb +1 -1
  122. metadata +110 -21
  123. data/lib/davinci_dtr_test_kit/ext/inferno_core/record_response_route.rb +0 -98
  124. data/lib/davinci_dtr_test_kit/ext/inferno_core/request.rb +0 -19
  125. data/lib/davinci_dtr_test_kit/ext/inferno_core/runnable.rb +0 -35
  126. data/lib/davinci_dtr_test_kit/mock_auth_server.rb +0 -228
  127. data/lib/davinci_dtr_test_kit/mock_ehr.rb +0 -105
  128. data/lib/davinci_dtr_test_kit/mock_payer.rb +0 -100
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a072f135a4057afa53b8836a3436fab457fc8c1ab15199e19608732b16d16cb
4
- data.tar.gz: e4942f1af9755743eab89b7a0cc8b559929ad8b4be4bed00e7e1a33b4de1b0bd
3
+ metadata.gz: 714c3c65e729c520080f2b112a538d123474b6193f858c1ca1a6a8a6fd018f04
4
+ data.tar.gz: 5d54ba3e7347d18042a9a846003bf9ad7d99082f1a7305882c71057dd4afbc9f
5
5
  SHA512:
6
- metadata.gz: aae323b007b88a564283b1fc946490e3c2330d6b3081de4783c0611c25afd732327e631d7e782743bab1fe1cab797dad84bcd9403accedcdb21f464278d05f0f
7
- data.tar.gz: e68f011efaa3f0785d94c7a1f683a9986474dc887f3b99492b62ccdaf5f3ecb92387be39c909872a6f6448dfc6cb8dc1520de971557d8325cf725b3fe6853771
6
+ metadata.gz: 9c14456cfef4db2b3e03b6828b8e7d605244e9fbe97965fcb60cc08489556604b89cc959810d8c14b3af4b420241230f9d7604c017760e6243ac0e561b5d0d32
7
+ data.tar.gz: b3d0f57301297c25ace0548a1f9dfe561610dab10b24841d38a68122adc43b822def90c1edcd22499831a47aed3609331e024ae9029d0b132c337c956176f052
@@ -0,0 +1,23 @@
1
+ require_relative 'dtr_adaptive_questionnaire_next_question_retrieval_group'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRAdaptiveQuestionnaireCompletionGroup < Inferno::TestGroup
5
+ id :dtr_adaptive_questionnaire_completion
6
+ title 'Completing the Adaptive Questionnaire'
7
+ description %(
8
+ The client makes a final $next-question call, including the answers to all required questions asked so far.
9
+ Inferno will validate that the request conforms to the [next question operation input parameters profile](http://hl7.org/fhir/uv/sdc/StructureDefinition/parameters-questionnaire-next-question-in)
10
+ and will update the status of the QuestionnaireResponse resource parameter to `complete`.
11
+ Inferno will also validate the completed QuestionnaireResponse conformance.
12
+ )
13
+
14
+ config(
15
+ options: {
16
+ next_question_prompt_title: 'Last Next Question Request'
17
+ }
18
+ )
19
+ run_as_group
20
+
21
+ group from: :dtr_adaptive_questionnaire_next_question_retrieval
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'dtr_adaptive_questionnaire_next_question_retrieval_group'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRAdaptiveQuestionnaireFollowupQuestionsGroup < Inferno::TestGroup
5
+ id :dtr_adaptive_questionnaire_followup_questions
6
+ title 'Retrieving the Next Question'
7
+ description %(
8
+ The client makes a subsequent call to request the next question or set of questions
9
+ using the $next-question operation, and including the answers to all required questions
10
+ in the questionnaire to this point.
11
+ Inferno will validate that the request conforms to the [next question operation input parameters profile](http://hl7.org/fhir/uv/sdc/StructureDefinition/parameters-questionnaire-next-question-in)
12
+ and will provide the next questions accordingly for the tester to complete and attest to pre-population
13
+ and questionnaire rendering.
14
+ )
15
+
16
+ config(
17
+ options: {
18
+ next_question_prompt_title: 'Follow-up Next Question Request'
19
+ }
20
+ )
21
+
22
+ run_as_group
23
+
24
+ group from: :dtr_adaptive_questionnaire_next_question_retrieval
25
+ end
26
+ end
@@ -0,0 +1,93 @@
1
+ require_relative '../../urls'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRAdaptiveQuestionnaireNextQuestionRequestTest < Inferno::Test
5
+ include URLs
6
+
7
+ id :dtr_adaptive_questionnaire_next_question_request
8
+ title 'Invoke the $next-question operation'
9
+ description %(
10
+ Inferno will wait for the client to invoke the $next-question operation to retrieve the next question
11
+ or set of questions.
12
+ Inferno will validate the request body and update the contained Questionnaire to include
13
+ the next question or set of questions.
14
+ )
15
+
16
+ input :access_token
17
+
18
+ def example_client_jwt_payload_part
19
+ Base64.strict_encode64({ inferno_client_id: access_token }.to_json).delete('=')
20
+ end
21
+
22
+ def request_identification
23
+ if config.options[:smart_app]
24
+ "eyJhbGciOiJub25lIn0.#{example_client_jwt_payload_part}"
25
+ else
26
+ access_token
27
+ end
28
+ end
29
+
30
+ def cont_test_description
31
+ <<~DESCRIPTION
32
+ ### Continuing the Tests
33
+
34
+ When the DTR application has finished loading the Questionnaire,
35
+ including any clinical data requests to support pre-population,
36
+ [Click here](#{resume_pass_url}?token=#{access_token}) to continue.
37
+ DESCRIPTION
38
+ end
39
+
40
+ def next_question_prompt_title
41
+ config.options[:next_question_prompt_title]
42
+ end
43
+
44
+ def next_question_prompt
45
+ if next_question_prompt_title&.include?('Initial')
46
+ 'Invoke the $next-question operation by sending a POST request to'
47
+ elsif next_question_prompt_title&.include?('Last')
48
+ 'Answer the remaining questions and then make a final next-question request by sending a POST request to'
49
+ else
50
+ "Answer the 'What do you want for dinner' question and then make a next-question request by sending a POST " \
51
+ 'request to'
52
+ end
53
+ end
54
+
55
+ def prompt_cont
56
+ if next_question_prompt_title&.include?('Initial')
57
+ %(Upon receipt, Inferno will provide the first set of questions to complete.)
58
+ elsif next_question_prompt_title&.include?('Last')
59
+ %(Upon receipt, Inferno will update the status of the QuestionnaireResponse
60
+ resource parameter to `complete`.)
61
+ else
62
+ %(Upon receipt, Inferno will provide the next set of questions to complete
63
+ based on previous answers.)
64
+ end
65
+ end
66
+
67
+ run do
68
+ wait(
69
+ identifier: access_token,
70
+ message: <<~MESSAGE
71
+ ### #{next_question_prompt_title}
72
+
73
+ #{next_question_prompt}
74
+
75
+ `#{next_url}`
76
+
77
+ #{prompt_cont}
78
+
79
+ ### Request Identification
80
+
81
+ In order to identify requests for this session, Inferno will look for
82
+ an `Authorization` header with value:
83
+
84
+ ```
85
+ Bearer #{request_identification}
86
+ ```
87
+
88
+ #{cont_test_description if config.options[:accepts_multiple_requests]}
89
+ MESSAGE
90
+ )
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,62 @@
1
+ require_relative '../../urls'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRAdaptiveQuestionnaireNextQuestionRequestValidationTest < Inferno::Test
5
+ include URLs
6
+
7
+ id :dtr_next_question_request_validation
8
+ title '$next-question request is valid'
9
+ description %(
10
+ Per the [OperationDefinition: Adaptive questionnaire next question](https://build.fhir.org/ig/HL7/sdc/OperationDefinition-Questionnaire-next-question.html#root)
11
+ section in the [Structured Data Capture IG](http://hl7.org/fhir/uv/sdc/ImplementationGuide/hl7.fhir.uv.sdc),
12
+ the request body for the `$next-question` operation should be a FHIR Parameters resource containing a
13
+ single parameter with:
14
+ - name: `questionnaire-response`
15
+ - resource: A `QuestionnaireResponse` resource
16
+
17
+ As outlined in the [FHIR Operation Request](https://hl7.org/fhir/r4/operations.html#request) section of the
18
+ FHIR specification, if an operation has exactly one input parameter of type Resource, it can also be invoked via
19
+ a POST request using that resource as the body (with no additional URL parameters).
20
+
21
+ This test validates the structure of the `$next-question` request body. It confirms that the body is either a
22
+ Parameters resource or a QuestionnaireResponse resource.
23
+
24
+ If it is a Parameters resource, it must contain one parameter named `questionnaire-response`
25
+ with a `resource` attribute set to a FHIR QuestionnaireResponse instance, as specified above.
26
+
27
+ The QuestionnaireResponse resource's structure and conformance will be validated
28
+ in the following test ('Adaptive QuestionnaireResponse is valid').
29
+ )
30
+
31
+ def assert_valid_resource_type(resource)
32
+ type = resource.resourceType
33
+ valid = ['Parameters', 'QuestionnaireResponse'].include?(type)
34
+ assert valid, "Request body not valid. Expected Parameters or QuestionnaireResponse, got #{type}"
35
+ end
36
+
37
+ def next_request_tag
38
+ config.options[:next_tag]
39
+ end
40
+
41
+ run do
42
+ load_tagged_requests next_request_tag
43
+ skip_if request.blank?, 'A $next-question request must be made prior to running this test'
44
+
45
+ assert request.url == next_url, "Request made to wrong URL: #{request.url}. Should instead be to #{next_url}"
46
+ assert_valid_json(request.request_body)
47
+ input_params = FHIR.from_contents(request.request_body)
48
+ assert input_params.present?, 'Request does not contain a recognized FHIR object'
49
+ assert_valid_resource_type(input_params)
50
+
51
+ if input_params.is_a?(FHIR::Parameters)
52
+ questionnaire_response_params = input_params.parameter.select { |param| param.name == 'questionnaire-response' }
53
+ qr_params_count = questionnaire_response_params.length
54
+ assert qr_params_count == 1,
55
+ "Input parameter must contain one `parameter:questionnaire-response` slice. Found #{qr_params_count}"
56
+
57
+ questionnaire_response = questionnaire_response_params.first.resource
58
+ assert_resource_type(:questionnaire_response, resource: questionnaire_response)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'dtr_adaptive_questionnaire_next_question_request_test'
2
+ require_relative 'dtr_adaptive_questionnaire_next_question_request_validation_test'
3
+ require_relative 'dtr_adaptive_questionnaire_response_validation_test'
4
+
5
+ module DaVinciDTRTestKit
6
+ class DTRAdaptiveQuestionnaireNextQuestionRetrievalGroup < Inferno::TestGroup
7
+ id :dtr_adaptive_questionnaire_next_question_retrieval
8
+ title 'Next Question Request and Validation'
9
+ description %(
10
+ Inferno will wait for the client system to request the next question (or set of questions) using the
11
+ $next-question operation and will return an updated QuestionnaireResponse with a contained Questionnaire
12
+ that includes the next question (or set of questions) for the tester to complete.
13
+ Inferno will then validate the conformance of the request.
14
+ )
15
+
16
+ # Test 1: wait for the $next-question request
17
+ test from: :dtr_adaptive_questionnaire_next_question_request
18
+ # Test 2: validate the $next-question request
19
+ test from: :dtr_next_question_request_validation
20
+ # Test 3: validate the QuestionnaireResponse in the input parameter
21
+ test from: :dtr_adaptive_questionnaire_response_validation
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ require_relative '../../urls'
2
+ require_relative '../../dtr_questionnaire_response_validation'
3
+
4
+ module DaVinciDTRTestKit
5
+ class DTRAdaptiveQuestionnaireResponseValidationTest < Inferno::Test
6
+ include URLs
7
+ include DTRQuestionnaireResponseValidation
8
+
9
+ id :dtr_adaptive_questionnaire_response_validation
10
+ title 'Adaptive QuestionnaireResponse is valid'
11
+ description %(
12
+ This test validates the conformance of the Adative QuestionnaireResponse to the
13
+ [SDCQuestionnaireResponseAdapt](http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse-adapt)
14
+ structure. It verifies the presence of mandatory elements and that elements
15
+ with required bindings contain appropriate values.
16
+
17
+ It also ensures that all required questions are answered, and that the `origin.source`
18
+ extension is correct for each answer:
19
+ - `PBD.1` (Last Name) and `LOC.1` (Location): `auto`
20
+ - `PBD.2` (First Name): `override`
21
+ - `3` (all nested dinner questions): `manual`
22
+
23
+ Note: For the initial next-question request, only the conformance to the profile is checked
24
+ since neither the QuestionnaireResponse nor the contained Questionnaire will have any items,
25
+ as no questions are yet known.
26
+ )
27
+
28
+ def profile_url
29
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaireresponse-adapt'
30
+ end
31
+
32
+ def next_request_tag
33
+ config.options[:next_tag]
34
+ end
35
+
36
+ run do
37
+ load_tagged_requests next_request_tag
38
+ skip_if request.blank?, 'A $next-question request must be made prior to running this test'
39
+
40
+ assert request.url == next_url, "Request made to wrong URL: #{request.url}. Should instead be to #{next_url}"
41
+ assert_valid_json(request.request_body)
42
+ input_params = FHIR.from_contents(request.request_body)
43
+ skip_if input_params.blank?, 'Request does not contain a recognized FHIR object'
44
+
45
+ questionnaire_response = nil
46
+ if input_params.is_a?(FHIR::QuestionnaireResponse)
47
+ questionnaire_response = input_params
48
+ elsif input_params.is_a?(FHIR::Parameters)
49
+ questionnaire_response = input_params.parameter&.find do |param|
50
+ param.name == 'questionnaire-response'
51
+ end&.resource
52
+ end
53
+
54
+ skip_if questionnaire_response.nil?, 'QuestionnaireResponse resource not provided.'
55
+ verify_basic_conformance(questionnaire_response.to_json, profile_url)
56
+
57
+ questionnaire = questionnaire_response.contained.find { |res| res.resourceType == 'Questionnaire' }
58
+ check_origin_sources(questionnaire.item, questionnaire_response.item, expected_overrides: ['PBD.2'])
59
+
60
+ required_link_ids = extract_required_link_ids(questionnaire.item)
61
+ check_answer_presence(questionnaire_response.item, required_link_ids)
62
+
63
+ assert(messages.none? { |m| m[:type] == 'error' }, 'QuestionnaireResponse is not correct, see error message(s)')
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,76 @@
1
+ require_relative '../../tags'
2
+ require_relative 'dtr_full_ehr_adaptive_questionnaire_initial_retrieval_group'
3
+ require_relative '../full_ehr/dtr_full_ehr_prepopulation_attestation_test'
4
+ require_relative '../full_ehr/dtr_full_ehr_prepopulation_override_attestation_test'
5
+ require_relative 'dtr_adaptive_questionnaire_followup_questions_group'
6
+ require_relative 'dtr_adaptive_questionnaire_completion_group'
7
+
8
+ module DaVinciDTRTestKit
9
+ class DTRFullEHRAdaptiveDinnerQuestionnaireWorkflowGroup < Inferno::TestGroup
10
+ id :dtr_full_ehr_adaptive_dinner_questionnaire_workflow
11
+ title 'Adaptive Questionnaire Workflow'
12
+ description %(
13
+ This test validates that a DTR Full EHR client can perform a full DTR Adaptive Questionnaire workflow
14
+ using a mocked questionnaire requesting what a patient wants for dinner. The client system must
15
+ demonstrate their ability to:
16
+
17
+ 1. Fetch the adaptive questionnaire package
18
+ ([DinnerOrderAdaptive](https://github.com/inferno-framework/davinci-dtr-test-kit/blob/main/lib/davinci_dtr_test_kit/fixtures/dinner_adaptive/questionnaire_dinner_order_adaptive.json))
19
+ 2. Fetch the first set of questions and render and pre-populate them appropriately, including:
20
+ - pre-populate data as directed by the questionnaire
21
+ - display questions only when they are enabled
22
+ 3. Answer the initial questions and request additional questions
23
+ 4. Complete the questionnaire and provide the completed QuestionnaireResponse
24
+ with appropriate indicators for pre-populated and manually-entered data.
25
+ )
26
+
27
+ group do
28
+ id :dtr_full_ehr_adaptive_questionnaire_retrieval
29
+ title 'Retrieving the Adaptive Questionnaire'
30
+ description %(
31
+ After DTR launch, Inferno will wait for the client system to request a questionnaire using the
32
+ $questionnaire-package operation and follow up with an initial $next-question request to retrieve
33
+ the first set of questions.
34
+
35
+ The initial set of questions will be returned for the tester to complete and attest to pre-population
36
+ and questionnaire rendering.
37
+
38
+ Inferno will also validate the conformance of the requests.
39
+ )
40
+ run_as_group
41
+
42
+ group from: :dtr_full_ehr_adaptive_questionnaire_initial_retrieval
43
+ group do
44
+ id :dtr_full_ehr_initial_questionnaire_rendering
45
+ title 'Filling Out the Questionnaire'
46
+ description %(
47
+ The tester will interact with the questionnaire within their client system
48
+ such that pre-population steps are taken, the qustionnaire is rendered, and
49
+ they are able to fill it out. The tester will attest that questionnaire pre-population
50
+ and rendering directives were followed.
51
+ )
52
+
53
+ # Test 1: attest to the pre-population of the name fields
54
+ test from: :dtr_full_ehr_prepopulation_attestation
55
+ # Test 2: attest to the pre-population and edit of the first name field
56
+ test from: :dtr_full_ehr_prepopulation_override_attestation
57
+ end
58
+ end
59
+
60
+ group from: :dtr_adaptive_questionnaire_followup_questions,
61
+ config: {
62
+ options: {
63
+ accepts_multiple_requests: true,
64
+ next_tag: "followup_#{CLIENT_NEXT_TAG}"
65
+ }
66
+ }
67
+
68
+ group from: :dtr_adaptive_questionnaire_completion,
69
+ config: {
70
+ options: {
71
+ accepts_multiple_requests: true,
72
+ next_tag: "completion_#{CLIENT_NEXT_TAG}"
73
+ }
74
+ }
75
+ end
76
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../../tags'
2
+ require_relative '../full_ehr/dtr_full_ehr_launch_attestation_test'
3
+ require_relative 'dtr_full_ehr_adaptive_questionnaire_request_test'
4
+ require_relative '../shared/dtr_questionnaire_package_request_validation_test'
5
+ require_relative 'dtr_adaptive_questionnaire_next_question_request_validation_test'
6
+ require_relative 'dtr_adaptive_questionnaire_response_validation_test'
7
+
8
+ module DaVinciDTRTestKit
9
+ class DTRFullEHRAdaptiveQuestionnaireInitialRetrievalGroup < Inferno::TestGroup
10
+ id :dtr_full_ehr_adaptive_questionnaire_initial_retrieval
11
+ title 'Adaptive Questionnaire Package and Initial Questions Retrieval'
12
+
13
+ config(options: { next_tag: "initial_#{CLIENT_NEXT_TAG}" })
14
+ run_as_group
15
+
16
+ # Test 0: attest to launch
17
+ test from: :dtr_full_ehr_launch_attestation
18
+ # Test 1: wait for the $questionnaire-package request and initial $next-question request
19
+ test from: :dtr_full_ehr_adaptive_questionnaire_request
20
+ # Test 2: validate the $questionnaire-package request body
21
+ test from: :dtr_questionnaire_package_request_validation
22
+ # Test 3: validate the $next-question request body
23
+ test from: :dtr_next_question_request_validation
24
+ # Test 4: validate the QuestionnaireResponse in the input parameter
25
+ test from: :dtr_adaptive_questionnaire_response_validation
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ require_relative '../../urls'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRFullEHRAdaptiveQuestionnaireRequestTest < Inferno::Test
5
+ include URLs
6
+
7
+ id :dtr_full_ehr_adaptive_questionnaire_request
8
+ title 'Invoke the Questionnaire Package and Initial Next Question Operation'
9
+ description %(
10
+ This test waits for two sequential client requests:
11
+
12
+ 1. **Questionnaire Package Request**: The client should first invoke the `$questionnaire-package` operation
13
+ to retrieve the adaptive questionnaire package. Inferno will respond to this request with an empty adaptive
14
+ questionnaire.
15
+
16
+ 2. **Initial Next Question Request**: After receiving the package, the client should invoke the
17
+ `$next-question` operation. Inferno will respond by providing the first set of questions.
18
+ )
19
+
20
+ config options: { accepts_multiple_requests: true }
21
+ input :access_token
22
+
23
+ run do
24
+ wait(
25
+ identifier: access_token,
26
+ message: %(
27
+ ### Adaptive Questionnaire Retrieval
28
+
29
+ 1. **Questionnaire Package Request**:
30
+ - Invoke the `$questionnaire-package` operation by sending a POST request to the following
31
+ endpoint to retrieve the adaptive questionnaire package:
32
+
33
+ `#{questionnaire_package_url}`.
34
+
35
+ - Inferno will respond with an empty adaptive questionnaire.
36
+
37
+ 2. **Initial Next Question Request**:
38
+ - After receiving the questionnaire package, invoke the `$next-question` operation by sending
39
+ a POST request to the following endpoint to retrieve the first set of questions:
40
+
41
+ `#{next_url}`.
42
+
43
+ - Inferno will respond with the initial set of questions.
44
+
45
+ Inferno will wait for both of these requests to be made.
46
+
47
+ ### Request Identification
48
+
49
+ In order to identify requests for this session, Inferno will look for
50
+ an `Authorization` header with value:
51
+
52
+ ```
53
+ Bearer #{access_token}
54
+ ```
55
+
56
+ ### Continuing the Tests
57
+
58
+ When both requests have been made, [Click here](#{resume_pass_url}?token=#{access_token}) to continue.
59
+ )
60
+ )
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../../tags'
2
+ require_relative 'dtr_smart_app_adaptive_questionnaire_request_test'
3
+ require_relative '../shared/dtr_questionnaire_package_request_validation_test'
4
+ require_relative 'dtr_adaptive_questionnaire_next_question_request_validation_test'
5
+ require_relative 'dtr_adaptive_questionnaire_response_validation_test'
6
+
7
+ module DaVinciDTRTestKit
8
+ class DTRSmartAppAdaptiveQuestionnaireInitialRetrievalGroup < Inferno::TestGroup
9
+ id :dtr_smart_app_adaptive_questionnaire_initial_retrieval
10
+ title 'Adaptive Questionnaire Package and Initial Questions Retrieval'
11
+
12
+ config(options: { next_tag: "initial_#{CLIENT_NEXT_TAG}" })
13
+ run_as_group
14
+
15
+ # Test 1: wait for the $questionnaire-package request and initial $next-question request
16
+ test from: :dtr_smart_app_adaptive_questionnaire_request
17
+ # Test 2: validate the $questionnaire-package request body
18
+ test from: :dtr_questionnaire_package_request_validation
19
+ # Test 3: validate the $next-question request body
20
+ test from: :dtr_next_question_request_validation
21
+ # Test 4: validate the QuestionnaireResponse in the input parameter
22
+ test from: :dtr_adaptive_questionnaire_response_validation
23
+ end
24
+ end
@@ -0,0 +1,148 @@
1
+ require_relative '../../urls'
2
+
3
+ module DaVinciDTRTestKit
4
+ class DTRSmartAppAdaptiveQuestionnaireRequestTest < Inferno::Test
5
+ include URLs
6
+
7
+ id :dtr_smart_app_adaptive_questionnaire_request
8
+ title 'Invoke the Questionnaire Package and Initial Next Question Operation'
9
+ description %(
10
+ This test waits for two sequential client requests:
11
+
12
+ 1. **Questionnaire Package Request**: The client should first invoke the `$questionnaire-package` operation
13
+ to retrieve the adaptive questionnaire package. Inferno will respond to this request with an empty adaptive
14
+ questionnaire.
15
+
16
+ 2. **Initial Next Question Request**: After receiving the package, the client should invoke the
17
+ `$next-question` operation. Inferno will respond by providing the first set of questions.
18
+ )
19
+
20
+ config options: { accepts_multiple_requests: true }
21
+ input :smart_app_launch,
22
+ type: 'radio',
23
+ title: 'SMART App Launch',
24
+ description: 'How will the DTR SMART App launch?',
25
+ options: { list_options: [{ label: 'EHR Launch from Inferno', value: 'ehr' },
26
+ { label: 'Standalone Launch', value: 'standalone' }] }
27
+ input :client_id
28
+ input :launch_uri,
29
+ optional: true,
30
+ description: 'Required if "Launch from Inferno" is selected'
31
+ input :adaptive_smart_patient_id,
32
+ optional: true,
33
+ title: 'SMART App Launch Patient ID (Dinner Adaptive)',
34
+ type: 'text',
35
+ description: %(
36
+ Patient instance ID to be provided by Inferno as the patient as a part of the SMART App Launch.
37
+ ),
38
+ default: 'pat015'
39
+ input :adaptive_smart_fhir_context,
40
+ optional: true,
41
+ title: 'SMART App Launch fhirContext (Dinner Adaptive)',
42
+ type: 'textarea',
43
+ description: %(
44
+ References to be provided by Inferno as the fhirContext as a part of the SMART App
45
+ Launch. These references help determine the behavior of the app. Referenced instances
46
+ may be provided in the "EHR-available resources" input.
47
+ ),
48
+ default: JSON.pretty_generate([{ reference: 'Coverage/cov015' },
49
+ { reference: 'DeviceRequest/devreqe0470' }])
50
+ input :adaptive_ehr_bundle,
51
+ optional: true,
52
+ title: 'EHR-available resources (Dinner Adaptive)',
53
+ type: 'textarea',
54
+ description: %(
55
+ Resources available from the EHR needed to drive the dinner adaptive workflow.
56
+ Formatted as a FHIR bundle that contains resources, each with an ID property populated. Each
57
+ instance present will be available for retrieval from Inferno at the endpoint:
58
+ <fhir-base>/<resource type>/<instance id>
59
+ )
60
+
61
+ def example_client_jwt_payload_part
62
+ Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
63
+ end
64
+
65
+ run do
66
+ # validate relevant inputs and provide warnings if they are bad
67
+ warning do
68
+ if adaptive_smart_fhir_context
69
+ assert_valid_json(adaptive_smart_fhir_context,
70
+ 'The **SMART App Launch fhirContext** input is not valid JSON, so it will not be included in
71
+ the access token response.')
72
+ end
73
+ end
74
+
75
+ warning do
76
+ if adaptive_ehr_bundle
77
+ assert_valid_json(adaptive_ehr_bundle,
78
+ 'The **EHR-available resources** input is not valid JSON, so no tester-specified instances
79
+ will be available to access from Inferno.')
80
+ assert(FHIR.from_contents(adaptive_ehr_bundle).is_a?(FHIR::Bundle),
81
+ 'The **EHR-available resources** input does not contain a FHIR Bundle, so no tester-specified instances
82
+ will be available to access from Inferno.')
83
+ end
84
+ end
85
+
86
+ launch_prompt = if smart_app_launch == 'ehr'
87
+ %(Launch the DTR SMART App from Inferno by right clicking
88
+ [this link](#{launch_uri}?iss=#{fhir_base_url}&launch=#{launch_uri})
89
+ and selecting "Open in new window" or "Open in new tab".)
90
+ else
91
+ %(Launch the SMART App from your EHR.)
92
+ end
93
+ inferno_prompt_cont = %(As the DTR app steps through the launch steps, Inferno will wait and respond to the app's
94
+ requests for SMART configuration, authorization and access token.)
95
+
96
+ wait(
97
+ identifier: client_id,
98
+ message: %(
99
+ ### SMART App Launch
100
+
101
+ #{launch_prompt}
102
+
103
+ #{inferno_prompt_cont if smart_app_launch == 'ehr'}
104
+
105
+ ### Adaptive Questionnaire Retrieval
106
+
107
+ 1. **Questionnaire Package Request**:
108
+ - Inferno will expect the SMART App to invoke the DTR Questionnaire Package operation by sending a POST
109
+ request to
110
+
111
+ `#{questionnaire_package_url}`
112
+
113
+ - Inferno will respond with an empty adaptive questionnaire.
114
+
115
+ 2. **Initial Next Question Request**:
116
+ - After receiving the questionnaire package, invoke the `$next-question` operation by sending
117
+ a POST request to the following endpoint to retrieve the first set of questions:
118
+
119
+ `#{next_url}`.
120
+
121
+ - Inferno will respond with the initial set of questions.
122
+
123
+ ### Pre-population
124
+
125
+ Inferno will then wait for the client to complete Questionnaire pre-population. The client should make FHIR
126
+ GET requests using service base path:
127
+
128
+ `#{fhir_base_url}`
129
+
130
+ ### Request Identification
131
+
132
+ In order to identify requests for this session, Inferno will look for
133
+ an `Authorization` header with value:
134
+
135
+ ```
136
+ Bearer eyJhbGciOiJub25lIn0.#{example_client_jwt_payload_part}.
137
+ ```
138
+
139
+ ### Continuing the Tests
140
+
141
+ When the DTR application has finished loading the Questionnaire,
142
+ including any clinical data requests to support pre-population,
143
+ [Click here](#{resume_pass_url}?client_id=#{client_id}) to continue.
144
+ )
145
+ )
146
+ end
147
+ end
148
+ end