us_core_test_kit 0.1.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 (350) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/us_core_test_kit/custom_groups/capability_statement/conformance_support_test.rb +41 -0
  4. data/lib/us_core_test_kit/custom_groups/capability_statement/fhir_version_test.rb +15 -0
  5. data/lib/us_core_test_kit/custom_groups/capability_statement/json_support_test.rb +40 -0
  6. data/lib/us_core_test_kit/custom_groups/capability_statement/profile_support_test.rb +90 -0
  7. data/lib/us_core_test_kit/custom_groups/capability_statement_group.rb +64 -0
  8. data/lib/us_core_test_kit/custom_groups/clinical_notes_guidance_group.rb +208 -0
  9. data/lib/us_core_test_kit/custom_groups/data_absent_reason_group.rb +59 -0
  10. data/lib/us_core_test_kit/date_search_validation.rb +101 -0
  11. data/lib/us_core_test_kit/ext/fhir_models.rb +59 -0
  12. data/lib/us_core_test_kit/fhir_resource_navigation.rb +63 -0
  13. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_must_support_test.rb +40 -0
  14. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_patient_clinical_status_search_test.rb +46 -0
  15. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_patient_search_test.rb +60 -0
  16. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_provenance_revinclude_search_test.rb +49 -0
  17. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_read_test.rb +24 -0
  18. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_reference_resolution_test.rb +28 -0
  19. data/lib/us_core_test_kit/generated/allergy_intolerance/allergy_intolerance_validation_test.rb +34 -0
  20. data/lib/us_core_test_kit/generated/allergy_intolerance_group.rb +85 -0
  21. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_must_support_test.rb +49 -0
  22. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_patient_category_date_search_test.rb +46 -0
  23. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_patient_category_search_test.rb +45 -0
  24. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_patient_category_status_search_test.rb +47 -0
  25. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_patient_code_date_search_test.rb +48 -0
  26. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_patient_code_search_test.rb +62 -0
  27. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_provenance_revinclude_search_test.rb +51 -0
  28. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_read_test.rb +24 -0
  29. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_reference_resolution_test.rb +28 -0
  30. data/lib/us_core_test_kit/generated/bodyheight/bodyheight_validation_test.rb +34 -0
  31. data/lib/us_core_test_kit/generated/bodyheight_group.rb +93 -0
  32. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_must_support_test.rb +49 -0
  33. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_patient_category_date_search_test.rb +46 -0
  34. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_patient_category_search_test.rb +45 -0
  35. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_patient_category_status_search_test.rb +47 -0
  36. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_patient_code_date_search_test.rb +48 -0
  37. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_patient_code_search_test.rb +62 -0
  38. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_provenance_revinclude_search_test.rb +51 -0
  39. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_read_test.rb +24 -0
  40. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_reference_resolution_test.rb +28 -0
  41. data/lib/us_core_test_kit/generated/bodytemp/bodytemp_validation_test.rb +34 -0
  42. data/lib/us_core_test_kit/generated/bodytemp_group.rb +93 -0
  43. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_must_support_test.rb +49 -0
  44. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_patient_category_date_search_test.rb +46 -0
  45. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_patient_category_search_test.rb +45 -0
  46. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_patient_category_status_search_test.rb +47 -0
  47. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_patient_code_date_search_test.rb +48 -0
  48. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_patient_code_search_test.rb +62 -0
  49. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_provenance_revinclude_search_test.rb +51 -0
  50. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_read_test.rb +24 -0
  51. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_reference_resolution_test.rb +28 -0
  52. data/lib/us_core_test_kit/generated/bodyweight/bodyweight_validation_test.rb +34 -0
  53. data/lib/us_core_test_kit/generated/bodyweight_group.rb +93 -0
  54. data/lib/us_core_test_kit/generated/bp/bp_must_support_test.rb +52 -0
  55. data/lib/us_core_test_kit/generated/bp/bp_patient_category_date_search_test.rb +46 -0
  56. data/lib/us_core_test_kit/generated/bp/bp_patient_category_search_test.rb +45 -0
  57. data/lib/us_core_test_kit/generated/bp/bp_patient_category_status_search_test.rb +47 -0
  58. data/lib/us_core_test_kit/generated/bp/bp_patient_code_date_search_test.rb +48 -0
  59. data/lib/us_core_test_kit/generated/bp/bp_patient_code_search_test.rb +62 -0
  60. data/lib/us_core_test_kit/generated/bp/bp_provenance_revinclude_search_test.rb +51 -0
  61. data/lib/us_core_test_kit/generated/bp/bp_read_test.rb +24 -0
  62. data/lib/us_core_test_kit/generated/bp/bp_reference_resolution_test.rb +28 -0
  63. data/lib/us_core_test_kit/generated/bp/bp_validation_test.rb +34 -0
  64. data/lib/us_core_test_kit/generated/bp_group.rb +93 -0
  65. data/lib/us_core_test_kit/generated/care_plan/care_plan_must_support_test.rb +41 -0
  66. data/lib/us_core_test_kit/generated/care_plan/care_plan_patient_category_date_search_test.rb +48 -0
  67. data/lib/us_core_test_kit/generated/care_plan/care_plan_patient_category_search_test.rb +62 -0
  68. data/lib/us_core_test_kit/generated/care_plan/care_plan_patient_category_status_date_search_test.rb +48 -0
  69. data/lib/us_core_test_kit/generated/care_plan/care_plan_patient_category_status_search_test.rb +47 -0
  70. data/lib/us_core_test_kit/generated/care_plan/care_plan_provenance_revinclude_search_test.rb +51 -0
  71. data/lib/us_core_test_kit/generated/care_plan/care_plan_read_test.rb +24 -0
  72. data/lib/us_core_test_kit/generated/care_plan/care_plan_reference_resolution_test.rb +28 -0
  73. data/lib/us_core_test_kit/generated/care_plan/care_plan_validation_test.rb +34 -0
  74. data/lib/us_core_test_kit/generated/care_plan_group.rb +89 -0
  75. data/lib/us_core_test_kit/generated/care_team/care_team_must_support_test.rb +39 -0
  76. data/lib/us_core_test_kit/generated/care_team/care_team_patient_status_search_test.rb +62 -0
  77. data/lib/us_core_test_kit/generated/care_team/care_team_provenance_revinclude_search_test.rb +50 -0
  78. data/lib/us_core_test_kit/generated/care_team/care_team_read_test.rb +24 -0
  79. data/lib/us_core_test_kit/generated/care_team/care_team_reference_resolution_test.rb +28 -0
  80. data/lib/us_core_test_kit/generated/care_team/care_team_validation_test.rb +34 -0
  81. data/lib/us_core_test_kit/generated/care_team_group.rb +83 -0
  82. data/lib/us_core_test_kit/generated/condition/condition_must_support_test.rb +39 -0
  83. data/lib/us_core_test_kit/generated/condition/condition_patient_category_search_test.rb +47 -0
  84. data/lib/us_core_test_kit/generated/condition/condition_patient_clinical_status_search_test.rb +46 -0
  85. data/lib/us_core_test_kit/generated/condition/condition_patient_code_search_test.rb +47 -0
  86. data/lib/us_core_test_kit/generated/condition/condition_patient_onset_date_search_test.rb +47 -0
  87. data/lib/us_core_test_kit/generated/condition/condition_patient_search_test.rb +60 -0
  88. data/lib/us_core_test_kit/generated/condition/condition_provenance_revinclude_search_test.rb +49 -0
  89. data/lib/us_core_test_kit/generated/condition/condition_read_test.rb +24 -0
  90. data/lib/us_core_test_kit/generated/condition/condition_reference_resolution_test.rb +28 -0
  91. data/lib/us_core_test_kit/generated/condition/condition_validation_test.rb +34 -0
  92. data/lib/us_core_test_kit/generated/condition_group.rb +91 -0
  93. data/lib/us_core_test_kit/generated/device/device_must_support_test.rb +43 -0
  94. data/lib/us_core_test_kit/generated/device/device_patient_search_test.rb +65 -0
  95. data/lib/us_core_test_kit/generated/device/device_patient_type_search_test.rb +52 -0
  96. data/lib/us_core_test_kit/generated/device/device_provenance_revinclude_search_test.rb +49 -0
  97. data/lib/us_core_test_kit/generated/device/device_read_test.rb +24 -0
  98. data/lib/us_core_test_kit/generated/device/device_reference_resolution_test.rb +28 -0
  99. data/lib/us_core_test_kit/generated/device/device_validation_test.rb +34 -0
  100. data/lib/us_core_test_kit/generated/device_group.rb +85 -0
  101. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_must_support_test.rb +43 -0
  102. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_category_date_search_test.rb +46 -0
  103. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_category_search_test.rb +63 -0
  104. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_code_date_search_test.rb +48 -0
  105. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_code_search_test.rb +45 -0
  106. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_search_test.rb +44 -0
  107. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_patient_status_search_test.rb +46 -0
  108. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_provenance_revinclude_search_test.rb +51 -0
  109. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_read_test.rb +24 -0
  110. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_reference_resolution_test.rb +28 -0
  111. data/lib/us_core_test_kit/generated/diagnostic_report_lab/diagnostic_report_lab_validation_test.rb +34 -0
  112. data/lib/us_core_test_kit/generated/diagnostic_report_lab_group.rb +96 -0
  113. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_must_support_test.rb +43 -0
  114. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_category_date_search_test.rb +46 -0
  115. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_category_search_test.rb +63 -0
  116. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_code_date_search_test.rb +48 -0
  117. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_code_search_test.rb +45 -0
  118. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_search_test.rb +44 -0
  119. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_patient_status_search_test.rb +46 -0
  120. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_provenance_revinclude_search_test.rb +51 -0
  121. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_read_test.rb +24 -0
  122. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_reference_resolution_test.rb +28 -0
  123. data/lib/us_core_test_kit/generated/diagnostic_report_note/diagnostic_report_note_validation_test.rb +34 -0
  124. data/lib/us_core_test_kit/generated/diagnostic_report_note_group.rb +96 -0
  125. data/lib/us_core_test_kit/generated/document_reference/document_reference_id_search_test.rb +40 -0
  126. data/lib/us_core_test_kit/generated/document_reference/document_reference_must_support_test.rb +49 -0
  127. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_category_date_search_test.rb +46 -0
  128. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_category_search_test.rb +45 -0
  129. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_search_test.rb +61 -0
  130. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_status_search_test.rb +46 -0
  131. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_type_period_search_test.rb +48 -0
  132. data/lib/us_core_test_kit/generated/document_reference/document_reference_patient_type_search_test.rb +45 -0
  133. data/lib/us_core_test_kit/generated/document_reference/document_reference_provenance_revinclude_search_test.rb +50 -0
  134. data/lib/us_core_test_kit/generated/document_reference/document_reference_read_test.rb +24 -0
  135. data/lib/us_core_test_kit/generated/document_reference/document_reference_reference_resolution_test.rb +28 -0
  136. data/lib/us_core_test_kit/generated/document_reference/document_reference_validation_test.rb +34 -0
  137. data/lib/us_core_test_kit/generated/document_reference_group.rb +99 -0
  138. data/lib/us_core_test_kit/generated/encounter/encounter_class_patient_search_test.rb +47 -0
  139. data/lib/us_core_test_kit/generated/encounter/encounter_date_patient_search_test.rb +45 -0
  140. data/lib/us_core_test_kit/generated/encounter/encounter_id_search_test.rb +40 -0
  141. data/lib/us_core_test_kit/generated/encounter/encounter_identifier_search_test.rb +43 -0
  142. data/lib/us_core_test_kit/generated/encounter/encounter_must_support_test.rb +51 -0
  143. data/lib/us_core_test_kit/generated/encounter/encounter_patient_search_test.rb +61 -0
  144. data/lib/us_core_test_kit/generated/encounter/encounter_patient_status_search_test.rb +45 -0
  145. data/lib/us_core_test_kit/generated/encounter/encounter_patient_type_search_test.rb +47 -0
  146. data/lib/us_core_test_kit/generated/encounter/encounter_provenance_revinclude_search_test.rb +50 -0
  147. data/lib/us_core_test_kit/generated/encounter/encounter_read_test.rb +24 -0
  148. data/lib/us_core_test_kit/generated/encounter/encounter_reference_resolution_test.rb +28 -0
  149. data/lib/us_core_test_kit/generated/encounter/encounter_validation_test.rb +34 -0
  150. data/lib/us_core_test_kit/generated/encounter_group.rb +97 -0
  151. data/lib/us_core_test_kit/generated/goal/goal_must_support_test.rb +39 -0
  152. data/lib/us_core_test_kit/generated/goal/goal_patient_lifecycle_status_search_test.rb +45 -0
  153. data/lib/us_core_test_kit/generated/goal/goal_patient_search_test.rb +60 -0
  154. data/lib/us_core_test_kit/generated/goal/goal_patient_target_date_search_test.rb +47 -0
  155. data/lib/us_core_test_kit/generated/goal/goal_provenance_revinclude_search_test.rb +49 -0
  156. data/lib/us_core_test_kit/generated/goal/goal_read_test.rb +24 -0
  157. data/lib/us_core_test_kit/generated/goal/goal_reference_resolution_test.rb +28 -0
  158. data/lib/us_core_test_kit/generated/goal/goal_validation_test.rb +34 -0
  159. data/lib/us_core_test_kit/generated/goal_group.rb +87 -0
  160. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_must_support_test.rb +49 -0
  161. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_patient_category_date_search_test.rb +46 -0
  162. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_patient_category_search_test.rb +45 -0
  163. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_patient_category_status_search_test.rb +47 -0
  164. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_patient_code_date_search_test.rb +48 -0
  165. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_patient_code_search_test.rb +62 -0
  166. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_provenance_revinclude_search_test.rb +51 -0
  167. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_read_test.rb +24 -0
  168. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_reference_resolution_test.rb +28 -0
  169. data/lib/us_core_test_kit/generated/head_circumference/head_circumference_validation_test.rb +34 -0
  170. data/lib/us_core_test_kit/generated/head_circumference_group.rb +93 -0
  171. data/lib/us_core_test_kit/generated/heartrate/heartrate_must_support_test.rb +49 -0
  172. data/lib/us_core_test_kit/generated/heartrate/heartrate_patient_category_date_search_test.rb +46 -0
  173. data/lib/us_core_test_kit/generated/heartrate/heartrate_patient_category_search_test.rb +45 -0
  174. data/lib/us_core_test_kit/generated/heartrate/heartrate_patient_category_status_search_test.rb +47 -0
  175. data/lib/us_core_test_kit/generated/heartrate/heartrate_patient_code_date_search_test.rb +48 -0
  176. data/lib/us_core_test_kit/generated/heartrate/heartrate_patient_code_search_test.rb +62 -0
  177. data/lib/us_core_test_kit/generated/heartrate/heartrate_provenance_revinclude_search_test.rb +51 -0
  178. data/lib/us_core_test_kit/generated/heartrate/heartrate_read_test.rb +24 -0
  179. data/lib/us_core_test_kit/generated/heartrate/heartrate_reference_resolution_test.rb +28 -0
  180. data/lib/us_core_test_kit/generated/heartrate/heartrate_validation_test.rb +34 -0
  181. data/lib/us_core_test_kit/generated/heartrate_group.rb +93 -0
  182. data/lib/us_core_test_kit/generated/immunization/immunization_must_support_test.rb +40 -0
  183. data/lib/us_core_test_kit/generated/immunization/immunization_patient_date_search_test.rb +47 -0
  184. data/lib/us_core_test_kit/generated/immunization/immunization_patient_search_test.rb +60 -0
  185. data/lib/us_core_test_kit/generated/immunization/immunization_patient_status_search_test.rb +45 -0
  186. data/lib/us_core_test_kit/generated/immunization/immunization_provenance_revinclude_search_test.rb +50 -0
  187. data/lib/us_core_test_kit/generated/immunization/immunization_read_test.rb +24 -0
  188. data/lib/us_core_test_kit/generated/immunization/immunization_reference_resolution_test.rb +28 -0
  189. data/lib/us_core_test_kit/generated/immunization/immunization_validation_test.rb +34 -0
  190. data/lib/us_core_test_kit/generated/immunization_group.rb +87 -0
  191. data/lib/us_core_test_kit/generated/medication_request/medication_request_must_support_test.rb +44 -0
  192. data/lib/us_core_test_kit/generated/medication_request/medication_request_patient_intent_authoredon_search_test.rb +53 -0
  193. data/lib/us_core_test_kit/generated/medication_request/medication_request_patient_intent_encounter_search_test.rb +52 -0
  194. data/lib/us_core_test_kit/generated/medication_request/medication_request_patient_intent_search_test.rb +68 -0
  195. data/lib/us_core_test_kit/generated/medication_request/medication_request_patient_intent_status_search_test.rb +49 -0
  196. data/lib/us_core_test_kit/generated/medication_request/medication_request_provenance_revinclude_search_test.rb +51 -0
  197. data/lib/us_core_test_kit/generated/medication_request/medication_request_read_test.rb +24 -0
  198. data/lib/us_core_test_kit/generated/medication_request/medication_request_reference_resolution_test.rb +28 -0
  199. data/lib/us_core_test_kit/generated/medication_request/medication_request_validation_test.rb +34 -0
  200. data/lib/us_core_test_kit/generated/medication_request/medication_validation_test.rb +34 -0
  201. data/lib/us_core_test_kit/generated/medication_request_group.rb +92 -0
  202. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_must_support_test.rb +41 -0
  203. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_patient_category_date_search_test.rb +46 -0
  204. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_patient_category_search_test.rb +62 -0
  205. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_patient_category_status_search_test.rb +47 -0
  206. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_patient_code_date_search_test.rb +48 -0
  207. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_patient_code_search_test.rb +45 -0
  208. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_provenance_revinclude_search_test.rb +51 -0
  209. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_read_test.rb +24 -0
  210. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_reference_resolution_test.rb +28 -0
  211. data/lib/us_core_test_kit/generated/observation_lab/observation_lab_validation_test.rb +34 -0
  212. data/lib/us_core_test_kit/generated/observation_lab_group.rb +93 -0
  213. data/lib/us_core_test_kit/generated/organization/organization_address_search_test.rb +39 -0
  214. data/lib/us_core_test_kit/generated/organization/organization_must_support_test.rb +47 -0
  215. data/lib/us_core_test_kit/generated/organization/organization_name_search_test.rb +49 -0
  216. data/lib/us_core_test_kit/generated/organization/organization_read_test.rb +24 -0
  217. data/lib/us_core_test_kit/generated/organization/organization_reference_resolution_test.rb +28 -0
  218. data/lib/us_core_test_kit/generated/organization/organization_validation_test.rb +34 -0
  219. data/lib/us_core_test_kit/generated/organization_group.rb +84 -0
  220. data/lib/us_core_test_kit/generated/patient/patient_birthdate_family_search_test.rb +41 -0
  221. data/lib/us_core_test_kit/generated/patient/patient_birthdate_name_search_test.rb +39 -0
  222. data/lib/us_core_test_kit/generated/patient/patient_family_gender_search_test.rb +41 -0
  223. data/lib/us_core_test_kit/generated/patient/patient_gender_name_search_test.rb +39 -0
  224. data/lib/us_core_test_kit/generated/patient/patient_id_search_test.rb +53 -0
  225. data/lib/us_core_test_kit/generated/patient/patient_identifier_search_test.rb +40 -0
  226. data/lib/us_core_test_kit/generated/patient/patient_must_support_test.rb +57 -0
  227. data/lib/us_core_test_kit/generated/patient/patient_name_search_test.rb +39 -0
  228. data/lib/us_core_test_kit/generated/patient/patient_provenance_revinclude_search_test.rb +49 -0
  229. data/lib/us_core_test_kit/generated/patient/patient_read_test.rb +24 -0
  230. data/lib/us_core_test_kit/generated/patient/patient_reference_resolution_test.rb +28 -0
  231. data/lib/us_core_test_kit/generated/patient/patient_validation_test.rb +34 -0
  232. data/lib/us_core_test_kit/generated/patient_group.rb +99 -0
  233. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_must_support_test.rb +49 -0
  234. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_patient_category_date_search_test.rb +46 -0
  235. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_patient_category_search_test.rb +45 -0
  236. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_patient_category_status_search_test.rb +47 -0
  237. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_patient_code_date_search_test.rb +48 -0
  238. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_patient_code_search_test.rb +62 -0
  239. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_provenance_revinclude_search_test.rb +51 -0
  240. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_read_test.rb +24 -0
  241. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_reference_resolution_test.rb +28 -0
  242. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age/pediatric_bmi_for_age_validation_test.rb +34 -0
  243. data/lib/us_core_test_kit/generated/pediatric_bmi_for_age_group.rb +93 -0
  244. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_must_support_test.rb +49 -0
  245. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_patient_category_date_search_test.rb +46 -0
  246. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_patient_category_search_test.rb +45 -0
  247. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_patient_category_status_search_test.rb +47 -0
  248. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_patient_code_date_search_test.rb +48 -0
  249. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_patient_code_search_test.rb +62 -0
  250. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_provenance_revinclude_search_test.rb +51 -0
  251. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_read_test.rb +24 -0
  252. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_reference_resolution_test.rb +28 -0
  253. data/lib/us_core_test_kit/generated/pediatric_weight_for_height/pediatric_weight_for_height_validation_test.rb +34 -0
  254. data/lib/us_core_test_kit/generated/pediatric_weight_for_height_group.rb +93 -0
  255. data/lib/us_core_test_kit/generated/practitioner/practitioner_identifier_search_test.rb +40 -0
  256. data/lib/us_core_test_kit/generated/practitioner/practitioner_must_support_test.rb +40 -0
  257. data/lib/us_core_test_kit/generated/practitioner/practitioner_name_search_test.rb +49 -0
  258. data/lib/us_core_test_kit/generated/practitioner/practitioner_read_test.rb +24 -0
  259. data/lib/us_core_test_kit/generated/practitioner/practitioner_reference_resolution_test.rb +28 -0
  260. data/lib/us_core_test_kit/generated/practitioner/practitioner_validation_test.rb +34 -0
  261. data/lib/us_core_test_kit/generated/practitioner_group.rb +84 -0
  262. data/lib/us_core_test_kit/generated/procedure/procedure_must_support_test.rb +38 -0
  263. data/lib/us_core_test_kit/generated/procedure/procedure_patient_code_date_search_test.rb +48 -0
  264. data/lib/us_core_test_kit/generated/procedure/procedure_patient_date_search_test.rb +45 -0
  265. data/lib/us_core_test_kit/generated/procedure/procedure_patient_search_test.rb +60 -0
  266. data/lib/us_core_test_kit/generated/procedure/procedure_patient_status_search_test.rb +46 -0
  267. data/lib/us_core_test_kit/generated/procedure/procedure_provenance_revinclude_search_test.rb +50 -0
  268. data/lib/us_core_test_kit/generated/procedure/procedure_read_test.rb +24 -0
  269. data/lib/us_core_test_kit/generated/procedure/procedure_reference_resolution_test.rb +28 -0
  270. data/lib/us_core_test_kit/generated/procedure/procedure_validation_test.rb +34 -0
  271. data/lib/us_core_test_kit/generated/procedure_group.rb +90 -0
  272. data/lib/us_core_test_kit/generated/provenance/provenance_must_support_test.rb +44 -0
  273. data/lib/us_core_test_kit/generated/provenance/provenance_read_test.rb +24 -0
  274. data/lib/us_core_test_kit/generated/provenance/provenance_reference_resolution_test.rb +28 -0
  275. data/lib/us_core_test_kit/generated/provenance/provenance_validation_test.rb +34 -0
  276. data/lib/us_core_test_kit/generated/provenance_group.rb +56 -0
  277. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_must_support_test.rb +65 -0
  278. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_patient_category_date_search_test.rb +46 -0
  279. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_patient_category_search_test.rb +45 -0
  280. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_patient_category_status_search_test.rb +47 -0
  281. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_patient_code_date_search_test.rb +48 -0
  282. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_patient_code_search_test.rb +62 -0
  283. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_provenance_revinclude_search_test.rb +51 -0
  284. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_read_test.rb +24 -0
  285. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_reference_resolution_test.rb +28 -0
  286. data/lib/us_core_test_kit/generated/pulse_oximetry/pulse_oximetry_validation_test.rb +34 -0
  287. data/lib/us_core_test_kit/generated/pulse_oximetry_group.rb +93 -0
  288. data/lib/us_core_test_kit/generated/resource_list.rb +26 -0
  289. data/lib/us_core_test_kit/generated/resprate/resprate_must_support_test.rb +49 -0
  290. data/lib/us_core_test_kit/generated/resprate/resprate_patient_category_date_search_test.rb +46 -0
  291. data/lib/us_core_test_kit/generated/resprate/resprate_patient_category_search_test.rb +45 -0
  292. data/lib/us_core_test_kit/generated/resprate/resprate_patient_category_status_search_test.rb +47 -0
  293. data/lib/us_core_test_kit/generated/resprate/resprate_patient_code_date_search_test.rb +48 -0
  294. data/lib/us_core_test_kit/generated/resprate/resprate_patient_code_search_test.rb +62 -0
  295. data/lib/us_core_test_kit/generated/resprate/resprate_provenance_revinclude_search_test.rb +51 -0
  296. data/lib/us_core_test_kit/generated/resprate/resprate_read_test.rb +24 -0
  297. data/lib/us_core_test_kit/generated/resprate/resprate_reference_resolution_test.rb +28 -0
  298. data/lib/us_core_test_kit/generated/resprate/resprate_validation_test.rb +34 -0
  299. data/lib/us_core_test_kit/generated/resprate_group.rb +93 -0
  300. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_must_support_test.rb +39 -0
  301. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_patient_category_date_search_test.rb +48 -0
  302. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_patient_category_search_test.rb +47 -0
  303. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_patient_category_status_search_test.rb +47 -0
  304. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_patient_code_date_search_test.rb +48 -0
  305. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_patient_code_search_test.rb +62 -0
  306. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_provenance_revinclude_search_test.rb +51 -0
  307. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_read_test.rb +24 -0
  308. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_reference_resolution_test.rb +28 -0
  309. data/lib/us_core_test_kit/generated/smokingstatus/smokingstatus_validation_test.rb +34 -0
  310. data/lib/us_core_test_kit/generated/smokingstatus_group.rb +93 -0
  311. data/lib/us_core_test_kit/generated/us_core_test_suite.rb +110 -0
  312. data/lib/us_core_test_kit/generator/group_generator.rb +171 -0
  313. data/lib/us_core_test_kit/generator/group_metadata.rb +98 -0
  314. data/lib/us_core_test_kit/generator/group_metadata_extractor.rb +281 -0
  315. data/lib/us_core_test_kit/generator/ig_loader.rb +63 -0
  316. data/lib/us_core_test_kit/generator/ig_metadata.rb +49 -0
  317. data/lib/us_core_test_kit/generator/ig_metadata_extractor.rb +56 -0
  318. data/lib/us_core_test_kit/generator/ig_resources.rb +48 -0
  319. data/lib/us_core_test_kit/generator/must_support_metadata_extractor.rb +221 -0
  320. data/lib/us_core_test_kit/generator/must_support_test_generator.rb +86 -0
  321. data/lib/us_core_test_kit/generator/naming.rb +58 -0
  322. data/lib/us_core_test_kit/generator/provenance_revinclude_search_test_generator.rb +186 -0
  323. data/lib/us_core_test_kit/generator/read_test_generator.rb +89 -0
  324. data/lib/us_core_test_kit/generator/reference_resolution_test_generator.rb +72 -0
  325. data/lib/us_core_test_kit/generator/resource_list_generator.rb +46 -0
  326. data/lib/us_core_test_kit/generator/search_definition_metadata_extractor.rb +181 -0
  327. data/lib/us_core_test_kit/generator/search_metadata_extractor.rb +74 -0
  328. data/lib/us_core_test_kit/generator/search_test_generator.rb +280 -0
  329. data/lib/us_core_test_kit/generator/special_cases.rb +17 -0
  330. data/lib/us_core_test_kit/generator/suite_generator.rb +67 -0
  331. data/lib/us_core_test_kit/generator/terminology_binding_metadata_extractor.rb +105 -0
  332. data/lib/us_core_test_kit/generator/validation_test_generator.rb +124 -0
  333. data/lib/us_core_test_kit/generator.rb +86 -0
  334. data/lib/us_core_test_kit/igs/StructureDefinition-bodyheight.json +3772 -0
  335. data/lib/us_core_test_kit/igs/StructureDefinition-bodytemp.json +3772 -0
  336. data/lib/us_core_test_kit/igs/StructureDefinition-bodyweight.json +3772 -0
  337. data/lib/us_core_test_kit/igs/StructureDefinition-bp.json +6034 -0
  338. data/lib/us_core_test_kit/igs/StructureDefinition-heartrate.json +3756 -0
  339. data/lib/us_core_test_kit/igs/StructureDefinition-resprate.json +3756 -0
  340. data/lib/us_core_test_kit/igs/package.tgz +0 -0
  341. data/lib/us_core_test_kit/must_support_test.rb +146 -0
  342. data/lib/us_core_test_kit/read_test.rb +62 -0
  343. data/lib/us_core_test_kit/reference_resolution_test.rb +111 -0
  344. data/lib/us_core_test_kit/request_logger.rb +46 -0
  345. data/lib/us_core_test_kit/search_test.rb +686 -0
  346. data/lib/us_core_test_kit/search_test_properties.rb +56 -0
  347. data/lib/us_core_test_kit/validation_test.rb +48 -0
  348. data/lib/us_core_test_kit/version.rb +3 -0
  349. data/lib/us_core_test_kit.rb +2 -0
  350. metadata +477 -0
@@ -0,0 +1,686 @@
1
+ require_relative 'date_search_validation'
2
+ require_relative 'fhir_resource_navigation'
3
+ require_relative 'search_test_properties'
4
+
5
+ module USCoreTestKit
6
+ module SearchTest
7
+ extend Forwardable
8
+ include DateSearchValidation
9
+ include FHIRResourceNavigation
10
+
11
+ def_delegators 'self.class', :metadata, :provenance_metadata, :properties
12
+ def_delegators 'properties',
13
+ :resource_type,
14
+ :search_param_names,
15
+ :saves_delayed_references?,
16
+ :first_search?,
17
+ :fixed_value_search?,
18
+ :possible_status_search?,
19
+ :test_medication_inclusion?,
20
+ :test_post_search?,
21
+ :token_search_params,
22
+ :test_reference_variants?,
23
+ :params_with_comparators,
24
+ :multiple_or_search_params
25
+
26
+ def all_search_params
27
+ @all_search_params ||=
28
+ patient_id_list.each_with_object({}) do |patient_id, params|
29
+ params[patient_id] ||= []
30
+ new_params =
31
+ if fixed_value_search?
32
+ fixed_value_search_param_values.map { |value| fixed_value_search_params(value, patient_id) }
33
+ else
34
+ [search_params_with_values(patient_id)]
35
+ end
36
+ new_params.reject! do |params|
37
+ params.any? { |_key, value| value.blank? }
38
+ end
39
+
40
+ params[patient_id].concat(new_params)
41
+ end
42
+ end
43
+
44
+ def all_provenance_revinclude_search_params
45
+ @all_provenance_revinclude_search_params ||=
46
+ all_search_params.transform_values! do |params_list|
47
+ params_list.map { |params| params.merge(_revinclude: 'Provenance:target') }
48
+ end
49
+ end
50
+
51
+ def any_valid_search_params?(search_params)
52
+ search_params.any? { |_patient_id, params| params.present? }
53
+ end
54
+
55
+ def run_provenance_revinclude_search_test
56
+ # TODO: skip if not supported?
57
+ skip_if !any_valid_search_params?(all_provenance_revinclude_search_params), unable_to_resolve_params_message
58
+
59
+ provenance_resources =
60
+ all_provenance_revinclude_search_params.flat_map do |_patient_id, params_list|
61
+ params_list.flat_map do |params|
62
+ fhir_search resource_type, params: params
63
+
64
+ perform_search_with_status(params, patient_id) if response[:status] == 400 && possible_status_search?
65
+
66
+ check_search_response
67
+
68
+ fetch_all_bundled_resources(additional_resource_types: ['Provenance'])
69
+ .select { |resource| resource.resourceType == 'Provenance' }
70
+ end
71
+ end
72
+
73
+ scratch_provenance_resources[:all] ||= []
74
+ scratch_provenance_resources[:all].concat(provenance_resources)
75
+
76
+ save_delayed_references(provenance_resources, 'Provenance')
77
+
78
+ skip_if provenance_resources.empty?, no_resources_skip_message('Provenance')
79
+ end
80
+
81
+ def run_search_test
82
+ # TODO: skip if not supported?
83
+ skip_if !any_valid_search_params?(all_search_params), unable_to_resolve_params_message
84
+
85
+ resources_returned =
86
+ all_search_params.flat_map do |patient_id, params_list|
87
+ params_list.flat_map { |params| perform_search(params, patient_id) }
88
+ end
89
+
90
+ skip_if resources_returned.empty?, no_resources_skip_message
91
+
92
+ perform_multiple_or_search_test if multiple_or_search_params.present?
93
+ end
94
+
95
+ def perform_search(params, patient_id)
96
+ fhir_search resource_type, params: params
97
+
98
+ perform_search_with_status(params, patient_id) if response[:status] == 400 && possible_status_search?
99
+
100
+ check_search_response
101
+
102
+ resources_returned =
103
+ fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
104
+
105
+ return [] if resources_returned.blank?
106
+
107
+ perform_comparator_searches(params, patient_id) if params_with_comparators.present?
108
+
109
+ filter_devices(resources_returned) if resource_type == 'Device'
110
+
111
+ if first_search?
112
+ all_scratch_resources.concat(resources_returned).uniq!
113
+ scratch_resources_for_patient(patient_id).concat(resources_returned).uniq!
114
+ end
115
+
116
+ resources_returned.each do |resource|
117
+ check_resource_against_params(resource, params)
118
+ end
119
+
120
+ save_delayed_references(resources_returned) if saves_delayed_references?
121
+
122
+ return resources_returned if all_search_variants_tested?
123
+
124
+ perform_post_search(resources_returned, params) if test_post_search?
125
+ test_medication_inclusion(resources_returned, params, patient_id) if test_medication_inclusion?
126
+ perform_reference_with_type_search(params, resources_returned.count) if test_reference_variants?
127
+ perform_search_with_system(params, patient_id) if token_search_params.present?
128
+
129
+ resources_returned
130
+ end
131
+
132
+ def perform_post_search(get_search_resources, params)
133
+ fhir_search resource_type, params: params, search_method: :post
134
+
135
+ check_search_response
136
+
137
+ post_search_resources = fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
138
+ get_resource_count = get_search_resources.length
139
+ post_resource_count = post_search_resources.length
140
+
141
+ search_variant_test_records[:post_variant] = true
142
+
143
+ assert get_resource_count == post_resource_count,
144
+ "Expected search by POST to return the same results as search by GET, " \
145
+ "but GET search returned #{get_resource_count} resources, and POST search " \
146
+ "returned #{post_resource_count} resources."
147
+ end
148
+
149
+ def filter_devices(resources)
150
+ codes_to_include = implantable_device_codes&.split(',')&.map(&:strip)
151
+ return resources if codes_to_include.blank?
152
+
153
+ resources.select! do |resource|
154
+ resource&.type&.coding&.any? { |coding| codes_to_include.include?(coding.code) }
155
+ end
156
+ end
157
+
158
+ def search_and_check_response(params, resource_type = self.resource_type)
159
+ fhir_search resource_type, params: params
160
+
161
+ check_search_response
162
+ end
163
+
164
+ def check_search_response
165
+ assert_response_status(200)
166
+ assert_resource_type(:bundle)
167
+ # NOTE: how do we want to handle validating Bundles?
168
+ end
169
+
170
+ def search_variant_test_records
171
+ @search_variant_test_records ||= initial_search_variant_test_records
172
+ end
173
+
174
+ def initial_search_variant_test_records
175
+ {}.tap do |records|
176
+ records[:post_variant] = false if test_post_search?
177
+ records[:medication_inclusion] = false if test_medication_inclusion?
178
+ records[:reference_variants] = false if test_reference_variants?
179
+ records[:token_variants] = false if token_search_params.present?
180
+ records[:comparator_searches] = Set.new if params_with_comparators.present?
181
+ end
182
+ end
183
+
184
+ def all_search_variants_tested?
185
+ search_variant_test_records.all? { |_variant, tested| tested.present? } &&
186
+ all_comparator_searches_tested?
187
+ end
188
+
189
+ def all_comparator_searches_tested?
190
+ return true if params_with_comparators.blank?
191
+
192
+ Set.new(params_with_comparators) == search_variant_test_records[:comparator_searches]
193
+ end
194
+
195
+ def date_comparator_value(comparator, date)
196
+ date = date.start || date.end if date.is_a? FHIR::Period
197
+ case comparator
198
+ when 'lt', 'le'
199
+ comparator + (DateTime.xmlschema(date) + 1).xmlschema
200
+ when 'gt', 'ge'
201
+ comparator + (DateTime.xmlschema(date) - 1).xmlschema
202
+ else
203
+ # ''
204
+ raise "Unsupported comparator '#{comparator}'"
205
+ end
206
+ end
207
+
208
+ def required_comparators(name)
209
+ metadata
210
+ .search_definitions
211
+ .dig(name.to_sym, :comparators)
212
+ .select { |_comparator, expectation| expectation == 'SHALL' }
213
+ .keys
214
+ .map(&:to_s)
215
+ end
216
+
217
+ def perform_comparator_searches(params, patient_id)
218
+ params_with_comparators.each do |name|
219
+ next if search_variant_test_records[:comparator_searches].include? name
220
+
221
+ required_comparators(name).each do |comparator|
222
+ path = search_param_path(name)
223
+ date_element = find_a_value_at(scratch_resources_for_patient(patient_id), path)
224
+ params_with_comparator = params.merge(name => date_comparator_value(comparator, date_element))
225
+
226
+ search_and_check_response(params_with_comparator)
227
+
228
+ fetch_all_bundled_resources
229
+ .each { |resource| check_resource_against_params(resource, params_with_comparator) }
230
+ end
231
+
232
+ search_variant_test_records[:comparator_searches] << name
233
+ end
234
+ end
235
+
236
+ def perform_reference_with_type_search(params, resource_count)
237
+ return if resource_count == 0
238
+ return if search_variant_test_records[:reference_variants]
239
+
240
+ new_search_params = params.merge('patient' => "Patient/#{params['patient']}")
241
+ search_and_check_response(new_search_params)
242
+
243
+ new_resource_count =
244
+ fetch_all_bundled_resources
245
+ .select { |resource| resource.resourceType == resource_type }
246
+ .count
247
+
248
+ assert new_resource_count == resource_count,
249
+ "Expected search by `#{params['patient']}` to to return the same results as searching " \
250
+ "by `#{new_search_params['patient']}`, but found #{resource_count} resources with " \
251
+ "`#{params['patient']}` and #{new_resource_count} with `#{new_search_params['patient']}`"
252
+
253
+ search_variant_test_records[:reference_variants] = true
254
+ end
255
+
256
+ def perform_search_with_system(params, patient_id)
257
+ return if search_variant_test_records[:token_variants]
258
+
259
+ new_search_params = token_search_params.each_with_object({}) do |name, search_params|
260
+ search_params[name] = search_param_value(name, patient_id, include_system: true)
261
+ end
262
+ return if new_search_params.any? { |_name, value| value.blank? }
263
+
264
+ search_params = params.merge(new_search_params)
265
+ search_and_check_response(search_params)
266
+
267
+ resources_returned =
268
+ fetch_all_bundled_resources
269
+ .select { |resource| resource.resourceType == resource_type }
270
+
271
+ assert resources_returned.present?, "No resources were returned when searching by `system|code`"
272
+
273
+ search_variant_test_records[:token_variants] = true
274
+ end
275
+
276
+ def perform_search_with_status(
277
+ original_params,
278
+ patient_id,
279
+ status_search_values: self.status_search_values,
280
+ resource_type: self.resource_type
281
+ )
282
+ assert resource.is_a?(FHIR::OperationOutcome), "Server returned a status of 400 without an OperationOutcome"
283
+ # TODO: warn about documenting status requirements
284
+ status_search_values.flat_map do |status_value|
285
+ search_params = original_params.merge("#{status_search_param_name}": status_value)
286
+
287
+ search_and_check_response(search_params)
288
+
289
+ entries = resource.entry.select { |entry| entry.resource.resourceType == resource_type }
290
+
291
+ if entries.present?
292
+ original_params.merge!("#{status_search_param_name}": status_value)
293
+ break
294
+ end
295
+ end
296
+ end
297
+
298
+ def status_search_param_name
299
+ @status_search_param_name ||=
300
+ metadata.search_definitions.keys.find { |key| key.to_s.include? 'status' }
301
+ end
302
+
303
+ def status_search_values
304
+ default_search_values(status_search_param_name)
305
+ end
306
+
307
+ def default_search_values(param_name)
308
+ definition = metadata.search_definitions[param_name]
309
+ return [] if definition.blank?
310
+
311
+ definition[:multiple_or] == 'SHALL' ? [definition[:values].join(',')] : [definition[:values]]
312
+ end
313
+
314
+
315
+ def perform_multiple_or_search_test
316
+ resolved_one = false
317
+
318
+ all_search_params.each do |patient_id, params_list|
319
+ next unless params_list.present?
320
+
321
+ search_params = params_list.first
322
+ existing_values = {}
323
+ missing_values = {}
324
+
325
+ multiple_or_search_params.each do |param_name|
326
+ search_value = default_search_values(param_name.to_sym)
327
+ search_params = search_params.merge("#{param_name}" => search_value)
328
+ existing_values[param_name.to_sym] = scratch_resources_for_patient(patient_id).map(&param_name.to_sym).compact.uniq
329
+ end
330
+
331
+ # skip patient without multiple-or values
332
+ next if existing_values.values.any?(&:empty?)
333
+
334
+ resolved_one = true
335
+
336
+ search_and_check_response(search_params)
337
+
338
+ resources_returned =
339
+ fetch_all_bundled_resources
340
+ .select { |resource| resource.resourceType == resource_type }
341
+
342
+ multiple_or_search_params.each do |param_name|
343
+ missing_values[param_name.to_sym] = existing_values[param_name.to_sym] - resources_returned.map(&param_name.to_sym)
344
+ end
345
+
346
+ missing_value_message = missing_values
347
+ .reject { |_param_name, missing_value| missing_value.empty? }
348
+ .map { |param_name, missing_value| "#{missing_value.join(',')} values from #{param_name}" }
349
+ .join(' and ')
350
+
351
+ assert missing_value_message.blank?, "Could not find #{missing_value_message} in any of the resources returned for Patient/#{patient_id}"
352
+
353
+ break if resolved_one
354
+ end
355
+ end
356
+
357
+ def test_medication_inclusion(medication_requests, params, patient_id)
358
+ return if search_variant_test_records[:medication_inclusion]
359
+
360
+ scratch[:medication_resources] ||= {}
361
+ scratch[:medication_resources][:all] ||= []
362
+ scratch[:medication_resources][patient_id] ||= []
363
+ scratch[:medication_resources][:contained] ||= []
364
+
365
+ requests_with_external_references =
366
+ medication_requests
367
+ .select { |request| request&.medicationReference&.present? }
368
+ .reject { |request| request&.medicationReference&.reference&.start_with? '#' }
369
+
370
+ contained_medications =
371
+ medication_requests
372
+ .select { |request| request&.medicationReference&.reference&.start_with? '#' }
373
+ .flat_map(&:contained)
374
+ .select { |resource| resource.resourceType == 'Medication' }
375
+
376
+ scratch[:medication_resources][:all] += contained_medications
377
+ scratch[:medication_resources][patient_id] += contained_medications
378
+ scratch[:medication_resources][:contained] += contained_medications
379
+
380
+ return if requests_with_external_references.blank?
381
+
382
+ search_params = params.merge(_include: 'MedicationRequest:medication')
383
+
384
+ search_and_check_response(search_params)
385
+
386
+ medications = fetch_all_bundled_resources.select { |resource| resource.resourceType == 'Medication' }
387
+ assert medications.present?, 'No Medications were included in the search results'
388
+
389
+ medications.uniq!(&:id)
390
+
391
+ scratch[:medication_resources][:all] += medications
392
+ scratch[:medication_resources][patient_id] += medications
393
+
394
+ search_variant_test_records[:medication_inclusion] = true
395
+ end
396
+
397
+ def all_scratch_resources
398
+ scratch_resources[:all] ||= []
399
+ end
400
+
401
+ def scratch_resources_for_patient(patient_id)
402
+ return all_scratch_resources if patient_id.nil?
403
+
404
+ scratch_resources[patient_id] ||= []
405
+ end
406
+
407
+ def references_to_save(resource_type = nil)
408
+ reference_metadata = resource_type == 'Provenance' ? provenance_metadata : metadata
409
+ reference_metadata.delayed_references
410
+ end
411
+
412
+ def fixed_value_search_param_name
413
+ (search_param_names - ['patient']).first
414
+ end
415
+
416
+ def fixed_value_search_param_values
417
+ metadata.search_definitions[fixed_value_search_param_name.to_sym][:values]
418
+ end
419
+
420
+ def fixed_value_search_params(value, patient_id)
421
+ search_param_names.each_with_object({}) do |name, params|
422
+ patient_id_param?(name) ? params[name] = patient_id : params[name] = value
423
+ end
424
+ end
425
+
426
+ def search_params_with_values(patient_id)
427
+ search_param_names.each_with_object({}) do |name, params|
428
+ value = patient_id_param?(name) ? patient_id : search_param_value(name, patient_id)
429
+ params[name] = value
430
+ end
431
+ end
432
+
433
+ def patient_id_list
434
+ return [nil] unless respond_to? :patient_ids
435
+
436
+ patient_ids.split(',').map(&:strip)
437
+ end
438
+
439
+ def patient_search?
440
+ search_param_names.any? { |name| patient_id_param? name }
441
+ end
442
+
443
+ def patient_id_param?(name)
444
+ name == 'patient' || (name == '_id' && resource_type == 'Patient')
445
+ end
446
+
447
+ def search_param_path(name)
448
+ path = metadata.search_definitions[name.to_sym][:path]
449
+ path == 'class' ? 'local_class' : path
450
+ end
451
+
452
+ def all_search_params_present?(params)
453
+ params.all? { |_name, value| value.present? }
454
+ end
455
+
456
+ def array_of_codes(array)
457
+ array.map { |name| "`#{name}`" }.join(', ')
458
+ end
459
+
460
+ def unable_to_resolve_params_message
461
+ "Could not find values for all search params #{array_of_codes(search_param_names)}"
462
+ end
463
+
464
+ def empty_search_params_message(empty_search_params)
465
+ "Could not find values for the search parameters #{array_of_codes(empty_search_params.keys)}"
466
+ end
467
+
468
+ def no_resources_skip_message(resource_type = self.resource_type)
469
+ "No #{resource_type} resources appear to be available. " \
470
+ "Please use patients with more information"
471
+ end
472
+
473
+ def fetch_all_bundled_resources(
474
+ reply_handler: nil,
475
+ max_pages: 20,
476
+ additional_resource_types: [],
477
+ resource_type: self.resource_type
478
+ )
479
+ page_count = 1
480
+ resources = []
481
+ bundle = resource
482
+
483
+ until bundle.nil? || page_count == max_pages
484
+ resources += bundle&.entry&.map { |entry| entry&.resource }
485
+ next_bundle_link = bundle&.link&.find { |link| link.relation == 'next' }&.url
486
+ reply_handler&.call(response)
487
+
488
+ break if next_bundle_link.blank?
489
+
490
+ reply = fhir_client.raw_read_url(next_bundle_link)
491
+
492
+ store_request('outgoing') { reply }
493
+ error_message = cant_resolve_next_bundle_message(next_bundle_link)
494
+
495
+ assert_response_status(200)
496
+ assert_valid_json(reply.body, error_message)
497
+
498
+ bundle = fhir_client.parse_reply(FHIR::Bundle, fhir_client.default_format, reply)
499
+
500
+ page_count += 1
501
+ end
502
+
503
+ valid_resource_types = [resource_type, 'OperationOutcome'].concat(additional_resource_types)
504
+ valid_resource_types << 'Medication' if resource_type == 'MedicationRequest'
505
+
506
+ all_valid_resource_types =
507
+ resources.all? { |entry| valid_resource_types.include? entry.resourceType }
508
+
509
+ assert all_valid_resource_types,
510
+ "All resources returned must be of the type: #{valid_resource_types.join(', ')}"
511
+
512
+ resources
513
+ end
514
+
515
+ def cant_resolve_next_bundle_message(link)
516
+ "Could not resolve next bundle: #{link}"
517
+ end
518
+
519
+ def search_param_value(name, patient_id, include_system: false)
520
+ path = search_param_path(name)
521
+ element = find_a_value_at(scratch_resources_for_patient(patient_id), path)
522
+ search_value =
523
+ case element
524
+ when FHIR::Period
525
+ if element.start.present?
526
+ 'gt' + (DateTime.xmlschema(element.start) - 1).xmlschema
527
+ else
528
+ end_datetime = get_fhir_datetime_range(element.end)[:end]
529
+ 'lt' + (end_datetime + 1).xmlschema
530
+ end
531
+ when FHIR::Reference
532
+ element.reference
533
+ when FHIR::CodeableConcept
534
+ if include_system
535
+ coding =
536
+ find_a_value_at(element, 'coding') { |coding| coding.code.present? && coding.system.present? }
537
+ coding.present? ? "#{coding.system}|#{coding.code}" : nil
538
+ else
539
+ find_a_value_at(element, 'coding.code')
540
+ end
541
+ when FHIR::Identifier
542
+ if include_system
543
+ identifier = find_a_value_at(scratch_resources_for_patient(patient_id), path) do |identifier|
544
+ identifier.value.present? && identifier.system.present?
545
+ end
546
+ identifier.present? ? "#{identifier.system}|#{identifier.value}" : nil
547
+ else
548
+ element.value
549
+ end
550
+ when FHIR::Coding
551
+ if include_system
552
+ coding = find_a_value_at(scratch_resources_for_patient(patient_id), path) do |coding|
553
+ coding.code.present? && coding.system.present?
554
+ end
555
+ coding.present? ? "#{coding.system}|#{coding.code}" : nil
556
+ else
557
+ element.code
558
+ end
559
+ when FHIR::HumanName
560
+ element.family || element.given&.first || element.text
561
+ when FHIR::Address
562
+ element.text || element.city || element.state || element.postalCode || element.country
563
+ else
564
+ element
565
+ end
566
+ escaped_value = search_value&.gsub(',', '\\,')
567
+ escaped_value
568
+ end
569
+
570
+ def save_resource_reference(resource_type, reference)
571
+ scratch[:references] ||= {}
572
+ scratch[:references][resource_type] ||= Set.new
573
+ scratch[:references][resource_type] << reference
574
+ end
575
+
576
+ def save_delayed_references(resources, containing_resource_type = self.resource_type)
577
+ resources.each do |resource|
578
+ references_to_save(containing_resource_type).each do |reference_to_save|
579
+ resolve_path(resource, reference_to_save[:path])
580
+ .select { |reference| reference.is_a?(FHIR::Reference) && !reference.contained? }
581
+ .each do |reference|
582
+ resource_type = reference.resource_class.name.demodulize
583
+ need_to_save = reference_to_save[:resources].include?(resource_type)
584
+ next unless need_to_save
585
+
586
+ save_resource_reference(resource_type, reference)
587
+ end
588
+ end
589
+ end
590
+ end
591
+
592
+ #### RESULT CHECKING ####
593
+
594
+ def check_resource_against_params(resource, params)
595
+ params.each do |name, search_value|
596
+ path = search_param_path(name)
597
+ type = metadata.search_definitions[name.to_sym][:type]
598
+ values_found =
599
+ resolve_path(resource, path)
600
+ .map do |value|
601
+ if value.is_a? FHIR::Reference
602
+ value.reference
603
+ else
604
+ value
605
+ end
606
+ end
607
+
608
+ match_found =
609
+ case type
610
+ when 'Period', 'date', 'instant', 'dateTime'
611
+ values_found.any? { |date| validate_date_search(search_value, date) }
612
+ when 'HumanName'
613
+ # When a string search parameter refers to the types HumanName and Address,
614
+ # the search covers the elements of type string, and does not cover elements such as use and period
615
+ # https://www.hl7.org/fhir/search.html#string
616
+ search_value_downcase = search_value.downcase
617
+ values_found.any? do |name|
618
+ name&.text&.downcase&.start_with?(search_value_downcase) ||
619
+ name&.family&.downcase&.start_with?(search_value_downcase) ||
620
+ name&.given&.any? { |given| given.downcase.start_with?(search_value_downcase) } ||
621
+ name&.prefix&.any? { |prefix| prefix.downcase.start_with?(search_value_downcase) } ||
622
+ name&.suffix&.any? { |suffix| suffix.downcase.start_with?(search_value_downcase) }
623
+ end
624
+ when 'Address'
625
+ search_value_downcase = search_value.downcase
626
+ values_found.any? do |address|
627
+ address&.text&.downcase&.start_with?(search_value_downcase) ||
628
+ address&.city&.downcase&.start_with?(search_value_downcase) ||
629
+ address&.state&.downcase&.start_with?(search_value_downcase) ||
630
+ address&.postalCode&.downcase&.start_with?(search_value_downcase) ||
631
+ address&.country&.downcase&.start_with?(search_value_downcase)
632
+ end
633
+ when 'CodeableConcept'
634
+ # FHIR token search (https://www.hl7.org/fhir/search.html#token): "When in doubt, servers SHOULD
635
+ # treat tokens in a case-insensitive manner, on the grounds that including undesired data has
636
+ # less safety implications than excluding desired behavior".
637
+ codings = values_found.flat_map(&:coding)
638
+ if search_value.include? '|'
639
+ system = search_value.split('|').first
640
+ code = search_value.split('|').last
641
+ codings&.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
642
+ else
643
+ codings&.any? { |coding| coding.code&.casecmp?(search_value) }
644
+ end
645
+ when 'Coding'
646
+ if search_value.include? '|'
647
+ system = search_value.split('|').first
648
+ code = search_value.split('|').last
649
+ values_found.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
650
+ else
651
+ values_found.any? { |coding| coding.code&.casecmp?(search_value) }
652
+ end
653
+ when 'Identifier'
654
+ if search_value.include? '|'
655
+ values_found.any? { |identifier| "#{identifier.system}|#{identifier.value}" == search_value }
656
+ else
657
+ values_found.any? { |identifier| identifier.value == search_value }
658
+ end
659
+ when 'string'
660
+ searched_values = search_value.downcase.split(/(?<!\\\\),/).map{ |string| string.gsub('\\,', ',') }
661
+ values_found.any? do |value_found|
662
+ searched_values.any? { |searched_value| value_found.downcase.starts_with? searched_value }
663
+ end
664
+ else
665
+ # searching by patient requires special case because we are searching by a resource identifier
666
+ # references can also be URL's, so we made need to resolve those url's
667
+ if ['subject', 'patient'].include? name.to_s
668
+ id = search_value.split('Patient/').last
669
+ possible_values = [id, 'Patient/' + id, "#{url}/Patient/\#{id}"]
670
+ values_found.any? do |reference|
671
+ possible_values.include? reference
672
+ end
673
+ else
674
+ search_values = search_value.split(/(?<!\\\\),/).map { |string| string.gsub('\\,', ',') }
675
+ values_found.any? { |value_found| search_values.include? value_found }
676
+ end
677
+ end
678
+
679
+ assert match_found,
680
+ "#{resource_type}/#{resource.id} did not match the search parameters:\n" \
681
+ "* Expected: #{search_value}\n" \
682
+ "* Found: #{values_found.map(&:inspect).join(', ')}"
683
+ end
684
+ end
685
+ end
686
+ end