davinci_dtr_test_kit 0.17.1 → 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/cross_suite/v2.2.0/dtr_conformance_verification.rb +21 -0
  15. data/lib/davinci_dtr_test_kit/cross_suite/v2.2.0/multi_request_message_helper.rb +35 -0
  16. data/lib/davinci_dtr_test_kit/cross_suite/v2.2.0/questionnaire_helper.rb +162 -0
  17. data/lib/davinci_dtr_test_kit/{dtr_client_options.rb → full_ehr/dtr_full_ehr_options.rb} +1 -1
  18. data/lib/davinci_dtr_test_kit/{endpoints → full_ehr/endpoints}/mock_payer.rb +9 -3
  19. data/lib/davinci_dtr_test_kit/{endpoints → full_ehr/endpoints}/mock_udap_smart_server/token_endpoint.rb +2 -2
  20. data/lib/davinci_dtr_test_kit/full_ehr/fixture_loader.rb +37 -0
  21. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_adaptive/dinner_order_adaptive_next_question_template.json +243 -0
  22. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_adaptive/parameters_questionnaire_dinner_order_adaptive.json +104 -0
  23. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/dinner_static/parameters_questionnaire_dinner_order_static.json +291 -0
  24. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/empty_templates/next_question_template_empty.json +1 -0
  25. data/lib/davinci_dtr_test_kit/full_ehr/fixtures/empty_templates/parameters_questionnaire_package_empty.json +9 -0
  26. data/lib/davinci_dtr_test_kit/full_ehr/short_circuit_interaction_verification.rb +73 -0
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. data/lib/davinci_dtr_test_kit/{client_groups/adaptive_questionnaire/custom → full_ehr/v2.0.1}/dtr_full_ehr_custom_adaptive_workflow_group.rb +14 -14
  35. 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
  36. data/lib/davinci_dtr_test_kit/{client_groups/must_support → full_ehr/v2.0.1}/dtr_full_ehr_questionnaire_must_support_group.rb +6 -6
  37. 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
  38. data/lib/davinci_dtr_test_kit/{dtr_full_ehr_suite.rb → full_ehr/v2.0.1/dtr_full_ehr_suite.rb} +19 -20
  39. 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
  40. 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
  41. 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
  42. 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
  43. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/dtr_must_support_attestation_test.rb +1 -1
  44. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/dtr_questionnaire_must_support_test.rb +1 -1
  45. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/payer_registration/configuration_display_smart_test.rb +1 -1
  46. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/payer_registration/configuration_display_udap_test.rb +1 -1
  47. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_expressions_test.rb +1 -1
  48. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_extensions_test.rb +1 -1
  49. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_libraries_test.rb +1 -1
  50. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_custom_questionnaire_package_validation_test.rb +1 -1
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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
  58. 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
  59. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_prepopulation_attestation_test.rb +1 -1
  60. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_prepopulation_override_attestation_test.rb +1 -1
  61. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_package_request_validation_test.rb +1 -1
  62. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_response_basic_conformance_test.rb +2 -2
  63. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_questionnaire_response_prepopulation_test.rb +1 -1
  64. data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/shared/dtr_rendering_attestation_test.rb +1 -1
  65. 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
  66. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_abstract_adaptive_group.rb +87 -0
  67. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_abstract_standard_group.rb +59 -0
  68. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_suite.rb +145 -0
  69. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/dtr_full_ehr_suite_description_v220.md +254 -0
  70. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/full_ehr_next_question_endpoint.rb +391 -0
  71. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/full_ehr_questionnaire_package_endpoint.rb +206 -0
  72. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/adaptive_questionnaires_completed_test.rb +108 -0
  73. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/interaction_wait_test.rb +177 -0
  74. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/interaction/ui_display_and_interaction_attestation_test.rb +132 -0
  75. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_additional_questionnaires_interaction_group.rb +74 -0
  76. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_adaptive_must_support_test.rb +45 -0
  77. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_base_must_support_test.rb +43 -0
  78. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/must_support/dtr_questionnaire_standard_must_support_test.rb +45 -0
  79. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/next_question_template_questionnaires.rb +21 -0
  80. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/request/dtr_next_question_request_validation_test.rb +85 -0
  81. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/request/dtr_questionnaire_package_request_validation_test.rb +89 -0
  82. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/response/dtr_next_question_response_validation_test.rb +85 -0
  83. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/response/dtr_questionnaire_package_response_validation_test.rb +77 -0
  84. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/workflows/dtr_full_ehr_workflow_adaptive_group.rb +24 -0
  85. data/lib/davinci_dtr_test_kit/full_ehr/v2.2.0/workflows/dtr_full_ehr_workflow_standard_group.rb +21 -0
  86. data/lib/davinci_dtr_test_kit/generator/ig_metadata.rb +21 -0
  87. data/lib/davinci_dtr_test_kit/generator/profile_metadata_extractor.rb +57 -0
  88. data/lib/davinci_dtr_test_kit/generator.rb +117 -0
  89. data/lib/davinci_dtr_test_kit/igs/davinci_dtr_2.2.0.tgz +0 -0
  90. data/lib/davinci_dtr_test_kit/{dtr_options.rb → light_ehr/dtr_light_ehr_options.rb} +1 -1
  91. data/lib/davinci_dtr_test_kit/{dtr_light_ehr_suite.rb → light_ehr/v2.0.1/dtr_light_ehr_suite.rb} +8 -9
  92. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1}/dtr_light_ehr_supported_endpoints_group.rb +5 -5
  93. data/lib/davinci_dtr_test_kit/{client_groups/light_ehr → light_ehr/v2.0.1}/dtr_smart_ehr_launch.rb +3 -3
  94. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_read.rb +1 -1
  95. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_read.rb +1 -1
  96. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_read.rb +1 -1
  97. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_read.rb +1 -1
  98. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_read.rb +1 -1
  99. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_read.rb +1 -1
  100. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_create.rb +1 -1
  101. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_update.rb +1 -1
  102. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_read.rb +1 -1
  103. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_create.rb +1 -1
  104. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_read.rb +1 -1
  105. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_update.rb +1 -1
  106. data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_read.rb +1 -1
  107. 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 +2 -2
  108. 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 +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_endpoint_test.rb +1 -1
  110. 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 +1 -1
  111. 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 +2 -2
  112. data/lib/davinci_dtr_test_kit/metadata.rb +13 -68
  113. data/lib/davinci_dtr_test_kit/requirements/davinci_dtr_test_kit_requirements.csv +216 -0
  114. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_full_ehr_requirements_coverage.csv +1 -1
  115. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_full_ehr_v220_requirements_coverage.csv +1 -0
  116. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_light_ehr_requirements_coverage.csv +1 -1
  117. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_payer_server_requirements_coverage.csv +1 -1
  118. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_payer_server_v220_requirements_coverage.csv +114 -0
  119. data/lib/davinci_dtr_test_kit/requirements/generated/dtr_smart_app_requirements_coverage.csv +1 -1
  120. data/lib/davinci_dtr_test_kit/requirements/hl7.fhir.us.davinci-dtr_2.2.0_requirements.xlsx +0 -0
  121. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → server/endpoints}/next_question_proxy_endpoint.rb +2 -0
  122. data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → server/endpoints}/questionnaire_package_proxy_endpoint.rb +2 -0
  123. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_libraries_test.rb +2 -1
  124. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_questionnaire_expressions_test.rb +2 -1
  125. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_form_questionnaire_extensions_test.rb +2 -1
  126. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_next_questionnaire_expressions_test.rb +2 -1
  127. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/adaptive_next_questionnaire_extensions_test.rb +2 -1
  128. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_request_test.rb +1 -1
  129. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_request_validation_test.rb +2 -1
  130. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_bundles_validation_test.rb +2 -1
  131. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_search_validation_test.rb +2 -1
  132. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_adaptive_response_validation_test.rb +3 -2
  133. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_request_validation_test.rb +2 -1
  134. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_response_validation_test.rb +2 -1
  135. data/lib/davinci_dtr_test_kit/{dtr_payer_server_suite.rb → server/v2.0.1/dtr_payer_server_suite.rb} +9 -10
  136. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1}/payer_server_adaptive_group.rb +13 -13
  137. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1}/payer_server_static_group.rb +6 -6
  138. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_libraries_test.rb +2 -1
  139. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_questionnaire_expressions_test.rb +2 -1
  140. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_questionnaire_extensions_test.rb +2 -1
  141. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_request_test.rb +3 -2
  142. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_request_validation_test.rb +3 -2
  143. data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/static_forms}/static_form_response_validation_test.rb +4 -3
  144. data/lib/davinci_dtr_test_kit/server/v2.2.0/client_simulation.rb +297 -0
  145. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_capability_statement_test.rb +73 -0
  146. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_suite.rb +322 -0
  147. data/lib/davinci_dtr_test_kit/server/v2.2.0/dtr_payer_server_suite_description_v220.md +37 -0
  148. data/lib/davinci_dtr_test_kit/server/v2.2.0/interaction_test.rb +97 -0
  149. data/lib/davinci_dtr_test_kit/server/v2.2.0/log_questionnaire_errors_support_test.rb +57 -0
  150. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_adaptive_must_support_test.rb +47 -0
  151. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_adaptive_search_must_support_test.rb +40 -0
  152. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_base_must_support_test.rb +40 -0
  153. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_package_bundle_must_support_test.rb +38 -0
  154. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_package_output_parameters_must_support_test.rb +37 -0
  155. data/lib/davinci_dtr_test_kit/server/v2.2.0/must_support/questionnaire_standard_must_support_test.rb +39 -0
  156. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_request_validation_test.rb +45 -0
  157. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/adaptive_questionnaire_endpoint_test.rb +98 -0
  158. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/invalid_questionnaire_response_test.rb +43 -0
  159. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_contained_questionnaire_response_references_test.rb +46 -0
  160. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_question_response_references_test.rb +56 -0
  161. data/lib/davinci_dtr_test_kit/server/v2.2.0/next_question_support/next_question_response_validation_test.rb +67 -0
  162. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/contained_binary_test.rb +58 -0
  163. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/contained_binary_validation.rb +128 -0
  164. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/cql_library_validation_test.rb +58 -0
  165. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_design_support.rb +65 -0
  166. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_expression_elm_test.rb +81 -0
  167. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_expression_language_test.rb +63 -0
  168. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_prepopulation_test.rb +42 -0
  169. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_design/questionnaire_relevance_logic_test.rb +40 -0
  170. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_operation_validation.rb +440 -0
  171. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_request_validation_test.rb +42 -0
  172. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/adaptive_questionnaire_response_contained_questionnaire_test.rb +127 -0
  173. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/adaptive_questionnaire_response_validation_test.rb +61 -0
  174. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/contained_questionnaire_response_references_test.rb +42 -0
  175. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_no_custom_extension_test.rb +184 -0
  176. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_questionnaire_not_found_test.rb +76 -0
  177. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/dtr_server_questionnaire_package_contents_test.rb +89 -0
  178. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/initial_questionnaire_response_test.rb +132 -0
  179. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_package_input_type_test.rb +110 -0
  180. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_references_version_specific_test.rb +79 -0
  181. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_questionnaire_canonical_test.rb +89 -0
  182. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_references_test.rb +51 -0
  183. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/questionnaire_response_validation_test.rb +63 -0
  184. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/source_data_error_test.rb +43 -0
  185. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_package_support/value_set_validation_test.rb +90 -0
  186. data/lib/davinci_dtr_test_kit/server/v2.2.0/questionnaire_response_reference_validation.rb +133 -0
  187. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/small_value_set_expansion_test.rb +120 -0
  188. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/value_set_expansion_test.rb +51 -0
  189. data/lib/davinci_dtr_test_kit/server/v2.2.0/value_set_expand_support/value_set_expansion_validation.rb +58 -0
  190. data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization/token_endpoint.rb +1 -1
  191. data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr/fhir_get_endpoint.rb +1 -1
  192. data/lib/davinci_dtr_test_kit/smart_app/endpoints/mock_payer/smart_app_next_question_endpoint.rb +12 -0
  193. data/lib/davinci_dtr_test_kit/smart_app/endpoints/mock_payer/smart_app_questionnaire_package_endpoint.rb +12 -0
  194. 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 +12 -12
  195. 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
  196. 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
  197. data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1/auth}/token_request_test.rb +1 -1
  198. 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
  199. data/lib/davinci_dtr_test_kit/{client_groups/must_support → smart_app/v2.0.1}/dtr_smart_app_questionnaire_must_support_group.rb +6 -6
  200. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1}/dtr_smart_app_respiratory_workflow_group.rb +3 -3
  201. 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
  202. data/lib/davinci_dtr_test_kit/{dtr_smart_app_suite.rb → smart_app/v2.0.1/dtr_smart_app_suite.rb} +21 -21
  203. 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
  204. data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1}/oauth2_authentication_group.rb +2 -2
  205. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_package_group.rb +1 -1
  206. 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
  207. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_questionnaire_response_group.rb +2 -2
  208. 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
  209. data/lib/davinci_dtr_test_kit/{client_groups/respiratory → smart_app/v2.0.1/static_respiratory}/dtr_respiratory_rendering_attestation_test.rb +1 -1
  210. 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
  211. 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
  212. 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
  213. 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
  214. 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
  215. 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
  216. 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
  217. data/lib/davinci_dtr_test_kit/tags.rb +2 -0
  218. data/lib/davinci_dtr_test_kit/version.rb +2 -2
  219. data/lib/davinci_dtr_test_kit.rb +6 -4
  220. metadata +299 -209
  221. data/lib/davinci_dtr_test_kit/certs/InfernoCA.key +0 -52
  222. data/lib/davinci_dtr_test_kit/certs/InfernoCA.pem +0 -35
  223. data/lib/davinci_dtr_test_kit/certs/TestKit.pem +0 -32
  224. data/lib/davinci_dtr_test_kit/certs/TestKitPrivateKey.key +0 -28
  225. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_next_question_endpoint.rb +0 -30
  226. data/lib/davinci_dtr_test_kit/endpoints/mock_payer/full_ehr_questionnaire_package_endpoint.rb +0 -31
  227. data/lib/davinci_dtr_test_kit/fixture_loader.rb +0 -21
  228. /data/lib/davinci_dtr_test_kit/{endpoints → cross_suite}/cors.rb +0 -0
  229. /data/lib/davinci_dtr_test_kit/{cql_test.rb → cross_suite/v2.0.1/cql_test.rb} +0 -0
  230. /data/lib/davinci_dtr_test_kit/{dtr_questionnaire_response_validation.rb → cross_suite/v2.0.1/dtr_questionnaire_response_validation.rb} +0 -0
  231. /data/lib/davinci_dtr_test_kit/{descriptions.rb → full_ehr/descriptions.rb} +0 -0
  232. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_burrito.json +0 -0
  233. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_hamburger.json +0 -0
  234. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/dinner_order_adaptive_next_question_initial.json +0 -0
  235. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_adaptive/questionnaire_dinner_order_adaptive.json +0 -0
  236. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_static/questionnaire_dinner_order_static.json +0 -0
  237. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/dinner_static/questionnaire_response_dinner_order_static.json +0 -0
  238. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/respiratory_assist_device/pre_populated_questionnaire_response.json +0 -0
  239. /data/lib/davinci_dtr_test_kit/{fixtures → full_ehr/fixtures}/respiratory_assist_device/questionnaire_package.json +0 -0
  240. /data/lib/davinci_dtr_test_kit/{fixtures.rb → full_ehr/fixtures.rb} +0 -0
  241. /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 +0 -0
  242. /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
  243. /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
  244. /data/lib/davinci_dtr_test_kit/{client_groups/auth → full_ehr/v2.0.1}/dtr_client_payer_auth_smart_group.rb +0 -0
  245. /data/lib/davinci_dtr_test_kit/{client_groups/auth → full_ehr/v2.0.1}/dtr_client_payer_auth_udap_group.rb +0 -0
  246. /data/lib/davinci_dtr_test_kit/{docs → full_ehr/v2.0.1}/dtr_full_ehr_suite_description_v201.md +0 -0
  247. /data/lib/davinci_dtr_test_kit/{client_groups → full_ehr/v2.0.1}/must_support/questionnaire_must_support_elements.rb +0 -0
  248. /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
  249. /data/lib/davinci_dtr_test_kit/{create_test.rb → light_ehr/create_test.rb} +0 -0
  250. /data/lib/davinci_dtr_test_kit/{endpoints/mock_payer → light_ehr/endpoints}/light_ehr_supported_payer_endpoint.rb +0 -0
  251. /data/lib/davinci_dtr_test_kit/{read_test.rb → light_ehr/read_test.rb} +0 -0
  252. /data/lib/davinci_dtr_test_kit/{update_test.rb → light_ehr/update_test.rb} +0 -0
  253. /data/lib/davinci_dtr_test_kit/{docs → light_ehr/v2.0.1}/dtr_light_ehr_suite_description_v201.md +0 -0
  254. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_must_support_test.rb +0 -0
  255. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/communication_request_validation.rb +0 -0
  256. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request/metadata.yml +0 -0
  257. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/communication_request_group.rb +0 -0
  258. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_must_support_test.rb +0 -0
  259. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/coverage_validation.rb +0 -0
  260. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage/metadata.yml +0 -0
  261. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/coverage_group.rb +0 -0
  262. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_must_support_test.rb +0 -0
  263. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/device_request_validation.rb +0 -0
  264. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request/metadata.yml +0 -0
  265. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/device_request_group.rb +0 -0
  266. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_must_support_test.rb +0 -0
  267. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/encounter_validation.rb +0 -0
  268. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter/metadata.yml +0 -0
  269. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/encounter_group.rb +0 -0
  270. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_must_support_test.rb +0 -0
  271. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/medication_request_validation.rb +0 -0
  272. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request/metadata.yml +0 -0
  273. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/medication_request_group.rb +0 -0
  274. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/metadata.yml +0 -0
  275. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_must_support_test.rb +0 -0
  276. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order/nutrition_order_validation.rb +0 -0
  277. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/nutrition_order_group.rb +0 -0
  278. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/metadata.yml +0 -0
  279. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_context_search.rb +0 -0
  280. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_must_support_test.rb +0 -0
  281. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_patient_search.rb +0 -0
  282. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_read.rb +0 -0
  283. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response/questionnaire_response_validation.rb +0 -0
  284. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/questionnaire_response_group.rb +0 -0
  285. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/metadata.yml +0 -0
  286. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_must_support_test.rb +0 -0
  287. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request/service_request_validation.rb +0 -0
  288. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/service_request_group.rb +0 -0
  289. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/metadata.yml +0 -0
  290. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_must_support_test.rb +0 -0
  291. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task/task_validation.rb +0 -0
  292. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/task_group.rb +0 -0
  293. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/metadata.yml +0 -0
  294. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_must_support_test.rb +0 -0
  295. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription/vision_prescription_validation.rb +0 -0
  296. /data/lib/davinci_dtr_test_kit/{profiles → light_ehr/v2.0.1/profiles}/vision_prescription_group.rb +0 -0
  297. /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
  298. /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
  299. /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
  300. /data/lib/davinci_dtr_test_kit/{endpoints/mock_authorization → server/endpoints}/simple_token_endpoint.rb +0 -0
  301. /data/lib/davinci_dtr_test_kit/{payer_server_groups → server/v2.0.1/adaptive_forms}/payer_server_next_response_complete_test.rb +0 -0
  302. /data/lib/davinci_dtr_test_kit/{docs → server/v2.0.1}/dtr_payer_server_suite_description_v201.md +0 -0
  303. /data/lib/davinci_dtr_test_kit/{validation_test.rb → server/validation_test.rb} +0 -0
  304. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization/authorize_endpoint.rb +0 -0
  305. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_authorization.rb +0 -0
  306. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr/questionnaire_response_endpoint.rb +0 -0
  307. /data/lib/davinci_dtr_test_kit/{endpoints → smart_app/endpoints}/mock_ehr.rb +0 -0
  308. /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
  309. /data/lib/davinci_dtr_test_kit/{auth_groups → smart_app/v2.0.1/auth}/token_validation_test.rb +0 -0
  310. /data/lib/davinci_dtr_test_kit/{docs → smart_app/v2.0.1}/dtr_smart_app_suite_description_v201.md +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,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'questionnaire_design_support'
4
+
5
+ module DaVinciDTRTestKit
6
+ module DTRPayerServerV220
7
+ class QuestionnaireRelevanceLogicTest < Inferno::Test
8
+ include QuestionnaireDesignSupport
9
+
10
+ ENABLE_WHEN_EXPRESSION_URL =
11
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression'
12
+
13
+ id :dtr_v220_payer_questionnaire_relevance_logic
14
+ title 'Questionnaires include relevance logic'
15
+ description %(
16
+ Inferno verifies that, across all Questionnaires returned by the DTR server, at
17
+ least one demonstrates logic for including only relevant questions and answer
18
+ choices based on answers already provided, using `enableWhen` or
19
+ `enableWhenExpression`.
20
+ )
21
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-17'
22
+
23
+ run do
24
+ questionnaires = returned_questionnaires.map { |details| details[:questionnaire] }
25
+ skip_if questionnaires.blank?, 'No Questionnaire resources were returned'
26
+
27
+ assert questionnaires.any? { |questionnaire| questionnaire_has_relevance_logic?(questionnaire) },
28
+ 'No Questionnaire included enableWhen or enableWhenExpression relevance logic.'
29
+ end
30
+
31
+ private
32
+
33
+ def questionnaire_has_relevance_logic?(questionnaire)
34
+ questionnaire_items(questionnaire).any? do |item|
35
+ item.enableWhen.present? || item.extension.any? { |extension| extension.url == ENABLE_WHEN_EXPRESSION_URL }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,440 @@
1
+ # NOTE: this was copied from 2.0.1 'cql_test', and is in the process of being updated
2
+ module DaVinciDTRTestKit
3
+ module QuestionnaireOperationValidation
4
+ QUESTIONNAIRE_PACKAGE_BUNDLE_PROFILE = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/DTR-QPackageBundle|2.2.0'.freeze
5
+ QUESTIONNAIRE_PACKAGE_PARAMETER_PROFILE = 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-output-parameters|2.2.0'.freeze
6
+
7
+ def extension_presence
8
+ @extension_presence ||= { 'found_min_launch_context' => false, 'found_min_variable' => false,
9
+ 'found_min_pop_context' => false, 'found_min_init_expression' => false,
10
+ 'found_min_candidate_expression' => false, 'found_min_context_expression' => false,
11
+ 'found_min_cqf_lib' => false }
12
+ end
13
+
14
+ # def cql_presence
15
+ # @cql_presence ||= { 'launch_context' => true, 'variable' => true,
16
+ # 'pop_context' => true, 'init_expression' => true,
17
+ # 'candidate_expression' => true, 'context_expression' => true }
18
+ # end
19
+
20
+ # def cqf_reference_libraries
21
+ # scratch[:cqf_reference_libraries] ||= Set.new
22
+ # end
23
+
24
+ def library_canonicals
25
+ @library_canonicals ||= Set.new
26
+ end
27
+
28
+ def library_names
29
+ @library_names ||= Set.new
30
+ end
31
+
32
+ def reset_library_tracking
33
+ @library_canonicals = Set.new
34
+ @library_names = Set.new
35
+ end
36
+
37
+ # def found_questionnaire
38
+ # @found_questionnaire ||= false
39
+ # end
40
+
41
+ # def found_duplicate_library_name
42
+ # @found_duplicate_library_name ||= false
43
+ # end
44
+
45
+ # def found_non_cql_elm_library
46
+ # @found_non_cql_elm_library ||= false
47
+ # end
48
+
49
+ # def found_non_cql_expression
50
+ # @found_non_cql_expression ||= false
51
+ # end
52
+
53
+ # def verify_questionnaire_extensions(questionnaires)
54
+ # assert questionnaires&.any? && questionnaires.all?(FHIR::Questionnaire), 'No questionnaires found.'
55
+ # questionnaires.each_with_index { |q, q_index| check_questionnaire_extensions(q, q_index) }
56
+ # check_library_references
57
+ # assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
58
+ # assert cql_presence['variable'], 'Variable expression logic not written in CQL.'
59
+ # assert cql_presence['launch_context'], 'Launch context expression logic not written in CQL.'
60
+ # assert cql_presence['pop_context'], 'Population context expression logic not written in CQL.'
61
+ # end
62
+
63
+ # def check_questionnaire_extensions(questionnaire, q_index)
64
+ # # are extensions present in this questionnaire?
65
+ # found_launch_context = found_variable = found_pop_context = found_cqf_lib = false
66
+ # cqf_count = total_cqf_libs(questionnaire.extension)
67
+ # misformatted_expressions = []
68
+ # questionnaire.extension.each_with_index do |extension, index|
69
+ # if extension.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext'
70
+ # found_launch_context = true
71
+ # extension_presence['found_min_launch_context'] = true
72
+ # check_for_cql(extension, 'launch_context', index, q_index, extension.url)
73
+ # misformatted_expressions << check_expression_format(extension, index)
74
+ # end
75
+ # if extension.url == 'http://hl7.org/fhir/StructureDefinition/variable'
76
+ # found_variable = true
77
+ # extension_presence['found_min_variable'] = true
78
+ # check_for_cql(extension, 'variable', index, q_index, extension.url)
79
+ # misformatted_expressions << check_expression_format(extension, index)
80
+ # end
81
+ # if extension.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext'
82
+ # found_pop_context = true
83
+ # extension_presence['found_min_pop_context'] = true
84
+ # check_for_cql(extension, 'pop_context', index, q_index, extension.url)
85
+ # misformatted_expressions << check_expression_format(extension, index)
86
+ # end
87
+ # next unless extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library'
88
+
89
+ # cqf_reference_libraries.add(extension.valueCanonical)
90
+ # found_cqf_lib = true
91
+ # extension_presence['found_min_cqf_lib'] = true
92
+
93
+ # check_for_cql(extension, '', index, q_index, extension.url)
94
+ # end
95
+ # add_launch_context_messages(found_launch_context, found_variable, found_pop_context, found_cqf_lib, q_index)
96
+ # return if cqf_count < 1
97
+
98
+ # add_formatting_messages(misformatted_expressions, q_index)
99
+ # assert misformatted_expressions.compact.empty?, 'Expression in questionnaire misformatted.'
100
+ # end
101
+
102
+ # def verify_questionnaire_items(questionnaires, final_cql_test: false)
103
+ # assert questionnaires&.any? && questionnaires.all?(FHIR::Questionnaire), 'No questionnaires found.'
104
+ # questionnaires.each_with_index { |q, q_index| check_questionnaire_items(q, q_index) }
105
+
106
+ # begin
107
+ # assert !found_non_cql_expression, 'Found non-cql expression.'
108
+ # assert extension_presence.value?(true), 'No extensions found. Questionnaire must demonstrate prepopulation.'
109
+ # assert cql_presence['init_expression'], 'Initial expression logic not written in CQL.'
110
+ # assert cql_presence['candidate_expression'], 'Candidate expression logic not written in CQL.'
111
+ # assert cql_presence['context_expression'], 'Context expression logic not written in CQL.'
112
+ # ensure
113
+ # reset_cql_tests if final_cql_test
114
+ # end
115
+ # end
116
+
117
+ # def add_launch_context_messages(found_launch_context, found_variable, found_pop_context, found_cqf_lib, q_index)
118
+ # unless found_launch_context
119
+ # messages << { type: 'info',
120
+ # message: format_markdown("[questionnaire #{q_index + 1}] included no launch context.") }
121
+ # end
122
+ # unless found_variable
123
+ # messages << { type: 'info',
124
+ # message: format_markdown("[questionnaire #{q_index + 1}]
125
+ # included no variable to query for additional data.") }
126
+ # end
127
+ # unless found_pop_context
128
+ # messages << { type: 'info',
129
+ # message: format_markdown("[questionnaire #{q_index + 1}]
130
+ # included no item population context.") }
131
+ # end
132
+ # return if found_cqf_lib
133
+
134
+ # messages << { type: 'info',
135
+ # message: format_markdown("[questionnaire #{q_index + 1}]
136
+ # included no cqf library.") }
137
+ # end
138
+
139
+ # def add_formatting_messages(misformatted_expressions, q_index)
140
+ # misformatted_expressions.compact.each do |idx|
141
+ # messages << { type: 'info',
142
+ # message: format_markdown("[expression #{idx + 1}] in [questionnaire #{q_index + 1}]
143
+ # does not begin with a reference to an included library name.") }
144
+ # end
145
+ # end
146
+
147
+ # def total_cqf_libs(extensions)
148
+ # cqf_count = 0
149
+ # extensions.each do |extension|
150
+ # next unless extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library'
151
+
152
+ # cqf_count += 1
153
+ # end
154
+ # cqf_count
155
+ # end
156
+
157
+ # def add_item_messages(found_item_expressions, q_index)
158
+ # unless found_item_expressions['found_candidate_expression']
159
+ # messages << { type: 'info',
160
+ # message: format_markdown("[questionnaire #{q_index + 1}] included no candidate expression.") }
161
+ # end
162
+ # unless found_item_expressions['found_init_expression']
163
+ # messages << { type: 'info',
164
+ # message: format_markdown("[questionnaire #{q_index + 1}] included no initial expression.") }
165
+ # end
166
+ # return if found_item_expressions['found_context_expression']
167
+
168
+ # messages << { type: 'info',
169
+ # message: format_markdown("[questionnaire #{q_index + 1}] included no context expression.") }
170
+ # end
171
+
172
+ # def check_questionnaire_items(questionnaire, q_index)
173
+ # # are expressions present in this questionnaire?
174
+ # found_item_expressions = { 'found_init_expression' => false,
175
+ # 'found_candidate_expression' => false,
176
+ # 'found_context_expression' => false }
177
+ # cqf_count = total_cqf_libs(questionnaire.extension)
178
+ # misformatted_expressions = []
179
+
180
+ # # check questionnaire items
181
+ # questionnaire.item.each_with_index do |item, index|
182
+ # misformatted_expressions.concat(check_nested_items(item, index, q_index, found_item_expressions, item.linkId))
183
+ # # check extensions on items
184
+ # item.extension.each do |item_ext|
185
+ # misformatted_expressions << check_item_extension(item_ext,
186
+ # index, q_index, found_item_expressions, item.linkId)
187
+ # end
188
+ # end
189
+ # add_item_messages(found_item_expressions, q_index)
190
+ # # only care about formatting when there are multiple cqf libs
191
+ # return if cqf_count < 1
192
+
193
+ # misformatted_expressions.compact.to_set.each do |idx|
194
+ # messages << { type: 'info',
195
+ # message: format_markdown("[item #{idx + 1}] in [questionnaire #{q_index + 1}]
196
+ # contains expression that does not begin with a reference to an included library name.") }
197
+ # end
198
+ # assert misformatted_expressions.compact.to_set.empty?, 'Expression in questionnaire misformatted.'
199
+ # end
200
+
201
+ def check_libraries(parameters, request_index)
202
+ questionnaire_bundles = extract_questionnaire_bundles(parameters)
203
+
204
+ questionnaire_bundles.each do |bundle|
205
+ reset_library_tracking
206
+
207
+ libraries = extract_libraries_from_bundles([bundle])
208
+
209
+ questionnaires = extract_questionnaires_from_bundles([bundle])
210
+
211
+ referenced_libraries =
212
+ Set.new(
213
+ questionnaires
214
+ .flat_map { |questionnaire| referenced_library_canonicals(questionnaire) }
215
+ )
216
+
217
+ libraries.each do |library|
218
+ library_canonicals.add(library_canonical(library)) unless library.url.nil?
219
+
220
+ referenced_libraries.merge(depends_on_library_canonicals(library))
221
+
222
+ evaluate_library(library, request_index)
223
+
224
+ next if library_names.add?(library.name)
225
+
226
+ add_message(
227
+ 'error',
228
+ "Request #{request_index}: Bundle contains multiple libraries named '#{library.name}'"
229
+ )
230
+ end
231
+
232
+ check_referenced_libraries(referenced_libraries, library_canonicals, request_index)
233
+ end
234
+ end
235
+
236
+ def library_canonical(library)
237
+ library_version_string = library.version.present? ? "|#{library.version}" : ''
238
+
239
+ "#{library.url}#{library_version_string}"
240
+ end
241
+
242
+ def evaluate_library(library, request_index)
243
+ unless library_contains_cql?(library)
244
+ add_message(
245
+ 'error',
246
+ "Request #{request_index}: Library `#{library.url}` does not include CQL."
247
+ )
248
+ end
249
+
250
+ unless library_contains_elm?(library) # rubocop:disable Style/GuardClause
251
+ add_message(
252
+ 'error',
253
+ "Request #{request_index}: Library `#{library.url}` does not include ELM."
254
+ )
255
+ end
256
+ end
257
+
258
+ def library_contains_cql?(library)
259
+ library
260
+ .content
261
+ .any? { |content| content.data.present? && content.contentType == 'text/cql' }
262
+ end
263
+
264
+ def library_contains_elm?(library)
265
+ library
266
+ .content
267
+ .any? { |content| content.data.present? && content.contentType == 'application/elm+json' }
268
+ end
269
+
270
+ def referenced_library_canonicals(questionnaire)
271
+ questionnaire
272
+ .extension
273
+ .select { |extension| extension.url == 'http://hl7.org/fhir/StructureDefinition/cqf-library' }
274
+ .map(&:valueCanonical)
275
+ end
276
+
277
+ def depends_on_library_canonicals(library)
278
+ library.relatedArtifact.filter_map do |related_artifact|
279
+ related_artifact.resource if related_artifact.type == 'depends-on'
280
+ end
281
+ end
282
+
283
+ def check_referenced_libraries(referenced_libraries, found_libraries, request_index)
284
+ unversioned_library_references = referenced_libraries.select { |library| library.exclude? '|' }
285
+
286
+ if unversioned_library_references.present?
287
+ unversioned_library_string =
288
+ unversioned_library_references
289
+ .map { |reference| "`#{reference}`" }
290
+ .join(', ')
291
+
292
+ add_message(
293
+ 'error',
294
+ "The Bundle included the following unversioned library references: #{unversioned_library_string}"
295
+ )
296
+ end
297
+
298
+ referenced_libraries.reject! { |library| library.exclude? '|' }
299
+
300
+ missing_libraries = referenced_libraries - found_libraries
301
+
302
+ return if missing_libraries.blank?
303
+
304
+ missing_library_string = missing_libraries.map { |url| "`#{url}`" }.join(', ')
305
+
306
+ add_message(
307
+ 'error',
308
+ "Request #{request_index}: The following libraries are referenced but not included in the Bundle: " \
309
+ "#{missing_library_string}"
310
+ )
311
+ end
312
+
313
+ # def check_item_extension(item_ext, index, q_index, found_item_expressions, link_id)
314
+ # if item_ext.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression'
315
+ # found_item_expressions['found_candidate_expression'] = true
316
+ # extension_presence['found_min_candidate_expression'] = true
317
+ # check_for_cql(item_ext, 'candidate_expression', index, q_index, item_ext.url, link_id)
318
+ # return check_expression_format(item_ext, index)
319
+ # end
320
+ # if item_ext.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression'
321
+ # found_item_expressions['found_init_expression'] = true
322
+ # extension_presence['found_min_init_expression'] = true
323
+ # check_for_cql(item_ext, 'init_expression', index, q_index, item_ext.url, link_id)
324
+ # return check_expression_format(item_ext, index)
325
+ # end
326
+ # if item_ext.url == 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression'
327
+ # found_item_expressions['found_context_expression'] = true
328
+ # extension_presence['found_min_context_expression'] = true
329
+ # check_for_cql(item_ext, 'context_expression', index, q_index, item_ext.url, link_id)
330
+ # return check_expression_format(item_ext, index)
331
+ # end
332
+ # check_for_cql(item_ext, '', index, q_index, item_ext.url, link_id)
333
+ # end
334
+
335
+ # def check_nested_items(item, index, q_index, found_item_expressions, link_id)
336
+ # misformatted_nested_expressions = []
337
+ # item.item.each do |nested_item|
338
+ # check_nested_items(nested_item, index, q_index, found_item_expressions, nested_item.linkId)
339
+ # nested_item.extension.each do |item_ext|
340
+ # misformatted_nested_expressions << check_item_extension(item_ext, index, q_index, found_item_expressions,
341
+ # link_id)
342
+ # end
343
+ # end
344
+ # misformatted_nested_expressions.compact
345
+ # end
346
+
347
+ # def check_expression_format(item_ext, index)
348
+ # return unless library_names.none?
349
+
350
+ # expression_passes = false
351
+ # library_names.each do |name|
352
+ # if item_ext.valueExpression.expression.start_with? "\"#{name}\""
353
+ # expression_passes = true
354
+ # break
355
+ # end
356
+ # end
357
+ # index unless expression_passes
358
+ # end
359
+
360
+ # def check_for_cql(extension, extension_name, index, q_index, url, link_id = '')
361
+ # return if extension.valueExpression.nil?
362
+ # return if extension.valueExpression.language == 'text/cql'
363
+
364
+ # cql_presence[extension_name] = false unless extension_name.blank?
365
+ # messages << if link_id.blank?
366
+ # { type: 'info',
367
+ # message: format_markdown("[extension #{index + 1}] in [questionnaire #{q_index + 1}]
368
+ # contains expression that does not have content type of cql
369
+ # (URL: #{url}).") }
370
+ # else
371
+ # { type: 'info',
372
+ # message: format_markdown("[item #{index + 1}] in [questionnaire #{q_index + 1}]
373
+ # contains expression that does not have content type of cql
374
+ # (linkId: #{link_id}, URL: #{url}).") }
375
+ # end
376
+ # end
377
+
378
+ # def extract_contained_questionnaires(questionnaire_responses)
379
+ # questionnaire_responses&.filter_map do |qr|
380
+ # qr.contained&.grep(FHIR::Questionnaire)
381
+ # end&.flatten&.compact
382
+ # end
383
+
384
+ def extract_questionnaires_from_bundles(questionnaire_bundles)
385
+ questionnaire_bundles.filter_map do |qb|
386
+ qb.entry.filter_map { |entry| entry.resource if entry.resource.is_a?(FHIR::Questionnaire) }
387
+ end&.flatten&.compact
388
+ end
389
+
390
+ def perform_questionnaire_package_response_validation(resource, index)
391
+ bundles = extract_questionnaire_bundles(resource)
392
+
393
+ resource_is_valid?(
394
+ resource:,
395
+ profile_url: QUESTIONNAIRE_PACKAGE_PARAMETER_PROFILE,
396
+ message_prefix: "Request #{index}: "
397
+ )
398
+
399
+ return if bundles.present?
400
+
401
+ add_message(
402
+ 'error',
403
+ "No Questionnaire Bundle found in response #{index}"
404
+ )
405
+ end
406
+
407
+ def extract_questionnaire_bundles(resource)
408
+ case resource&.resourceType
409
+ when 'Bundle'
410
+ [resource]
411
+ when 'Parameters'
412
+ extract_bundles_from_parameter(resource)
413
+ else
414
+ []
415
+ end
416
+ end
417
+
418
+ def extract_bundles_from_parameter(parameter)
419
+ return [] if parameter.blank?
420
+
421
+ parameter.parameter&.filter_map do |param|
422
+ param.resource if param.resource&.resourceType == 'Bundle'
423
+ end
424
+ end
425
+
426
+ # def extract_questionnaire_from_questionnaire_package(questionnaire_pkg_json, questionnaire_url)
427
+ # resource = FHIR.from_contents(questionnaire_pkg_json)
428
+ # questionnaire_bundles = extract_questionnaire_bundles(resource)
429
+ # questionnaires = extract_questionnaires_from_bundles(questionnaire_bundles)
430
+
431
+ # questionnaires.find { |q| q.url == questionnaire_url }
432
+ # end
433
+
434
+ def extract_libraries_from_bundles(questionnaire_bundles)
435
+ questionnaire_bundles.filter_map do |qb|
436
+ qb.entry.filter_map { |entry| entry.resource if entry&.resource.is_a?(FHIR::Library) }
437
+ end&.flatten&.compact
438
+ end
439
+ end
440
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../validation_test'
2
+ require_relative '../../tags'
3
+
4
+ module DaVinciDTRTestKit
5
+ module DTRPayerServerV220
6
+ class QuestionnairePackageRequestValidationTest < Inferno::Test
7
+ include DaVinciDTRTestKit::ValidationTest
8
+
9
+ id :dtr_v220_payer_questionnaire_package_request_validation
10
+ title '$questionnaire-package request is valid'
11
+ description %(
12
+ This test validates that each outgoing $questionnaire-package request body
13
+ conforms to the [DTR Questionnaire Package Input Parameters profile](https://hl7.org/fhir/us/davinci-dtr/2.2.0/en/StructureDefinition-dtr-qpackage-input-parameters.html).
14
+ Inferno generates these request bodies from the provided test input.
15
+ )
16
+ simulation_verification
17
+
18
+ run do
19
+ load_tagged_requests(QUESTIONNAIRE_TAG)
20
+
21
+ omit_if requests.empty?, 'No $questionnaire-package requests were made.'
22
+
23
+ requests.each_with_index do |request, index|
24
+ fhir_obj = begin
25
+ FHIR.from_contents(request.request_body)
26
+ rescue StandardError
27
+ nil
28
+ end
29
+
30
+ validate_resource(
31
+ fhir_obj,
32
+ :parameters,
33
+ 'http://hl7.org/fhir/us/davinci-dtr/StructureDefinition/dtr-qpackage-input-parameters|2.2.0',
34
+ index
35
+ )
36
+ end
37
+
38
+ assert_no_error_messages('Non-conformant $questionnaire-package request. See Messages for details.')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../questionnaire_operation_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 AdaptiveQuestionnaireResponseContainedQuestionnaireTest < Inferno::Test
10
+ include QuestionnaireOperationValidation
11
+ include MultiRequestMessageHelper
12
+
13
+ ADAPTIVE_QUESTIONNAIRE_EXTENSION_URL =
14
+ 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-questionnaireAdaptive'
15
+
16
+ id :dtr_v220_payer_adaptive_questionnaire_response_contained_questionnaire
17
+ title 'Adaptive QuestionnaireResponses reference a contained Questionnaire'
18
+ description %(
19
+ This test verifies that each QuestionnaireResponse accompanying an adaptive
20
+ Questionnaire in a `$questionnaire-package` response references a contained
21
+ Questionnaire. The contained Questionnaire must be derived from the canonical
22
+ URL of the adaptive Questionnaire being completed.
23
+ )
24
+ verifies_requirements 'hl7.fhir.us.davinci-dtr_2.2.0@spec-25'
25
+
26
+ run do
27
+ load_tagged_requests(QUESTIONNAIRE_TAG)
28
+ adaptive_package_found = false
29
+
30
+ requests.each_with_index do |request, request_index|
31
+ resource = parse_fhir_request_entity(request.response_body, 'Response', request_index)
32
+ next unless resource.present?
33
+
34
+ extract_questionnaire_bundles(resource).each do |bundle|
35
+ adaptive_questionnaire = bundle.entry.filter_map(&:resource).find do |entry_resource|
36
+ adaptive_questionnaire?(entry_resource)
37
+ end
38
+ next unless adaptive_questionnaire.present?
39
+
40
+ adaptive_package_found = true
41
+ validate_questionnaire_response(bundle, adaptive_questionnaire, request_index)
42
+ end
43
+ end
44
+
45
+ omit_if !adaptive_package_found, 'No adaptive Questionnaire packages were returned.'
46
+
47
+ assert_no_error_messages(
48
+ "#{requests_with_errors_prefix}Adaptive QuestionnaireResponses must reference a contained Questionnaire " \
49
+ 'derived from the adaptive Questionnaire canonical. See Messages for details.'
50
+ )
51
+ end
52
+
53
+ private
54
+
55
+ def adaptive_questionnaire?(resource)
56
+ resource.is_a?(FHIR::Questionnaire) &&
57
+ resource.extension.any? do |extension|
58
+ extension.url == ADAPTIVE_QUESTIONNAIRE_EXTENSION_URL &&
59
+ (extension.valueBoolean || extension.valueUrl.present?)
60
+ end
61
+ end
62
+
63
+ def validate_questionnaire_response(bundle, adaptive_questionnaire, request_index)
64
+ questionnaire_response = bundle.entry.filter_map(&:resource).find do |entry_resource|
65
+ entry_resource.is_a?(FHIR::QuestionnaireResponse)
66
+ end
67
+
68
+ unless questionnaire_response.present?
69
+ add_request_message(
70
+ 'error',
71
+ 'Adaptive Questionnaire package contains no QuestionnaireResponse.',
72
+ request_index
73
+ )
74
+ return
75
+ end
76
+
77
+ contained_questionnaire = referenced_contained_questionnaire(questionnaire_response, request_index)
78
+ return unless contained_questionnaire.present?
79
+
80
+ validate_derived_from(contained_questionnaire, adaptive_questionnaire, questionnaire_response, request_index)
81
+ end
82
+
83
+ def referenced_contained_questionnaire(questionnaire_response, request_index)
84
+ reference = questionnaire_response.questionnaire
85
+ unless reference&.start_with?('#')
86
+ add_request_message(
87
+ 'error',
88
+ 'QuestionnaireResponse.questionnaire does not reference a contained Questionnaire.',
89
+ request_index
90
+ )
91
+ return
92
+ end
93
+
94
+ contained_questionnaire = questionnaire_response.contained.find do |contained_resource|
95
+ contained_resource.is_a?(FHIR::Questionnaire) && contained_resource.id == reference.delete_prefix('#')
96
+ end
97
+ unless contained_questionnaire.present?
98
+ add_request_message(
99
+ 'error',
100
+ "QuestionnaireResponse.questionnaire references `#{reference}`, " \
101
+ 'but no contained Questionnaire has that id.',
102
+ request_index
103
+ )
104
+ end
105
+
106
+ contained_questionnaire
107
+ end
108
+
109
+ def validate_derived_from(contained_questionnaire, adaptive_questionnaire, questionnaire_response, request_index)
110
+ canonical = questionnaire_canonical(adaptive_questionnaire)
111
+ return if canonical.present? && contained_questionnaire.derivedFrom.include?(canonical)
112
+
113
+ add_request_message(
114
+ 'error',
115
+ "Contained Questionnaire `#{questionnaire_response.questionnaire}` is not derived from `#{canonical}`.",
116
+ request_index
117
+ )
118
+ end
119
+
120
+ def questionnaire_canonical(questionnaire)
121
+ return unless questionnaire.url.present?
122
+
123
+ "#{questionnaire.url}#{"|#{questionnaire.version}" if questionnaire.version.present?}"
124
+ end
125
+ end
126
+ end
127
+ end