davinci_dtr_test_kit 0.17.0 → 0.18.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 (311) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/v220_full_ehr_suite_run_against_payer_suite.json.erb +19 -0
  3. data/config/presets/v220_payer_suite_run_against_full_ehr_suite.json.erb +76 -0
  4. data/lib/davinci_dtr_test_kit/cross_suite/fhirpath_utils.rb +52 -0
  5. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_base_questionnaire/metadata.yml +212 -0
  6. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_q_package_bundle/metadata.yml +39 -0
  7. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_qpackage_output_parameters/metadata.yml +30 -0
  8. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_questionnaire_adapt/metadata.yml +17 -0
  9. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_questionnaire_adapt_search/metadata.yml +91 -0
  10. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/dtr_std_questionnaire/metadata.yml +17 -0
  11. data/lib/davinci_dtr_test_kit/cross_suite/generated/v2.2.0/metadata.yml +403 -0
  12. data/lib/davinci_dtr_test_kit/cross_suite/generated_profile_metadata.rb +22 -0
  13. data/lib/davinci_dtr_test_kit/cross_suite/response_selection_utils.rb +85 -0
  14. data/lib/davinci_dtr_test_kit/{cql_test.rb → cross_suite/v2.0.1/cql_test.rb} +3 -3
  15. data/lib/davinci_dtr_test_kit/cross_suite/v2.2.0/dtr_conformance_verification.rb +21 -0
  16. data/lib/davinci_dtr_test_kit/cross_suite/v2.2.0/multi_request_message_helper.rb +35 -0
  17. data/lib/davinci_dtr_test_kit/cross_suite/v2.2.0/questionnaire_helper.rb +162 -0
  18. data/lib/davinci_dtr_test_kit/{dtr_client_options.rb → full_ehr/dtr_full_ehr_options.rb} +1 -1
  19. data/lib/davinci_dtr_test_kit/{endpoints → full_ehr/endpoints}/mock_payer.rb +9 -3
  20. data/lib/davinci_dtr_test_kit/{endpoints → full_ehr/endpoints}/mock_udap_smart_server/token_endpoint.rb +2 -2
  21. data/lib/davinci_dtr_test_kit/full_ehr/fixture_loader.rb +37 -0
  22. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_template.json +243 -0
  23. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_adaptive/parameters_questionnaire_dinner_order_adaptive.json +104 -0
  24. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_static/parameters_questionnaire_dinner_order_static.json +291 -0
  25. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/empty_templates/next_question_template_empty.json +1 -0
  26. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/empty_templates/parameters_questionnaire_package_empty.json +9 -0
  27. data/lib/davinci_dtr_test_kit/full_ehr/short_circuit_interaction_verification.rb +73 -0
  28. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → full_ehr/v2.0.1/adaptive_custom}/dtr_custom_next_question_response_validation_test.rb +2 -1
  29. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → full_ehr/v2.0.1/adaptive_custom}/dtr_full_ehr_custom_adaptive_request_test.rb +1 -1
  30. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → full_ehr/v2.0.1/adaptive_dinner}/dtr_adaptive_next_question_retrieval_group.rb +3 -3
  31. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → full_ehr/v2.0.1/adaptive_dinner}/dtr_full_ehr_adaptive_initial_retrieval_group.rb +5 -5
  32. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire → full_ehr/v2.0.1/adaptive_interaction}/dtr_adaptive_next_question_request_test.rb +1 -1
  33. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire → full_ehr/v2.0.1/adaptive_interaction}/dtr_adaptive_next_question_request_validation_test.rb +1 -1
  34. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire → full_ehr/v2.0.1/adaptive_interaction}/dtr_adaptive_response_validation_test.rb +2 -2
  35. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → full_ehr/v2.0.1}/dtr_full_ehr_adaptive_dinner_workflow_group.rb +7 -7
  36. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → full_ehr/v2.0.1}/dtr_full_ehr_custom_adaptive_workflow_group.rb +18 -16
  37. data/lib/davinci_dtr_test_kit/{client_groups/custom_static → full_ehr/v2.0.1}/dtr_full_ehr_custom_static_workflow_group.rb +11 -11
  38. data/lib/davinci_dtr_test_kit/{client_groups/must_support → full_ehr/v2.0.1}/dtr_full_ehr_questionnaire_must_support_group.rb +8 -7
  39. data/lib/davinci_dtr_test_kit/{client_groups/dinner_static → full_ehr/v2.0.1}/dtr_full_ehr_static_dinner_workflow_group.rb +7 -7
  40. data/lib/davinci_dtr_test_kit/{dtr_full_ehr_suite.rb → full_ehr/v2.0.1/dtr_full_ehr_suite.rb} +23 -20
  41. data/lib/davinci_dtr_test_kit/{client_groups/payer_registration/dtr_client_registration_group.rb → full_ehr/v2.0.1/dtr_payer_registration_group.rb} +8 -8
  42. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer/next_question_endpoint.rb → full_ehr/v2.0.1/full_ehr_next_question_endpoint.rb} +18 -7
  43. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer/questionnaire_package_endpoint.rb → full_ehr/v2.0.1/full_ehr_questionnaire_package_endpoint.rb} +22 -7
  44. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/dtr_full_ehr_ms_questionnaire_package_request_test.rb +1 -1
  45. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/dtr_must_support_attestation_test.rb +2 -1
  46. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/dtr_questionnaire_must_support_test.rb +3 -2
  47. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/payer_registration/configuration_display_smart_test.rb +1 -1
  48. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/payer_registration/configuration_display_udap_test.rb +1 -1
  49. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_expressions_test.rb +3 -2
  50. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_extensions_test.rb +3 -2
  51. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_libraries_test.rb +3 -2
  52. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_package_validation_test.rb +3 -2
  53. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_adaptive_request_test.rb +1 -1
  54. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_launch_attestation_test.rb +1 -1
  55. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_prepopulation_attestation_test.rb +1 -1
  56. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_prepopulation_override_attestation_test.rb +1 -1
  57. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_questionnaire_package_request_test.rb +1 -1
  58. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_questionnaire_response_conformance_test.rb +1 -1
  59. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_questionnaire_response_correctness_test.rb +1 -1
  60. data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_store_attestation_test.rb +1 -1
  61. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_prepopulation_attestation_test.rb +1 -1
  62. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_prepopulation_override_attestation_test.rb +1 -1
  63. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_package_request_validation_test.rb +1 -1
  64. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_response_basic_conformance_test.rb +2 -2
  65. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_response_prepopulation_test.rb +1 -1
  66. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_rendering_attestation_test.rb +1 -1
  67. data/lib/davinci_dtr_test_kit/{client_groups/dinner_static → full_ehr/v2.0.1/static_dinner}/dtr_static_dinner_enabled_questions_attestation_test.rb +1 -1
  68. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_abstract_adaptive_group.rb +87 -0
  69. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_abstract_standard_group.rb +59 -0
  70. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_suite.rb +145 -0
  71. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_suite_description_v220.md +254 -0
  72. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/full_ehr_next_question_endpoint.rb +391 -0
  73. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/full_ehr_questionnaire_package_endpoint.rb +206 -0
  74. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/adaptive_questionnaires_completed_test.rb +108 -0
  75. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/interaction_wait_test.rb +177 -0
  76. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/ui_display_and_interaction_attestation_test.rb +132 -0
  77. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_additional_questionnaires_interaction_group.rb +74 -0
  78. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_adaptive_must_support_test.rb +45 -0
  79. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_base_must_support_test.rb +43 -0
  80. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_standard_must_support_test.rb +45 -0
  81. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/next_question_template_questionnaires.rb +21 -0
  82. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/request/dtr_next_question_request_validation_test.rb +85 -0
  83. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/request/dtr_questionnaire_package_request_validation_test.rb +89 -0
  84. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/response/dtr_next_question_response_validation_test.rb +85 -0
  85. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/response/dtr_questionnaire_package_response_validation_test.rb +77 -0
  86. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/workflows/dtr_full_ehr_workflow_adaptive_group.rb +24 -0
  87. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/workflows/dtr_full_ehr_workflow_standard_group.rb +21 -0
  88. data/lib/davinci_dtr_test_kit/generator/ig_metadata.rb +21 -0
  89. data/lib/davinci_dtr_test_kit/generator/profile_metadata_extractor.rb +57 -0
  90. data/lib/davinci_dtr_test_kit/generator.rb +117 -0
  91. data/lib/davinci_dtr_test_kit/igs/davinci_dtr_2.2.0.tgz +0 -0
  92. data/lib/davinci_dtr_test_kit/{dtr_options.rb → light_ehr/dtr_light_ehr_options.rb} +1 -1
  93. data/lib/davinci_dtr_test_kit/{dtr_light_ehr_suite.rb → light_ehr/v2.0.1/dtr_light_ehr_suite.rb} +21 -10
  94. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1}/dtr_light_ehr_supported_endpoints_group.rb +5 -5
  95. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1}/dtr_smart_ehr_launch.rb +3 -3
  96. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_read.rb +1 -1
  97. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_read.rb +1 -1
  98. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_read.rb +1 -1
  99. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_read.rb +1 -1
  100. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_read.rb +1 -1
  101. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_read.rb +1 -1
  102. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_create.rb +1 -1
  103. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_update.rb +1 -1
  104. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_read.rb +1 -1
  105. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_create.rb +1 -1
  106. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_read.rb +1 -1
  107. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_update.rb +1 -1
  108. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_read.rb +1 -1
  109. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/supported_endpoints}/dtr_light_ehr_supported_payers_accept_header_test.rb +3 -2
  110. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/supported_endpoints}/dtr_light_ehr_supported_payers_config_test.rb +2 -1
  111. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/supported_endpoints}/dtr_light_ehr_supported_payers_endpoint_test.rb +2 -1
  112. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/supported_endpoints}/dtr_light_ehr_supported_payers_use_test.rb +2 -1
  113. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/supported_endpoints}/dtr_light_ehr_supported_payers_user_response_test.rb +5 -3
  114. data/lib/davinci_dtr_test_kit/metadata.rb +13 -68
  115. data/lib/davinci_dtr_test_kit/requirements/davinci_dtr_test_kit_requirements.csv +216 -0
  116. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_full_ehr_requirements_coverage.csv +1 -1
  117. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_full_ehr_v220_requirements_coverage.csv +1 -0
  118. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_light_ehr_requirements_coverage.csv +1 -1
  119. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_payer_server_requirements_coverage.csv +1 -1
  120. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_payer_server_v220_requirements_coverage.csv +114 -0
  121. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_smart_app_requirements_coverage.csv +1 -1
  122. data/lib/davinci_dtr_test_kit/requirements/hl7.fhir.us.davinci-dtr_2.2.0_requirements.xlsx +0 -0
  123. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → server/endpoints}/next_question_proxy_endpoint.rb +2 -0
  124. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → server/endpoints}/questionnaire_package_proxy_endpoint.rb +2 -0
  125. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_libraries_test.rb +2 -1
  126. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_questionnaire_expressions_test.rb +2 -1
  127. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_questionnaire_extensions_test.rb +2 -1
  128. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_next_questionnaire_expressions_test.rb +2 -1
  129. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_next_questionnaire_extensions_test.rb +2 -1
  130. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_request_test.rb +2 -1
  131. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_request_validation_test.rb +3 -1
  132. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_bundles_validation_test.rb +3 -1
  133. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_search_validation_test.rb +3 -1
  134. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_validation_test.rb +4 -2
  135. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_request_validation_test.rb +3 -1
  136. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_response_validation_test.rb +3 -1
  137. data/lib/davinci_dtr_test_kit/{dtr_payer_server_suite.rb → server/v2.0.1/dtr_payer_server_suite.rb} +13 -10
  138. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1}/payer_server_adaptive_group.rb +13 -13
  139. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1}/payer_server_static_group.rb +6 -6
  140. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_libraries_test.rb +2 -1
  141. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_questionnaire_expressions_test.rb +2 -1
  142. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_questionnaire_extensions_test.rb +2 -1
  143. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_request_test.rb +4 -2
  144. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_request_validation_test.rb +3 -2
  145. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_response_validation_test.rb +5 -3
  146. data/lib/davinci_dtr_test_kit/server/v2.2.0/client_simulation.rb +297 -0
  147. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_capability_statement_test.rb +73 -0
  148. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_suite.rb +322 -0
  149. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_suite_description_v220.md +37 -0
  150. data/lib/davinci_dtr_test_kit/server/v2.2.0/interaction_test.rb +97 -0
  151. data/lib/davinci_dtr_test_kit/server/v2.2.0/log_questionnaire_errors_support_test.rb +57 -0
  152. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_adaptive_must_support_test.rb +47 -0
  153. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_adaptive_search_must_support_test.rb +40 -0
  154. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_base_must_support_test.rb +40 -0
  155. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_package_bundle_must_support_test.rb +38 -0
  156. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_package_output_parameters_must_support_test.rb +37 -0
  157. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_standard_must_support_test.rb +39 -0
  158. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_request_validation_test.rb +45 -0
  159. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/adaptive_questionnaire_endpoint_test.rb +98 -0
  160. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/invalid_questionnaire_response_test.rb +43 -0
  161. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_contained_questionnaire_response_references_test.rb +46 -0
  162. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_question_response_references_test.rb +56 -0
  163. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_question_response_validation_test.rb +67 -0
  164. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/contained_binary_test.rb +58 -0
  165. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/contained_binary_validation.rb +128 -0
  166. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/cql_library_validation_test.rb +58 -0
  167. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_design_support.rb +65 -0
  168. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_expression_elm_test.rb +81 -0
  169. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_expression_language_test.rb +63 -0
  170. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_prepopulation_test.rb +42 -0
  171. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_relevance_logic_test.rb +40 -0
  172. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_operation_validation.rb +440 -0
  173. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_request_validation_test.rb +42 -0
  174. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/adaptive_questionnaire_response_contained_questionnaire_test.rb +127 -0
  175. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/adaptive_questionnaire_response_validation_test.rb +61 -0
  176. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/contained_questionnaire_response_references_test.rb +42 -0
  177. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_no_custom_extension_test.rb +184 -0
  178. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_questionnaire_not_found_test.rb +76 -0
  179. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_questionnaire_package_contents_test.rb +89 -0
  180. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/initial_questionnaire_response_test.rb +132 -0
  181. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_package_input_type_test.rb +110 -0
  182. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_references_version_specific_test.rb +79 -0
  183. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_questionnaire_canonical_test.rb +89 -0
  184. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_references_test.rb +51 -0
  185. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_validation_test.rb +63 -0
  186. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/source_data_error_test.rb +43 -0
  187. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/value_set_validation_test.rb +90 -0
  188. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_response_reference_validation.rb +133 -0
  189. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/small_value_set_expansion_test.rb +120 -0
  190. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/value_set_expansion_test.rb +51 -0
  191. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/value_set_expansion_validation.rb +58 -0
  192. data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization/token_endpoint.rb +1 -1
  193. data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr/fhir_get_endpoint.rb +1 -1
  194. data/lib/davinci_dtr_test_kit/smart_app/endpoints/mock_payer/smart_app_next_question_endpoint.rb +12 -0
  195. data/lib/davinci_dtr_test_kit/smart_app/endpoints/mock_payer/smart_app_questionnaire_package_endpoint.rb +12 -0
  196. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → smart_app/v2.0.1/adaptive_custom}/dtr_smart_app_custom_adaptive_workflow_group.rb +17 -15
  197. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → smart_app/v2.0.1/adaptive_dinner}/dtr_smart_app_adaptive_dinner_workflow_group.rb +5 -5
  198. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → smart_app/v2.0.1/adaptive_dinner}/dtr_smart_app_adaptive_initial_retrieval_group.rb +4 -4
  199. data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1/auth}/token_request_test.rb +1 -1
  200. data/lib/davinci_dtr_test_kit/{client_groups/custom_static → smart_app/v2.0.1}/dtr_smart_app_custom_static_workflow_group.rb +11 -11
  201. data/lib/davinci_dtr_test_kit/{client_groups/must_support → smart_app/v2.0.1}/dtr_smart_app_questionnaire_must_support_group.rb +8 -7
  202. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1}/dtr_smart_app_respiratory_workflow_group.rb +3 -3
  203. data/lib/davinci_dtr_test_kit/{client_groups/dinner_static → smart_app/v2.0.1}/dtr_smart_app_static_dinner_workflow_group.rb +7 -7
  204. data/lib/davinci_dtr_test_kit/{dtr_smart_app_suite.rb → smart_app/v2.0.1/dtr_smart_app_suite.rb} +25 -21
  205. data/lib/davinci_dtr_test_kit/{docs → smart_app/v2.0.1}/dtr_smart_app_suite_description_v201.md +8 -0
  206. data/lib/davinci_dtr_test_kit/{client_groups → smart_app/v2.0.1}/must_support/dtr_smart_app_ms_questionnaire_package_request_test.rb +2 -2
  207. data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1}/oauth2_authentication_group.rb +2 -2
  208. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_package_group.rb +1 -1
  209. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_package_request_test.rb +1 -1
  210. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_response_group.rb +2 -2
  211. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_response_save_test.rb +1 -1
  212. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_rendering_attestation_test.rb +1 -1
  213. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_adaptive_request_test.rb +1 -1
  214. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_prepopulation_attestation_test.rb +1 -1
  215. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_prepopulation_override_attestation_test.rb +1 -1
  216. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_questionnaire_package_request_test.rb +1 -1
  217. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_questionnaire_response_correctness_test.rb +1 -1
  218. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_questionnaire_response_save_test.rb +1 -1
  219. data/lib/davinci_dtr_test_kit/{client_groups/smart_app → smart_app/v2.0.1/tests}/dtr_smart_app_saving_questionnaire_response_group.rb +1 -1
  220. data/lib/davinci_dtr_test_kit/tags.rb +2 -0
  221. data/lib/davinci_dtr_test_kit/version.rb +2 -2
  222. data/lib/davinci_dtr_test_kit.rb +6 -4
  223. metadata +329 -215
  224. data/lib/davinci_dtr_test_kit/certs/InfernoCA.key +0 -52
  225. data/lib/davinci_dtr_test_kit/certs/InfernoCA.pem +0 -35
  226. data/lib/davinci_dtr_test_kit/certs/TestKit.pem +0 -32
  227. data/lib/davinci_dtr_test_kit/certs/TestKitPrivateKey.key +0 -28
  228. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +0 -30
  229. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +0 -31
  230. data/lib/davinci_dtr_test_kit/fixture_loader.rb +0 -21
  231. /data/lib/davinci_dtr_test_kit/{endpoints → cross_suite}/cors.rb +0 -0
  232. /data/lib/davinci_dtr_test_kit/{dtr_questionnaire_response_validation.rb → cross_suite/v2.0.1/dtr_questionnaire_response_validation.rb} +0 -0
  233. /data/lib/davinci_dtr_test_kit/{descriptions.rb → full_ehr/descriptions.rb} +0 -0
  234. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +0 -0
  235. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +0 -0
  236. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +0 -0
  237. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/questionnaire_dinner_order_adaptive.json +0 -0
  238. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_static/questionnaire_dinner_order_static.json +0 -0
  239. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_static/questionnaire_response_dinner_order_static.json +0 -0
  240. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/respiratory_assist_device/pre_populated_questionnaire_response.json +0 -0
  241. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/respiratory_assist_device/questionnaire_package.json +0 -0
  242. /data/lib/davinci_dtr_test_kit/{fixtures.rb → full_ehr/fixtures.rb} +0 -0
  243. /data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → full_ehr/v2.0.1/adaptive_dinner}/dtr_adaptive_completion_group.rb +0 -0
  244. /data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/dinner_order → full_ehr/v2.0.1/adaptive_dinner}/dtr_adaptive_followup_questions_group.rb +0 -0
  245. /data/lib/davinci_dtr_test_kit/{client_groups/auth → full_ehr/v2.0.1}/dtr_client_payer_auth_smart_group.rb +0 -0
  246. /data/lib/davinci_dtr_test_kit/{client_groups/auth → full_ehr/v2.0.1}/dtr_client_payer_auth_udap_group.rb +0 -0
  247. /data/lib/davinci_dtr_test_kit/{docs → full_ehr/v2.0.1}/dtr_full_ehr_suite_description_v201.md +0 -0
  248. /data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/questionnaire_must_support_elements.rb +0 -0
  249. /data/lib/davinci_dtr_test_kit/{client_groups/full_ehr → full_ehr/v2.0.1/shared}/dtr_full_ehr_saving_questionnaire_response_group.rb +0 -0
  250. /data/lib/davinci_dtr_test_kit/{create_test.rb → light_ehr/create_test.rb} +0 -0
  251. /data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → light_ehr/endpoints}/light_ehr_supported_payer_endpoint.rb +0 -0
  252. /data/lib/davinci_dtr_test_kit/{read_test.rb → light_ehr/read_test.rb} +0 -0
  253. /data/lib/davinci_dtr_test_kit/{update_test.rb → light_ehr/update_test.rb} +0 -0
  254. /data/lib/davinci_dtr_test_kit/{docs → light_ehr/v2.0.1}/dtr_light_ehr_suite_description_v201.md +0 -0
  255. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_must_support_test.rb +0 -0
  256. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_validation.rb +0 -0
  257. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/metadata.yml +0 -0
  258. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request_group.rb +0 -0
  259. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_must_support_test.rb +0 -0
  260. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_validation.rb +0 -0
  261. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/metadata.yml +0 -0
  262. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage_group.rb +0 -0
  263. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_must_support_test.rb +0 -0
  264. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_validation.rb +0 -0
  265. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/metadata.yml +0 -0
  266. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request_group.rb +0 -0
  267. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_must_support_test.rb +0 -0
  268. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_validation.rb +0 -0
  269. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/metadata.yml +0 -0
  270. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter_group.rb +0 -0
  271. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_must_support_test.rb +0 -0
  272. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_validation.rb +0 -0
  273. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/metadata.yml +0 -0
  274. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request_group.rb +0 -0
  275. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/metadata.yml +0 -0
  276. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_must_support_test.rb +0 -0
  277. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_validation.rb +0 -0
  278. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order_group.rb +0 -0
  279. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/metadata.yml +0 -0
  280. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_context_search.rb +0 -0
  281. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_must_support_test.rb +0 -0
  282. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_patient_search.rb +0 -0
  283. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_read.rb +0 -0
  284. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_validation.rb +0 -0
  285. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response_group.rb +0 -0
  286. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/metadata.yml +0 -0
  287. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_must_support_test.rb +0 -0
  288. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_validation.rb +0 -0
  289. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request_group.rb +0 -0
  290. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/metadata.yml +0 -0
  291. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_must_support_test.rb +0 -0
  292. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_validation.rb +0 -0
  293. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task_group.rb +0 -0
  294. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/metadata.yml +0 -0
  295. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_must_support_test.rb +0 -0
  296. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_validation.rb +0 -0
  297. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription_group.rb +0 -0
  298. /data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/smart_ehr_launch}/fhir_context_coverage_test.rb +0 -0
  299. /data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/smart_ehr_launch}/fhir_context_references_test.rb +0 -0
  300. /data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1/smart_ehr_launch}/fhir_launch_context_test.rb +0 -0
  301. /data/lib/davinci_dtr_test_kit/{endpoints/mock_authorization → server/endpoints}/simple_token_endpoint.rb +0 -0
  302. /data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_response_complete_test.rb +0 -0
  303. /data/lib/davinci_dtr_test_kit/{docs → server/v2.0.1}/dtr_payer_server_suite_description_v201.md +0 -0
  304. /data/lib/davinci_dtr_test_kit/{validation_test.rb → server/validation_test.rb} +0 -0
  305. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization/authorize_endpoint.rb +0 -0
  306. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization.rb +0 -0
  307. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr/questionnaire_response_endpoint.rb +0 -0
  308. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr.rb +0 -0
  309. /data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → smart_app/v2.0.1/adaptive_custom}/dtr_smart_app_custom_adaptive_request_test.rb +0 -0
  310. /data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1/auth}/token_validation_test.rb +0 -0
  311. /data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_rendering_group.rb +0 -0
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../questionnaire_response_reference_validation'
4
+ require_relative '../../../cross_suite/v2.2.0/multi_request_message_helper'
5
+ require_relative '../../../tags'
6
+
7
+ module DaVinciDTRTestKit
8
+ module DTRPayerServerV220
9
+ class NextQuestionContainedResponseReferencesTest < Inferno::Test
10
+ include QuestionnaireResponseReferenceValidation
11
+ include MultiRequestMessageHelper
12
+
13
+ id :dtr_v220_payer_next_question_contained_response_references
14
+ title 'Contained $next-question QuestionnaireResponse references occur only in answer values'
15
+ description %(
16
+ This test verifies that a QuestionnaireResponse returned by `$next-question` uses
17
+ contained resource references only as
18
+ `QuestionnaireResponse.item.answer.valueReference` values.
19
+ )
20
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-140',
21
+ 'hl7.fhir.us.davinci-dtr_2.2.0@spec-141'
22
+
23
+ run do
24
+ load_tagged_requests(NEXT_TAG)
25
+
26
+ omit_if requests.blank?, 'No $next-question requests were made.'
27
+
28
+ responses_by_request = requests.map { |request| questionnaire_responses_from_request(request) }
29
+
30
+ skip_if responses_by_request.all?(&:empty?), 'No QuestionnaireResponse resources were returned.'
31
+
32
+ responses_by_request.each_with_index do |questionnaire_responses, request_index|
33
+ questionnaire_responses.each do |questionnaire_response|
34
+ invalid_contained_reference_locations(questionnaire_response).each do |reference|
35
+ add_request_message('error', reference, request_index)
36
+ end
37
+ end
38
+ end
39
+
40
+ message = "#{requests_with_errors_prefix}" \
41
+ 'Contained resource references are permitted only in item.answer valueReference '
42
+ assert_no_error_messages("#{message}elements. See Messages for details.")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../questionnaire_response_reference_validation'
4
+ require_relative '../../../cross_suite/v2.2.0/multi_request_message_helper'
5
+ require_relative '../../../tags'
6
+
7
+ module DaVinciDTRTestKit
8
+ module DTRPayerServerV220
9
+ class NextQuestionResponseReferencesTest < Inferno::Test
10
+ include QuestionnaireResponseReferenceValidation
11
+ include MultiRequestMessageHelper
12
+
13
+ id :dtr_v220_payer_next_question_response_references
14
+ title '$next-question QuestionnaireResponse references only target contained or client FHIR resources'
15
+ description %(
16
+ This test verifies that every reference in each QuestionnaireResponse returned by
17
+ `$next-question` points to either a resource contained in that QuestionnaireResponse
18
+ or a resource on the DTR client's FHIR endpoint. Relative references are interpreted
19
+ relative to the DTR client's FHIR endpoint. To validate absolute references, provide
20
+ the DTR Client FHIR Endpoint input.
21
+ )
22
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-139'
23
+
24
+ input :client_fhir_endpoint, optional: true
25
+
26
+ run do
27
+ load_tagged_requests(NEXT_TAG)
28
+
29
+ omit_if requests.blank?, 'No $next-question requests were made.'
30
+
31
+ responses_by_request = requests.map { |request| questionnaire_responses_from_request(request) }
32
+
33
+ skip_if responses_by_request.all?(&:empty?), 'No QuestionnaireResponse resources were returned.'
34
+
35
+ absolute_references_returned = responses_by_request.flatten.any? do |response|
36
+ questionnaire_response_has_absolute_reference?(response)
37
+ end
38
+
39
+ responses_by_request.each_with_index do |questionnaire_responses, request_index|
40
+ questionnaire_responses.each do |questionnaire_response|
41
+ invalid_questionnaire_response_references(questionnaire_response, client_fhir_endpoint).each do |reference|
42
+ add_request_message('error', reference, request_index)
43
+ end
44
+ end
45
+ end
46
+
47
+ message = "#{requests_with_errors_prefix}" \
48
+ "References must target contained resources or the DTR client's FHIR endpoint. "
49
+ assert_no_error_messages("#{message}See Messages for details.")
50
+
51
+ skip_if client_fhir_endpoint.blank? && absolute_references_returned,
52
+ 'Absolute QuestionnaireResponse references were returned, but no DTR Client FHIR Endpoint was provided.'
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../tags'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ class NextQuestionResponseValidationTest < Inferno::Test
8
+ NEXT_QUESTION_OUTPUT_PARAMETERS_PROFILE =
9
+ 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-next-question-output-parameters|2.2.0'
10
+ ADAPTIVE_QUESTIONNAIRE_RESPONSE_PROFILE =
11
+ 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-questionnaireresponse-adapt|2.2.0'
12
+
13
+ id :dtr_v220_payer_next_question_response_validation
14
+ title 'Verify that the $next-question response conforms to the DTR Next Question Output Parameters profile'
15
+ description %(
16
+ Inferno verifies that each payer server response to the `$next-question`
17
+ operation conforms to the [DTR Next Question Output Parameters profile](https://hl7.org/fhir/us/davinci-dtr/2.2.0/en/StructureDefinition-dtr-next-question-output-parameters.html)
18
+ when it is a Parameters resource, or to the [DTR Questionnaire Response
19
+ for adaptive form profile](https://hl7.org/fhir/us/davinci-dtr/2.2.0/en/StructureDefinition-dtr-questionnaireresponse-adapt.html)
20
+ when it is a plain QuestionnaireResponse resource.
21
+ )
22
+
23
+ run do
24
+ load_tagged_requests(NEXT_TAG)
25
+
26
+ omit_if requests.blank?, 'No $next-question requests were made.'
27
+
28
+ requests.each_with_index do |request, index|
29
+ add_message('error', "Request #{index + 1} was unsuccessful.") unless [200, 201].include? request.status
30
+
31
+ JSON.parse(request.response_body)
32
+ resource = FHIR.from_contents(request.response_body)
33
+
34
+ if resource.nil?
35
+ add_message('error', "Response #{index + 1} did not contain FHIR resources.")
36
+ next
37
+ end
38
+
39
+ perform_next_question_response_validation(resource, index)
40
+ rescue JSON::ParserError
41
+ add_message('error', "Response #{index + 1} contained invalid JSON.")
42
+ end
43
+
44
+ assert_no_error_messages('Not all responses were valid. See messages for details.')
45
+ end
46
+
47
+ def perform_next_question_response_validation(resource, index)
48
+ case resource
49
+ when FHIR::Parameters
50
+ resource_is_valid?(
51
+ resource:,
52
+ profile_url: NEXT_QUESTION_OUTPUT_PARAMETERS_PROFILE,
53
+ message_prefix: "Response #{index + 1}: "
54
+ )
55
+ when FHIR::QuestionnaireResponse
56
+ resource_is_valid?(
57
+ resource:,
58
+ profile_url: ADAPTIVE_QUESTIONNAIRE_RESPONSE_PROFILE,
59
+ message_prefix: "Response #{index + 1}: "
60
+ )
61
+ else
62
+ add_message('error', "Response #{index + 1} was not a Parameters or QuestionnaireResponse resource.")
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../../../tags'
2
+ require_relative '../questionnaire_response_reference_validation'
3
+ require_relative 'contained_binary_validation'
4
+ require_relative '../../../cross_suite/v2.2.0/multi_request_message_helper'
5
+
6
+ module DaVinciDTRTestKit
7
+ module DTRPayerServerV220
8
+ class ContainedBinaryTest < Inferno::Test
9
+ include ContainedBinaryValidation
10
+ include MultiRequestMessageHelper
11
+ include QuestionnaireResponseReferenceValidation
12
+
13
+ id :dtr_v220_payer_contained_binary
14
+ title 'Contained Binary resources are PDFs or safe XHTML'
15
+ description %(
16
+ This test verifies that Binary resources contained in QuestionnaireResponses
17
+ returned from the `$questionnaire-package` or `$next-question` operations are
18
+ either PDFs or XHTML fragments that follow the FHIR R4 Narrative safety rules.
19
+ XHTML must be a non-empty `<div>` fragment in the XHTML namespace and must not
20
+ contain active content, scripts, external stylesheets, deprecated elements, or
21
+ event-related attributes.
22
+ )
23
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-160'
24
+
25
+ run do
26
+ load_tagged_requests(QUESTIONNAIRE_TAG)
27
+ load_tagged_requests(NEXT_TAG)
28
+ omit_if requests.blank?,
29
+ 'No $questionnaire-package or $next-question requests were made'
30
+
31
+ binary_found = false
32
+ requests.each_with_index do |request, request_index|
33
+ questionnaire_responses_from_request(request).each do |questionnaire_response|
34
+ contained_binaries([questionnaire_response]).each do |binary|
35
+ binary_found = true
36
+ next if contained_binary_is_safe?(binary)
37
+
38
+ add_request_message(
39
+ 'error',
40
+ "#{binary_description(binary)} is not a PDF or safe XHTML fragment.",
41
+ request_index
42
+ )
43
+ end
44
+ end
45
+ end
46
+
47
+ omit_if !binary_found, 'No Binary resources were contained in QuestionnaireResponses'
48
+ message = "#{requests_with_errors_prefix}" \
49
+ 'Contained Binary resources must be PDFs or safe XHTML fragments. See Messages for details.'
50
+ assert_no_error_messages(message)
51
+ end
52
+
53
+ def binary_description(binary)
54
+ binary.id.present? ? "Binary `#{binary.id}`" : 'contained Binary without an id'
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,128 @@
1
+ require 'base64'
2
+ require 'nokogiri'
3
+
4
+ module DaVinciDTRTestKit
5
+ module DTRPayerServerV220
6
+ module ContainedBinaryValidation
7
+ PDF_CONTENT_TYPE = 'application/pdf'.freeze
8
+ XHTML_CONTENT_TYPE = 'application/xhtml+xml'.freeze
9
+ XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'.freeze
10
+
11
+ # TODO: Review the FHIR-referenced HTML 4.0 chapters in detail and determine
12
+ # whether this validator needs additional allowed-element or allowed-attribute handling.
13
+ #
14
+ # This validator interprets Binary XHTML according to the FHIR R4 Narrative
15
+ # fragment rules. It enforces the explicitly prohibited elements and
16
+ # attributes, but does not yet attempt a comprehensive HTML allowlist.
17
+ # https://hl7.org/fhir/R4/narrative.html#security
18
+ #
19
+ # "The XHTML content SHALL NOT contain a head, a body element,
20
+ # external stylesheet references, deprecated elements, scripts,
21
+ # forms, base/link/xlink, frames, iframes, objects or
22
+ # event related attributes (e.g. onClick)."
23
+ PROHIBITED_ELEMENTS = %w[
24
+ base body form frame frameset head iframe input link object script style
25
+ ].freeze
26
+ # HTML 4.0 deprecated elements: https://www.w3.org/TR/REC-html40-971218/appendix/changes.html#h-A.1.2
27
+ DEPRECATED_ELEMENTS = %w[applet basefont center dir font isindex menu s strike u].freeze
28
+ EXECUTABLE_URL_SCHEMES = %w[javascript vbscript].freeze
29
+
30
+ def contained_binaries(questionnaire_responses)
31
+ questionnaire_responses.flat_map do |questionnaire_response|
32
+ questionnaire_response.contained&.grep(FHIR::Binary) || []
33
+ end
34
+ end
35
+
36
+ def contained_binary_is_safe?(binary)
37
+ return true if binary.contentType == PDF_CONTENT_TYPE
38
+ return false unless binary.contentType == XHTML_CONTENT_TYPE
39
+
40
+ safe_xhtml?(Base64.strict_decode64(binary.data.to_s))
41
+ rescue ArgumentError
42
+ false
43
+ end
44
+
45
+ def safe_xhtml?(xhtml)
46
+ document = parse_xhtml(xhtml)
47
+
48
+ narrative_fragment?(document) &&
49
+ document.errors.empty? &&
50
+ narrative_has_content?(document) &&
51
+ document_has_no_unsafe_content?(document)
52
+ rescue Nokogiri::XML::SyntaxError
53
+ false
54
+ end
55
+
56
+ private
57
+
58
+ def parse_xhtml(xhtml)
59
+ # Strict parsing rejects malformed XHTML. `nonet` prevents XML from
60
+ # loading any network resources while it is being parsed.
61
+ Nokogiri::XML::Document.parse(xhtml) { |config| config.strict.nonet }
62
+ end
63
+
64
+ def document_has_no_unsafe_content?(document)
65
+ # Inspect every nested XHTML element, including elements in the default
66
+ # XHTML namespace which a non-namespaced XPath would not reliably select.
67
+ document.root.traverse do |node|
68
+ return false if node.element? && unsafe_xhtml_element?(node)
69
+ end
70
+
71
+ true
72
+ end
73
+
74
+ def narrative_fragment?(document)
75
+ # FHIR Narrative XHTML is represented as a div fragment in the XHTML namespace,
76
+ # rather than as a complete HTML document.
77
+ document.root&.name == 'div' && document.root.namespace&.href == XHTML_NAMESPACE
78
+ end
79
+
80
+ def narrative_has_content?(document)
81
+ # FHIR Narrative requires non-whitespace text or an image in the div fragment.
82
+ !document.root.text.strip.empty? ||
83
+ !document.root.at_xpath('.//xhtml:img', xhtml: XHTML_NAMESPACE).nil?
84
+ end
85
+
86
+ def unsafe_xhtml_element?(element)
87
+ prohibited_element?(element) ||
88
+ deprecated_element?(element) ||
89
+ xlink_node?(element) ||
90
+ element.attribute_nodes.any? { |attribute| unsafe_xhtml_attribute?(attribute) }
91
+ end
92
+
93
+ def prohibited_element?(element)
94
+ PROHIBITED_ELEMENTS.include?(element.name.downcase)
95
+ end
96
+
97
+ def deprecated_element?(element)
98
+ DEPRECATED_ELEMENTS.include?(element.name.downcase)
99
+ end
100
+
101
+ def xlink_node?(node)
102
+ # xlink is an XML namespace, so it can qualify either an element or an
103
+ # attribute (for example, xlink:href) rather than appearing as an HTML element.
104
+ node.namespace&.prefix == 'xlink'
105
+ end
106
+
107
+ def unsafe_xhtml_attribute?(attribute)
108
+ # In XHTML, event handlers are attributes beginning with `on`, such as
109
+ # `onclick`. They run JavaScript when the corresponding browser event occurs.
110
+ return true if attribute.name.match?(/\Aon/i)
111
+
112
+ return true if xlink_node?(attribute)
113
+
114
+ # `href` and `src` are the XHTML attributes that direct a browser to
115
+ # navigate to or load a URL. Other attributes cannot invoke a URL scheme.
116
+ return false unless %w[href src].include?(attribute.name.downcase)
117
+
118
+ # `javascript:` and `vbscript:` URLs execute code when followed instead
119
+ # of loading a document or image.
120
+ EXECUTABLE_URL_SCHEMES.include?(url_scheme(attribute.value))
121
+ end
122
+
123
+ def url_scheme(url)
124
+ url.to_s.strip.partition(':').first.downcase
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../../../tags'
2
+ require_relative '../questionnaire_operation_validation'
3
+
4
+ module DaVinciDTRTestKit
5
+ module DTRPayerServerV220
6
+ class CQLLibraryValidationTest < Inferno::Test
7
+ include QuestionnaireOperationValidation
8
+
9
+ id :dtr_v220_payer_cql_library_validation
10
+
11
+ title 'All referenced CQL Libraries are included'
12
+ description %(
13
+ Inferno will verify that the payer server's response to the
14
+ questionnaire-package operation includes all CQL Libraries referenced in
15
+ the returned Questionnaires.
16
+ )
17
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-87',
18
+ 'hl7.fhir.us.davinci-dtr_2.2.0@spec-95',
19
+ 'hl7.fhir.us.davinci-dtr_2.2.0@spec-98',
20
+ 'hl7.fhir.us.davinci-dtr_2.2.0@spec-99',
21
+ 'hl7.fhir.us.davinci-dtr_2.2.0@oper-13',
22
+ 'hl7.fhir.us.davinci-dtr_2.2.0@oper-16'
23
+
24
+ run do
25
+ load_tagged_requests(QUESTIONNAIRE_TAG)
26
+
27
+ successful_requests = requests.select { |request| [200, 201].include? request.response[:status] }
28
+
29
+ skip_if successful_requests.blank?, 'No successful $questionnaire-package requests were made'
30
+
31
+ library_count = 0
32
+
33
+ successful_requests.each_with_index do |request, index|
34
+ JSON.parse(request.response_body)
35
+
36
+ resource = FHIR.from_contents(request.response_body)
37
+
38
+ next if resource.nil?
39
+
40
+ questionnaire_bundles = extract_questionnaire_bundles(resource)
41
+ libraries = extract_libraries_from_bundles(questionnaire_bundles)
42
+
43
+ next if libraries.blank?
44
+
45
+ check_libraries(resource, index)
46
+
47
+ library_count += libraries.length
48
+ rescue JSON::ParserError
49
+ next
50
+ end
51
+
52
+ assert_no_error_messages('Not all responses contained all necessary valid CQL Libraries.')
53
+
54
+ omit_if library_count.zero?, 'No CQL libraries were found.'
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../tags'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ module QuestionnaireDesignSupport
8
+ CQL_MEDIA_TYPES = [
9
+ 'text/cql',
10
+ 'text/cql-expression',
11
+ 'text/cql-identifier'
12
+ ].freeze
13
+
14
+ private
15
+
16
+ # Returns a Hash for each Questionnaire returned in a tagged response:
17
+ # { questionnaire:, operation:, request_index: }
18
+ # request_index is scoped independently to each operation.
19
+ def returned_questionnaires
20
+ questionnaires_from_requests(load_tagged_requests(QUESTIONNAIRE_TAG), '$questionnaire-package') +
21
+ questionnaires_from_requests(load_tagged_requests(NEXT_TAG), '$next-question')
22
+ end
23
+
24
+ def questionnaires_from_requests(requests, operation)
25
+ requests.each_with_index.flat_map do |request, request_index|
26
+ next [] if request.response_body.blank?
27
+
28
+ resource = FHIR.from_contents(request.response_body)
29
+ questionnaires_from_resource(resource).map do |questionnaire|
30
+ { questionnaire:, operation:, request_index: }
31
+ end
32
+ rescue JSON::ParserError, FHIR::ClientException
33
+ []
34
+ end
35
+ end
36
+
37
+ def questionnaires_from_resource(resource)
38
+ case resource.resourceType
39
+ when 'Questionnaire'
40
+ [resource]
41
+ when 'QuestionnaireResponse'
42
+ resource.contained.grep(FHIR::Questionnaire)
43
+ when 'Bundle'
44
+ questionnaires_from_resources(resource.entry.map(&:resource))
45
+ when 'Parameters'
46
+ questionnaires_from_resources(resource.parameter.map(&:resource))
47
+ else
48
+ []
49
+ end
50
+ end
51
+
52
+ def questionnaires_from_resources(resources)
53
+ resources.compact.flat_map { |resource| questionnaires_from_resource(resource) }
54
+ end
55
+
56
+ def questionnaire_items(questionnaire)
57
+ questionnaire.item.flat_map { |item| [item] + questionnaire_items(item) }
58
+ end
59
+
60
+ def cql_expression?(expression)
61
+ CQL_MEDIA_TYPES.include?(expression.language.to_s.split(';').first.strip)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'questionnaire_design_support'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ class QuestionnaireExpressionElmTest < Inferno::Test
8
+ include QuestionnaireDesignSupport
9
+
10
+ ALTERNATIVE_EXPRESSION_URL = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/alternativeExpression'
11
+
12
+ id :dtr_v220_payer_questionnaire_expression_elm
13
+ title 'Questionnaire expressions include compiled JSON ELM'
14
+ description %(
15
+ Inferno verifies that each Expression in the returned Questionnaires has
16
+ an Alternative Expression extension containing compiled JSON ELM.
17
+ )
18
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-96'
19
+
20
+ run do
21
+ questionnaire_details = returned_questionnaires
22
+ skip_if questionnaire_details.blank?, 'No Questionnaire resources were returned'
23
+
24
+ cql_expressions = questionnaire_details.flat_map { |details| cql_questionnaire_expressions(details) }
25
+ omit_if cql_expressions.blank?, 'No CQL expressions were found'
26
+
27
+ expressions_without_elm = cql_expressions.reject do |details|
28
+ alternative_expression_present?(details[:expression])
29
+ end
30
+
31
+ expressions_without_elm.each do |details|
32
+ add_message(
33
+ 'error',
34
+ "#{details[:location]} does not include an Alternative Expression extension with compiled JSON ELM."
35
+ )
36
+ end
37
+
38
+ assert expressions_without_elm.blank?,
39
+ 'One or more CQL expressions did not include compiled JSON ELM. See messages for details.'
40
+ end
41
+
42
+ private
43
+
44
+ def cql_questionnaire_expressions(details)
45
+ questionnaire = details[:questionnaire]
46
+ cql_expressions_from_extensions(questionnaire.extension, details, 'Questionnaire-level extension') +
47
+ questionnaire_items(questionnaire).flat_map do |item|
48
+ cql_expressions_from_extensions(item.extension, details, "linkId `#{item.linkId}`")
49
+ end
50
+ end
51
+
52
+ def cql_expressions_from_extensions(extensions, details, location)
53
+ extensions.flat_map do |extension|
54
+ expressions = []
55
+ if extension.valueExpression.present? && cql_expression?(extension.valueExpression)
56
+ expressions << {
57
+ expression: extension.valueExpression,
58
+ location: "#{request_location(details)}, #{location}"
59
+ }
60
+ end
61
+ expressions.concat(cql_expressions_from_extensions(extension.extension, details, location))
62
+ end
63
+ end
64
+
65
+ def request_location(details)
66
+ "#{details[:operation]} request #{details[:request_index] + 1}"
67
+ end
68
+
69
+ def alternative_expression_present?(expression)
70
+ expression.extension.any? do |extension|
71
+ extension.url == ALTERNATIVE_EXPRESSION_URL && expression_contains_elm?(extension.valueExpression)
72
+ end
73
+ end
74
+
75
+ def expression_contains_elm?(expression)
76
+ expression&.language == 'application/elm+json' &&
77
+ (expression&.expression.present? || extension.valueExpression&.reference.present?)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'questionnaire_design_support'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ class QuestionnaireExpressionLanguageTest < Inferno::Test
8
+ include QuestionnaireDesignSupport
9
+
10
+ id :dtr_v220_payer_questionnaire_expression_language
11
+ title 'Questionnaire flow and rendering expressions use CQL'
12
+ description %(
13
+ Inferno verifies that Expression-valued Questionnaire item extensions are
14
+ written in CQL. This requirement is conditional and is omitted when no
15
+ such expressions are present.
16
+ )
17
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-18'
18
+
19
+ run do
20
+ questionnaire_details = returned_questionnaires
21
+ skip_if questionnaire_details.blank?, 'No Questionnaire resources were returned'
22
+
23
+ expressions = questionnaire_details.flat_map { |details| questionnaire_item_expressions(details) }
24
+ omit_if expressions.blank?, 'No flow or rendering expressions were found'
25
+
26
+ non_cql_expressions = expressions.reject do |details|
27
+ cql_expression?(details[:expression])
28
+ end
29
+ non_cql_details = non_cql_expressions.map do |details|
30
+ language = details[:expression].language.presence || 'missing'
31
+ "#{request_location(details[:request_details])} linkId `#{details[:link_id]}` (language `#{language}`)"
32
+ end
33
+
34
+ assert non_cql_expressions.blank?,
35
+ "The following flow or rendering expressions were not written in CQL: #{non_cql_details.join(', ')}"
36
+ end
37
+
38
+ private
39
+
40
+ def questionnaire_item_expressions(details)
41
+ questionnaire = details[:questionnaire]
42
+ questionnaire_items(questionnaire).flat_map do |item|
43
+ item.extension.flat_map do |extension|
44
+ expressions_from_extension(extension).map do |expression|
45
+ { expression:, link_id: item.linkId, request_details: details }
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def expressions_from_extension(extension)
52
+ [
53
+ extension.valueExpression,
54
+ *extension.extension.flat_map { |nested_extension| expressions_from_extension(nested_extension) }
55
+ ].compact
56
+ end
57
+
58
+ def request_location(details)
59
+ "#{details[:operation]} request #{details[:request_index] + 1}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'questionnaire_design_support'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ class QuestionnairePrepopulationTest < Inferno::Test
8
+ include QuestionnaireDesignSupport
9
+
10
+ POPULATION_EXPRESSION_URLS = [
11
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression',
12
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression',
13
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression'
14
+ ].freeze
15
+
16
+ id :dtr_v220_payer_questionnaire_prepopulation
17
+ title 'Questionnaires support EHR prepopulation'
18
+ description %(
19
+ Inferno verifies that, across all Questionnaires returned by the DTR server,
20
+ at least one includes an extension indicating support for population from
21
+ EHR data.
22
+ )
23
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-54'
24
+
25
+ run do
26
+ questionnaires = returned_questionnaires.map { |details| details[:questionnaire] }
27
+ skip_if questionnaires.blank?, 'No Questionnaire resources were returned'
28
+
29
+ assert questionnaires.any? { |questionnaire| questionnaire_has_prepopulation_logic?(questionnaire) },
30
+ 'No Questionnaire included logic supporting population from the EHR.'
31
+ end
32
+
33
+ private
34
+
35
+ def questionnaire_has_prepopulation_logic?(questionnaire)
36
+ questionnaire_items(questionnaire).any? do |item|
37
+ item.extension.any? { |extension| POPULATION_EXPRESSION_URLS.include?(extension.url) }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end