davinci_plan_net_test_kit 0.9.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 (325) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/davinci_plan_net_test_kit/custom_groups/capability_statement/conformance_support_test.rb +41 -0
  4. data/lib/davinci_plan_net_test_kit/custom_groups/capability_statement/fhir_version_test.rb +15 -0
  5. data/lib/davinci_plan_net_test_kit/custom_groups/capability_statement/instantiate_test.rb +19 -0
  6. data/lib/davinci_plan_net_test_kit/custom_groups/capability_statement/json_support_test.rb +39 -0
  7. data/lib/davinci_plan_net_test_kit/custom_groups/capability_statement/profile_support_test.rb +38 -0
  8. data/lib/davinci_plan_net_test_kit/custom_groups/combination_searches/examples.json +40 -0
  9. data/lib/davinci_plan_net_test_kit/custom_groups/data_absent_reason_group.rb +59 -0
  10. data/lib/davinci_plan_net_test_kit/custom_groups/reverse_chain_tests/examples.json +60 -0
  11. data/lib/davinci_plan_net_test_kit/custom_groups/v1.1.0/capability_statement_group.rb +75 -0
  12. data/lib/davinci_plan_net_test_kit/date_search_validation.rb +108 -0
  13. data/lib/davinci_plan_net_test_kit/fhir_resource_navigation.rb +75 -0
  14. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/davinci_plan_net_test_suite.rb +231 -0
  15. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_forward_chain_organization_address_search_test.rb +55 -0
  16. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_forward_chain_organization_name_search_test.rb +55 -0
  17. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_forward_chain_organization_partof_search_test.rb +55 -0
  18. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_forward_chain_organization_type_search_test.rb +55 -0
  19. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_id_search_test.rb +41 -0
  20. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_include_endpoint_organization_search_test.rb +52 -0
  21. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_lastupdated_search_test.rb +43 -0
  22. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_must_support_test.rb +47 -0
  23. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_no_params_search_test.rb +49 -0
  24. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_organization_search_test.rb +41 -0
  25. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_read_test.rb +26 -0
  26. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_reference_resolution_test.rb +42 -0
  27. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/endpoint_validation_test.rb +40 -0
  28. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint/metadata.yml +171 -0
  29. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/endpoint_group.rb +168 -0
  30. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_combination_list_specialty_covered_by_network_search_test.rb +55 -0
  31. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_coverage_area_search_test.rb +41 -0
  32. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_endpoint_search_test.rb +41 -0
  33. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_endpoint_organization_search_test.rb +55 -0
  34. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_address_city_search_test.rb +55 -0
  35. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_address_postalcode_search_test.rb +55 -0
  36. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_address_search_test.rb +55 -0
  37. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_address_state_search_test.rb +55 -0
  38. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_organization_search_test.rb +55 -0
  39. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_location_type_search_test.rb +55 -0
  40. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_organization_address_search_test.rb +55 -0
  41. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_organization_name_search_test.rb +55 -0
  42. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_organization_partof_search_test.rb +55 -0
  43. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_forward_chain_organization_type_search_test.rb +55 -0
  44. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_id_search_test.rb +41 -0
  45. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_include_healthcare_service_coverage_area_search_test.rb +52 -0
  46. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_include_healthcare_service_endpoint_search_test.rb +52 -0
  47. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_include_healthcare_service_location_search_test.rb +52 -0
  48. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_include_healthcare_service_organization_search_test.rb +52 -0
  49. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_lastupdated_search_test.rb +43 -0
  50. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_location_search_test.rb +41 -0
  51. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_must_support_test.rb +65 -0
  52. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_name_search_test.rb +41 -0
  53. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_no_params_search_test.rb +49 -0
  54. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_organization_search_test.rb +41 -0
  55. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_read_test.rb +26 -0
  56. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_reference_resolution_test.rb +45 -0
  57. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_revinclude_organization_affiliation_service_search_test.rb +60 -0
  58. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_revinclude_practitioner_role_service_search_test.rb +60 -0
  59. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_service_category_search_test.rb +42 -0
  60. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_service_type_search_test.rb +42 -0
  61. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_specialty_search_test.rb +42 -0
  62. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/healthcare_service_validation_test.rb +40 -0
  63. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service/metadata.yml +1377 -0
  64. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/healthcare_service_group.rb +240 -0
  65. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_administered_by_search_test.rb +41 -0
  66. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_coverage_area_search_test.rb +41 -0
  67. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_forward_chain_administered_by_name_search_test.rb +55 -0
  68. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_forward_chain_administered_by_partof_search_test.rb +55 -0
  69. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_forward_chain_owned_by_name_search_test.rb +55 -0
  70. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_forward_chain_owned_by_partof_search_test.rb +55 -0
  71. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_id_search_test.rb +41 -0
  72. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_identifier_search_test.rb +44 -0
  73. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_include_insurance_plan_administered_by_search_test.rb +52 -0
  74. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_include_insurance_plan_coverage_area_search_test.rb +52 -0
  75. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_include_insurance_plan_owned_by_search_test.rb +52 -0
  76. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_lastupdated_search_test.rb +43 -0
  77. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_must_support_test.rb +57 -0
  78. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_name_search_test.rb +41 -0
  79. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_no_params_search_test.rb +49 -0
  80. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_owned_by_search_test.rb +41 -0
  81. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_plan_type_search_test.rb +42 -0
  82. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_read_test.rb +26 -0
  83. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_reference_resolution_test.rb +48 -0
  84. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_type_search_test.rb +42 -0
  85. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/insurance_plan_validation_test.rb +40 -0
  86. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan/metadata.yml +368 -0
  87. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/insurance_plan_group.rb +193 -0
  88. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_address_city_search_test.rb +41 -0
  89. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_address_postalcode_search_test.rb +41 -0
  90. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_address_search_test.rb +41 -0
  91. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_address_state_search_test.rb +41 -0
  92. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_endpoint_search_test.rb +41 -0
  93. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_endpoint_organization_search_test.rb +55 -0
  94. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_organization_address_search_test.rb +55 -0
  95. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_organization_name_search_test.rb +55 -0
  96. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_organization_partof_search_test.rb +55 -0
  97. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_organization_type_search_test.rb +55 -0
  98. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_partof_address_search_test.rb +55 -0
  99. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_partof_organization_search_test.rb +55 -0
  100. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_forward_chain_partof_type_search_test.rb +55 -0
  101. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_id_search_test.rb +41 -0
  102. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_include_location_endpoint_search_test.rb +52 -0
  103. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_include_location_organization_search_test.rb +52 -0
  104. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_include_location_partof_search_test.rb +52 -0
  105. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_lastupdated_search_test.rb +43 -0
  106. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_must_support_test.rb +66 -0
  107. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_no_params_search_test.rb +49 -0
  108. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_organization_search_test.rb +41 -0
  109. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_partof_search_test.rb +41 -0
  110. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_read_test.rb +26 -0
  111. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_reference_resolution_test.rb +44 -0
  112. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_reverse_chain_insurance_plan_coverage_area_owned_by_search_test.rb +62 -0
  113. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_revinclude_healthcare_service_location_search_test.rb +60 -0
  114. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_revinclude_insurance_plan_coverage_area_search_test.rb +60 -0
  115. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_revinclude_organization_affiliation_location_search_test.rb +60 -0
  116. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_revinclude_practitioner_role_location_search_test.rb +60 -0
  117. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_type_search_test.rb +42 -0
  118. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/location_validation_test.rb +40 -0
  119. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location/metadata.yml +395 -0
  120. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/location_group.rb +262 -0
  121. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/metadata.yml +5214 -0
  122. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/metadata.yml +304 -0
  123. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_address_search_test.rb +41 -0
  124. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_coverage_area_search_test.rb +41 -0
  125. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_endpoint_search_test.rb +41 -0
  126. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_forward_chain_endpoint_organization_search_test.rb +55 -0
  127. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_forward_chain_partof_address_search_test.rb +55 -0
  128. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_forward_chain_partof_name_search_test.rb +55 -0
  129. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_forward_chain_partof_type_search_test.rb +55 -0
  130. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_id_search_test.rb +41 -0
  131. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_include_organization_coverage_area_search_test.rb +52 -0
  132. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_include_organization_endpoint_search_test.rb +52 -0
  133. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_include_organization_partof_search_test.rb +52 -0
  134. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_lastupdated_search_test.rb +43 -0
  135. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_must_support_test.rb +58 -0
  136. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_name_search_test.rb +41 -0
  137. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_no_params_search_test.rb +49 -0
  138. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_partof_search_test.rb +41 -0
  139. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_read_test.rb +26 -0
  140. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_reference_resolution_test.rb +43 -0
  141. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_reverse_chain_practitioner_role_network_location_search_test.rb +62 -0
  142. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_revinclude_practitioner_role_network_search_test.rb +60 -0
  143. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_type_search_test.rb +42 -0
  144. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network/network_validation_test.rb +40 -0
  145. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/network_group.rb +238 -0
  146. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/metadata.yml +1296 -0
  147. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_endpoint_search_test.rb +41 -0
  148. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_endpoint_organization_search_test.rb +55 -0
  149. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_address_city_search_test.rb +55 -0
  150. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_address_postalcode_search_test.rb +55 -0
  151. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_address_search_test.rb +55 -0
  152. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_address_state_search_test.rb +55 -0
  153. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_organization_search_test.rb +55 -0
  154. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_location_type_search_test.rb +55 -0
  155. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_network_name_search_test.rb +55 -0
  156. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_network_partof_search_test.rb +55 -0
  157. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_participating_organization_address_search_test.rb +55 -0
  158. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_participating_organization_name_search_test.rb +55 -0
  159. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_participating_organization_partof_search_test.rb +55 -0
  160. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_participating_organization_type_search_test.rb +55 -0
  161. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_primary_organization_address_search_test.rb +55 -0
  162. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_primary_organization_name_search_test.rb +55 -0
  163. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_primary_organization_partof_search_test.rb +55 -0
  164. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_primary_organization_type_search_test.rb +55 -0
  165. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_service_location_search_test.rb +55 -0
  166. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_service_organization_search_test.rb +55 -0
  167. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_forward_chain_service_service_category_search_test.rb +55 -0
  168. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_id_search_test.rb +41 -0
  169. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_endpoint_search_test.rb +52 -0
  170. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_location_search_test.rb +52 -0
  171. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_network_search_test.rb +52 -0
  172. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_participating_organization_search_test.rb +52 -0
  173. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_primary_organization_search_test.rb +52 -0
  174. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_include_organization_affiliation_service_search_test.rb +52 -0
  175. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_lastupdated_search_test.rb +43 -0
  176. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_location_search_test.rb +41 -0
  177. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_must_support_test.rb +52 -0
  178. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_network_search_test.rb +41 -0
  179. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_no_params_search_test.rb +49 -0
  180. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_participating_organization_search_test.rb +41 -0
  181. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_primary_organization_search_test.rb +41 -0
  182. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_read_test.rb +26 -0
  183. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_reference_resolution_test.rb +47 -0
  184. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_role_search_test.rb +42 -0
  185. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_service_search_test.rb +41 -0
  186. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_specialty_search_test.rb +42 -0
  187. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil/org_affil_validation_test.rb +40 -0
  188. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/org_affil_group.rb +241 -0
  189. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/metadata.yml +384 -0
  190. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_address_search_test.rb +41 -0
  191. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_coverage_area_search_test.rb +43 -0
  192. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_endpoint_search_test.rb +41 -0
  193. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_forward_chain_endpoint_organization_search_test.rb +55 -0
  194. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_forward_chain_partof_address_search_test.rb +55 -0
  195. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_forward_chain_partof_name_search_test.rb +55 -0
  196. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_forward_chain_partof_type_search_test.rb +55 -0
  197. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_id_search_test.rb +41 -0
  198. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_include_organization_coverage_area_search_test.rb +52 -0
  199. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_include_organization_endpoint_search_test.rb +52 -0
  200. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_include_organization_partof_search_test.rb +52 -0
  201. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_lastupdated_search_test.rb +43 -0
  202. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_must_support_test.rb +68 -0
  203. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_name_search_test.rb +41 -0
  204. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_no_params_search_test.rb +49 -0
  205. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_partof_search_test.rb +41 -0
  206. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_read_test.rb +26 -0
  207. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_reference_resolution_test.rb +43 -0
  208. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_reverse_chain_insurance_plan_owned_by_coverage_area_search_test.rb +62 -0
  209. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_reverse_chain_org_affil_participating_organization_location_search_test.rb +62 -0
  210. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_reverse_chain_org_affil_participating_organization_network_search_test.rb +62 -0
  211. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_reverse_chain_org_affil_participating_organization_specialty_search_test.rb +62 -0
  212. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_endpoint_organization_search_test.rb +60 -0
  213. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_healthcare_service_organization_search_test.rb +60 -0
  214. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_insurance_plan_administered_by_search_test.rb +60 -0
  215. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_insurance_plan_owned_by_search_test.rb +60 -0
  216. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_organization_affiliation_participating_organization_search_test.rb +60 -0
  217. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_organization_affiliation_primary_organization_search_test.rb +60 -0
  218. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_revinclude_practitioner_role_organization_search_test.rb +60 -0
  219. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_type_search_test.rb +42 -0
  220. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization/organization_validation_test.rb +40 -0
  221. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/organization_group.rb +265 -0
  222. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/metadata.yml +253 -0
  223. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_family_search_test.rb +41 -0
  224. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_given_search_test.rb +41 -0
  225. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_id_search_test.rb +41 -0
  226. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_lastupdated_search_test.rb +43 -0
  227. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_must_support_test.rb +57 -0
  228. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_name_search_test.rb +41 -0
  229. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_no_params_search_test.rb +49 -0
  230. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_read_test.rb +26 -0
  231. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_reference_resolution_test.rb +42 -0
  232. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_reverse_chain_practitioner_role_practitioner_location_search_test.rb +62 -0
  233. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_reverse_chain_practitioner_role_practitioner_network_search_test.rb +62 -0
  234. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_reverse_chain_practitioner_role_practitioner_role_search_test.rb +62 -0
  235. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_reverse_chain_practitioner_role_practitioner_specialty_search_test.rb +62 -0
  236. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_revinclude_practitioner_role_practitioner_search_test.rb +60 -0
  237. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner/practitioner_validation_test.rb +40 -0
  238. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_group.rb +188 -0
  239. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/metadata.yml +1198 -0
  240. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_combination_list_practitioners_with_specialty_and_location_search_test.rb +50 -0
  241. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_endpoint_search_test.rb +41 -0
  242. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_endpoint_organization_search_test.rb +55 -0
  243. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_address_city_search_test.rb +55 -0
  244. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_address_postalcode_search_test.rb +55 -0
  245. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_address_search_test.rb +55 -0
  246. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_address_state_search_test.rb +55 -0
  247. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_organization_search_test.rb +55 -0
  248. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_location_type_search_test.rb +55 -0
  249. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_network_address_search_test.rb +55 -0
  250. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_network_name_search_test.rb +55 -0
  251. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_network_partof_search_test.rb +55 -0
  252. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_network_type_search_test.rb +55 -0
  253. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_organization_address_search_test.rb +55 -0
  254. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_organization_name_search_test.rb +55 -0
  255. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_organization_partof_search_test.rb +55 -0
  256. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_organization_type_search_test.rb +55 -0
  257. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_practitioner_name_search_test.rb +55 -0
  258. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_service_location_search_test.rb +55 -0
  259. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_service_organization_search_test.rb +55 -0
  260. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_forward_chain_service_service_category_search_test.rb +55 -0
  261. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_id_search_test.rb +41 -0
  262. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_endpoint_search_test.rb +52 -0
  263. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_location_search_test.rb +52 -0
  264. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_network_search_test.rb +52 -0
  265. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_organization_search_test.rb +52 -0
  266. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_practitioner_search_test.rb +52 -0
  267. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_include_practitioner_role_service_search_test.rb +52 -0
  268. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_lastupdated_search_test.rb +43 -0
  269. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_location_search_test.rb +41 -0
  270. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_must_support_test.rb +70 -0
  271. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_network_search_test.rb +41 -0
  272. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_no_params_search_test.rb +49 -0
  273. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_organization_search_test.rb +41 -0
  274. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_practitioner_search_test.rb +41 -0
  275. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_read_test.rb +26 -0
  276. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_reference_resolution_test.rb +46 -0
  277. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_role_search_test.rb +42 -0
  278. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_service_search_test.rb +41 -0
  279. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_specialty_search_test.rb +42 -0
  280. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role/practitioner_role_validation_test.rb +40 -0
  281. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/practitioner_role_group.rb +241 -0
  282. data/lib/davinci_plan_net_test_kit/generated/v1.1.0/resource_list.rb +16 -0
  283. data/lib/davinci_plan_net_test_kit/generator/combination_search_test_generator.rb +215 -0
  284. data/lib/davinci_plan_net_test_kit/generator/forward_chain_test_generator.rb +198 -0
  285. data/lib/davinci_plan_net_test_kit/generator/group_generator.rb +377 -0
  286. data/lib/davinci_plan_net_test_kit/generator/group_metadata.rb +77 -0
  287. data/lib/davinci_plan_net_test_kit/generator/group_metadata_extractor.rb +268 -0
  288. data/lib/davinci_plan_net_test_kit/generator/ig_loader.rb +76 -0
  289. data/lib/davinci_plan_net_test_kit/generator/ig_metadata.rb +52 -0
  290. data/lib/davinci_plan_net_test_kit/generator/ig_metadata_extractor.rb +57 -0
  291. data/lib/davinci_plan_net_test_kit/generator/ig_resources.rb +64 -0
  292. data/lib/davinci_plan_net_test_kit/generator/include_search_test_generator.rb +205 -0
  293. data/lib/davinci_plan_net_test_kit/generator/must_support_metadata_extractor.rb +337 -0
  294. data/lib/davinci_plan_net_test_kit/generator/must_support_metadata_extractor_us_core_3.rb +25 -0
  295. data/lib/davinci_plan_net_test_kit/generator/must_support_test_generator.rb +116 -0
  296. data/lib/davinci_plan_net_test_kit/generator/naming.rb +34 -0
  297. data/lib/davinci_plan_net_test_kit/generator/read_test_generator.rb +86 -0
  298. data/lib/davinci_plan_net_test_kit/generator/reference_resolution_test_generator.rb +92 -0
  299. data/lib/davinci_plan_net_test_kit/generator/resource_list_generator.rb +42 -0
  300. data/lib/davinci_plan_net_test_kit/generator/reverse_chain_search_test_generator.rb +194 -0
  301. data/lib/davinci_plan_net_test_kit/generator/revinclude_search_test_generator.rb +204 -0
  302. data/lib/davinci_plan_net_test_kit/generator/search_definition_metadata_extractor.rb +193 -0
  303. data/lib/davinci_plan_net_test_kit/generator/search_metadata_extractor.rb +74 -0
  304. data/lib/davinci_plan_net_test_kit/generator/search_no_params_test_generator.rb +124 -0
  305. data/lib/davinci_plan_net_test_kit/generator/search_test_generator.rb +276 -0
  306. data/lib/davinci_plan_net_test_kit/generator/special_cases.rb +92 -0
  307. data/lib/davinci_plan_net_test_kit/generator/suite_generator.rb +93 -0
  308. data/lib/davinci_plan_net_test_kit/generator/terminology_binding_metadata_extractor.rb +120 -0
  309. data/lib/davinci_plan_net_test_kit/generator/validation_test_generator.rb +140 -0
  310. data/lib/davinci_plan_net_test_kit/generator/value_extractor.rb +117 -0
  311. data/lib/davinci_plan_net_test_kit/generator.rb +143 -0
  312. data/lib/davinci_plan_net_test_kit/igs/package/SearchParameter-Resource-id.json +1 -0
  313. data/lib/davinci_plan_net_test_kit/igs/package/SearchParameter-Resource-lastUpdated.json +1 -0
  314. data/lib/davinci_plan_net_test_kit/igs/package.tgz +0 -0
  315. data/lib/davinci_plan_net_test_kit/must_support_test.rb +211 -0
  316. data/lib/davinci_plan_net_test_kit/provenance_validator.rb +37 -0
  317. data/lib/davinci_plan_net_test_kit/read_test.rb +62 -0
  318. data/lib/davinci_plan_net_test_kit/reference_resolution_test.rb +179 -0
  319. data/lib/davinci_plan_net_test_kit/request_logger.rb +46 -0
  320. data/lib/davinci_plan_net_test_kit/search_test.rb +1252 -0
  321. data/lib/davinci_plan_net_test_kit/search_test_properties.rb +66 -0
  322. data/lib/davinci_plan_net_test_kit/validation_test.rb +56 -0
  323. data/lib/davinci_plan_net_test_kit/version.rb +5 -0
  324. data/lib/davinci_plan_net_test_kit.rb +1 -0
  325. metadata +452 -0
@@ -0,0 +1,1252 @@
1
+ require_relative 'date_search_validation'
2
+ require_relative 'fhir_resource_navigation'
3
+ require_relative 'search_test_properties'
4
+ require_relative 'generator/special_cases'
5
+
6
+ module DaVinciPlanNetTestKit
7
+ module SearchTest
8
+ extend Forwardable
9
+ include DateSearchValidation
10
+ include FHIRResourceNavigation
11
+
12
+ def_delegators 'self.class', :metadata, :additional_metadata, :reverse_chain_field_name, :properties
13
+ def_delegators 'properties',
14
+ :resource_type,
15
+ :search_param_names,
16
+ :revinclude_param,
17
+ :rev_param_sp,
18
+ :include_param,
19
+ :inc_param_sp,
20
+ :chain_param,
21
+ :chain_param_base,
22
+ :additional_resource_type,
23
+ :additional_resource,
24
+ :reverse_chain_param,
25
+ :reverse_chain_target,
26
+ :input_name,
27
+ :saves_delayed_references?,
28
+ :first_search?,
29
+ :fixed_value_search?,
30
+ :possible_status_search?,
31
+ :test_post_search?,
32
+ :token_search_params,
33
+ :test_reference_variants?,
34
+ :params_with_comparators,
35
+ :multiple_or_search_params,
36
+ :combination_search?
37
+
38
+ def given_input?
39
+ !(self.send(input_name).nil? || self.send(input_name).empty?)
40
+ end
41
+
42
+ def input_based_skip_assert(resources, message)
43
+ if given_input?
44
+ skip_if resources.empty?, "#{message} Please try a different input"
45
+ else
46
+ assert !resources.empty?, message
47
+ end
48
+ end
49
+
50
+
51
+ def set_additional_resource(additional_resource)
52
+ scratch[:additional_resource_for_test] ||= {}
53
+ scratch[:additional_resource_for_test][:resource] = additional_resource
54
+ scratch[:additional_resource_for_test][:id] = search_param_value("_id", additional_resource)
55
+ scratch[:additional_resource_for_test][:"#{chain_param}"] = search_param_value(chain_param, additional_resource) if chain_param
56
+ scratch[:additional_resource_for_test][:"#{inc_param_sp}"] = search_param_value(inc_param_sp, additional_resource) if inc_param_sp
57
+ scratch[:additional_resource_for_test][:"#{rev_param_sp}"] = search_param_value(rev_param_sp, additional_resource) if rev_param_sp
58
+ scratch[:additional_resource_for_test][:"#{reverse_chain_param}"] = search_param_value(reverse_chain_param, additional_resource) if reverse_chain_param
59
+ end
60
+
61
+ def additional_resource(field = nil)
62
+ field = field&.to_sym if field.class != Symbol
63
+ case field
64
+ when nil
65
+ scratch[:additional_resource_for_test][:resource]
66
+ when :id
67
+ scratch[:additional_resource_for_test][:id]
68
+ when :"#{chain_param}"
69
+ scratch[:additional_resource_for_test][:"#{chain_param}"]
70
+ when :"#{inc_param_sp}"
71
+ scratch[:additional_resource_for_test][:"#{inc_param_sp}"]
72
+ when :"#{rev_param_sp}"
73
+ scratch[:additional_resource_for_test][:"#{rev_param_sp}"]
74
+ when :"#{reverse_chain_param}"
75
+ given_input? ? self.send(:"#{input_name}") : scratch[:additional_resource_for_test][:"#{reverse_chain_param}"]
76
+ end
77
+ end
78
+
79
+ def find_base_resource(desired_resource, search_param, resources)
80
+ # Access correct scratch based on what base you are looking for
81
+ is_include = desired_resource == resource_type
82
+ skip_if resources.nil?, no_instance_gathering_message
83
+ base_resource = resources
84
+ .select { |resource| resource.resourceType == desired_resource }
85
+ .reject { |resource| search_param_value(search_param, resource).nil? }
86
+ .first
87
+ skip_if base_resource.nil?, unable_to_find_base_message(desired_resource, search_param)
88
+ set_additional_resource(base_resource)
89
+ base_resource
90
+ end
91
+
92
+ def find_forward_chain_value
93
+ # Look through return from relevant include test
94
+ # If it is in additional_scratch_resources, it was put there from an _include/_revinclude test
95
+ chain_candidate = additional_scratch_resources
96
+ .find { |resource| !search_param_value(chain_param, resource).nil?}
97
+ skip_if chain_candidate.nil?, no_forward_chain_resource_found_message
98
+ chain_field_value = search_param_value(chain_param, chain_candidate)
99
+ set_additional_resource(chain_candidate)
100
+ chain_field_value
101
+ end
102
+
103
+ def find_reverse_chain_resource
104
+ chain_candidate = additional_scratch_resources
105
+ .reject { |resource| search_param_value(reverse_chain_target, resource).nil?}
106
+ .find { |resource| !search_param_value(reverse_chain_param, resource).nil?}
107
+ skip_if chain_candidate.nil?, no_reverse_chain_resource_found_message
108
+ chain_field_value = search_param_value(reverse_chain_param, chain_candidate)
109
+ set_additional_resource(chain_candidate)
110
+ chain_field_value
111
+ end
112
+
113
+ def all_search_params
114
+ @all_search_params ||=
115
+ resource_id_list.each_with_object({}) do |resource_id, params|
116
+ params[resource_id] ||= []
117
+ new_params =
118
+ if fixed_value_search?
119
+ fixed_value_search_param_values.map { |value| fixed_value_search_params(value, resource_id) }
120
+ else
121
+ [search_params_with_values(search_param_names, resource_id)]
122
+ end
123
+ new_params.reject! do |params|
124
+ params.any? { |_key, value| value.blank? }
125
+ end
126
+ params[resource_id].concat(new_params)
127
+ end
128
+ end
129
+
130
+ def all_revinclude_search_params
131
+ @all_revinclude_search_params ||=
132
+ all_search_params.transform_values! do |params_list|
133
+ find_base_resource(additional_resource_type, rev_param_sp, additional_scratch_resources) if !given_input?
134
+ base_id = given_input? ? self.send(input_name) : additional_resource(rev_param_sp)
135
+ params_list.map { |params| {_id: base_id}.merge(_revinclude: revinclude_param) }
136
+ end
137
+ end
138
+
139
+ def all_include_search_params
140
+ @all_include_search_params ||=
141
+ all_search_params.transform_values! do |params_list|
142
+ # No input needed for includes so can just pass into the map
143
+ find_base_resource(resource_type, inc_param_sp, all_scratch_resources)
144
+ params_list.map { |params| {_id: additional_resource(:id)}.merge(_include: include_param) }
145
+ end
146
+ end
147
+
148
+ def all_reverse_chain_search_params
149
+ @all_revchain_search_params ||=
150
+ all_search_params.transform_values! do |params_list|
151
+ field_value = given_input? ? self.send(input_name) : find_reverse_chain_resource
152
+ params_list.map { |params| {"_has:#{additional_resource_type}:#{reverse_chain_target}:#{reverse_chain_param}": field_value}}
153
+ end
154
+ end
155
+
156
+ def all_forward_chain_search_params
157
+ @all_forward_chain_search_params ||=
158
+ all_search_params.transform_values! do |params_list|
159
+ params_list.map { |params| {"#{chain_param_base}.#{chain_param}": find_forward_chain_value} }
160
+ end
161
+ end
162
+
163
+ def all_combination_search_params
164
+ @all_combination_search_params ||=
165
+ #First get resource pool that can be used for populating base resources
166
+ resource_pool = resources_with_all_search_params_with_values(search_param_names)
167
+ #Then find a reference to one from this pool
168
+
169
+ if inc_param_sp
170
+ find_base_resource(resource_type, inc_param_sp, resource_pool)
171
+ params_list = base_combination_search_params(additional_resource).dup
172
+ params_list = include_param ? params_list.merge(_include: include_param) : params_list
173
+ end
174
+ # After all references have been confirmed, populate it with elements of the resource that meets all requirements
175
+ # Revinclude
176
+ # Forward Chain
177
+ if reverse_chain_param
178
+ params_list = base_combination_search_params(resource_pool.first).dup
179
+ field_value = given_input? ? self.send(input_name) : find_reverse_chain_resource
180
+ params_list.merge!("_has:#{additional_resource_type}:#{reverse_chain_target}:#{reverse_chain_param}": field_value)
181
+ end
182
+ #TODO: Fill with the rest of advanced searches once more combination tests are ready
183
+ params_list
184
+ end
185
+
186
+ def base_combination_search_params(resource = nil)
187
+ @base_combination_search_params ||=
188
+ search_param_values_from_same_resource(search_param_names, resource)
189
+ end
190
+
191
+
192
+ def any_valid_search_params?(search_params)
193
+ search_params.any? { |_resource_id, params| params.present? }
194
+ end
195
+
196
+ def run_include_search_test
197
+ skip_if !any_valid_search_params?(all_include_search_params), "Invalid Params"
198
+ resources =
199
+ all_include_search_params.flat_map do |_resource_id, params_list|
200
+ params_list.flat_map do |params|
201
+ fhir_search resource_type, params: params
202
+ perform_search_with_status(params, resource_id) if response[:status] == 400 && possible_status_search?
203
+
204
+ check_search_response
205
+
206
+ returned_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
207
+
208
+ base_resources = returned_resources
209
+ .select { |res| res.resourceType == resource_type }
210
+
211
+ matching_resources = returned_resources
212
+ .select { |res| res.resourceType == additional_resource_type }
213
+
214
+ matching_resources.reject! { |res| res.id == params[:_id]} if additional_resource_type == resource_type
215
+
216
+ expected_reference = additional_resource(inc_param_sp)
217
+ matching_resources.each { |res|
218
+ check_resource_against_params(res, {_id: expected_reference})
219
+ }
220
+ matching_resources
221
+ end
222
+ end
223
+
224
+ save_delayed_references(resources, additional_resource_type)
225
+ additional_scratch_resources.concat(resources).uniq!
226
+
227
+ assert !resources.empty?, no_resources_skip_message(additional_resource_type)
228
+
229
+ end
230
+
231
+ def run_revinclude_search_test
232
+ skip_if !any_valid_search_params?(all_revinclude_search_params), "Invalid parameter. Please provide a different id for revinclude testing"
233
+ resources =
234
+ all_revinclude_search_params.flat_map do |_resource_id, params_list|
235
+ params_list.flat_map do |params|
236
+ fhir_search resource_type, params: params
237
+ perform_search_with_status(params, resource_id) if response[:status] == 400 && possible_status_search?
238
+
239
+ check_search_response
240
+
241
+ matching_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
242
+ .select { |res| res.resourceType == additional_resource_type }
243
+ .reject { |res| res.id == params[:_id] }
244
+
245
+ matching_resources.each { |res| check_resource_against_params(res, {"#{rev_param_sp}": "#{params[:_id]}"}) }
246
+ matching_resources
247
+ end
248
+ end
249
+
250
+ save_delayed_references(resources, additional_resource_type)
251
+ additional_scratch_resources.concat(resources).uniq!
252
+
253
+ input_based_skip_assert(resources, no_resources_skip_message(resource_type))
254
+ end
255
+
256
+ def run_search_test
257
+ # TODO: skip if not supported?
258
+ skip_if !any_valid_search_params?(all_search_params), unable_to_resolve_params_message
259
+ resources_returned =
260
+ all_search_params.flat_map do |resource_id, params_list|
261
+ params_list.flat_map { |params| perform_search(params, resource_id) }
262
+ end
263
+
264
+ assert !resources_returned.empty?, no_resources_skip_message
265
+
266
+ perform_multiple_or_search_test if multiple_or_search_params.present?
267
+ end
268
+
269
+ def run_search_no_params_test(profile_instance_id_string)
270
+
271
+ # read ids provided by user input
272
+ if profile_instance_id_string
273
+ input_instance_id_list = profile_instance_id_string.split(',').map(&:strip)
274
+
275
+ input_instance_id_list.each do |id|
276
+ fhir_read resource_type, id
277
+ assert_response_status(200)
278
+ assert_resource_type(resource_type)
279
+ all_scratch_resources << resource
280
+ end
281
+ end
282
+
283
+ # perform parameterless search for the profile's resourceType
284
+ if no_param_search == 'true'
285
+ fhir_search resource_type
286
+
287
+ check_search_response
288
+
289
+ resources_returned = fetch_matching_bundled_resources(max_pages: max_pages.to_i, max_instances: max_instances.to_i)
290
+
291
+ if first_search? && !resources_returned.empty?
292
+ all_scratch_resources.concat(resources_returned).uniq!
293
+ end
294
+ end
295
+
296
+ info "Found #{all_scratch_resources.size} instances to use for testing profile #{metadata.profile_name}."
297
+
298
+ assert !all_scratch_resources.empty?, "No instances found for testing profile #{metadata.profile_name}."
299
+
300
+ end
301
+
302
+ def run_search_on_additional_resource_type(param)
303
+ additional_resource_params = {"#{param}": additional_resource(param.to_sym)}
304
+ skip_if !any_valid_search_params?(additional_resource_params), "Invalid Params"
305
+
306
+ fhir_search additional_resource_type, params: additional_resource_params
307
+
308
+ check_search_response
309
+ additional_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
310
+ .select { |res| res.resourceType == additional_resource_type }
311
+
312
+ additional_resources.each { |res| check_resource_against_params(res, additional_resource_params) }
313
+
314
+ save_delayed_references(additional_resources, additional_resource_type)
315
+ additional_scratch_resources.concat(additional_resources).uniq!
316
+
317
+ assert !additional_resources.empty?, "Search on #{additional_resource_type}'s #{param} failed to retrieve any resources."
318
+ additional_resources
319
+ end
320
+
321
+
322
+ def run_forward_chain_search_test
323
+ resources =
324
+ all_forward_chain_search_params.flat_map do |_resource_id, params_list|
325
+ params_list.flat_map do |params|
326
+ fhir_search resource_type, params: params
327
+ perform_search_with_status(params, resource_id) if response[:status] == 400 && possible_status_search?
328
+
329
+ check_search_response
330
+
331
+ returned_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
332
+ assert !returned_resources.empty?, "No #{resource_type} resources returned"
333
+ base_resources = returned_resources
334
+ .select { |res| res.resourceType == resource_type }
335
+
336
+ contextual_resources = run_search_on_additional_resource_type(chain_param)
337
+ # Check that all references within the Base point to one of the resources in scratch currently.
338
+ base_resources.each do |base_res|
339
+ reference_value = search_param_value(chain_param_base, base_res)
340
+ assert (contextual_resources.any? do |res|
341
+ is_reference_match?(reference_value, search_param_value("_id", res))
342
+ end), forward_chaining_incorrect_reference_error_message(base_res)
343
+ end
344
+ base_resources
345
+ end
346
+ end
347
+ assert !resources.empty?, no_resources_skip_message
348
+ end
349
+
350
+ def run_reverse_chain_search_test
351
+ resources =
352
+ all_reverse_chain_search_params.flat_map do |_resource_id, params_list|
353
+ params_list.flat_map do |params|
354
+ fhir_search resource_type, params: params
355
+ perform_search_with_status(params, resource_id) if response[:status] == 400 && possible_status_search?
356
+
357
+ check_search_response
358
+
359
+ returned_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
360
+ input_based_skip_assert(returned_resources, "No resources found.")
361
+ base_resources = returned_resources
362
+ .select { |res| res.resourceType == resource_type }
363
+
364
+ contextual_resources = run_search_on_additional_resource_type(reverse_chain_param)
365
+ base_resources.each do |base_res|
366
+ assert (contextual_resources.any? do |res|
367
+ reference_value = search_param_value(reverse_chain_target, res)
368
+ reference_value.nil? ? false : is_reference_match?(reference_value, search_param_value("_id", base_res))
369
+ end), reverse_chaining_incorrect_reference_error_message(base_res)
370
+ end
371
+ base_resources
372
+ end
373
+ end
374
+ input_based_skip_assert(resources, "No resources found.")
375
+ end
376
+
377
+ def run_combination_search_test
378
+ fhir_search resource_type, params: all_combination_search_params
379
+ perform_search_with_status(all_combination_search_params, resource_id) if response[:status] == 400 && possible_status_search?
380
+
381
+ check_search_response
382
+
383
+ returned_resources = fetch_all_bundled_resources(additional_resource_types: [additional_resource_type])
384
+ assert !returned_resources.empty?, "No #{resource_type} resources found"
385
+
386
+ base_resources = returned_resources
387
+ .select { |res| res.resourceType == resource_type }
388
+ base_resources.each { |res| check_resource_against_params(res, base_combination_search_params)}
389
+
390
+ if inc_param_sp
391
+ matching_resources = returned_resources
392
+ .select { |res| res.resourceType == additional_resource_type }
393
+ assert !matching_resources.empty?, "Server did not return any #{additional_resource_type} resources, but query was based on existing element"
394
+
395
+ assert matching_resources.all? { |match_res|
396
+ base_resources.any? { |base_res|
397
+ if search_param_value(inc_param_sp, base_res).nil?
398
+ false
399
+ else
400
+ resource_fields_conform_to_params?(base_res, {"#{inc_param_sp}": search_param_value("_id", match_res)})
401
+ end
402
+ }
403
+ }, "Server returned a #{additional_resource_type} resource that was not referenced by any matching #{resource_type} instances"
404
+ end
405
+
406
+ if reverse_chain_param
407
+ input_based_skip_assert(returned_resources, "No resources found.")
408
+ contextual_resources = run_search_on_additional_resource_type(reverse_chain_param)
409
+ base_resources.each do |base_res|
410
+ assert (contextual_resources.any? do |res|
411
+ reference_value = search_param_value(reverse_chain_target, res)
412
+ reference_value.nil? ? false : is_reference_match?(reference_value, search_param_value("_id", base_res))
413
+ end), reverse_chaining_incorrect_reference_error_message(base_res)
414
+ end
415
+ end
416
+ end
417
+
418
+
419
+ def perform_search(params, resource_id)
420
+ fhir_search resource_type, params: params
421
+
422
+ perform_search_with_status(params, resource_id) if response[:status] == 400 && possible_status_search?
423
+
424
+ check_search_response
425
+
426
+ resources_returned =
427
+ fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
428
+
429
+ return [] if resources_returned.blank?
430
+
431
+ perform_comparator_searches(params, resource_id) if params_with_comparators.present?
432
+
433
+ if first_search?
434
+ all_scratch_resources.concat(resources_returned).uniq!
435
+ scratch_resources_for_resource(resource_id).concat(resources_returned).uniq!
436
+ end
437
+
438
+ resources_returned.each do |resource|
439
+ check_resource_against_params(resource, params)
440
+ end
441
+
442
+ save_delayed_references(resources_returned) if saves_delayed_references?
443
+
444
+ return resources_returned if all_search_variants_tested?
445
+
446
+ perform_post_search(resources_returned, params) if test_post_search?
447
+
448
+ perform_reference_with_type_search(params, resources_returned.count) if test_reference_variants?
449
+ perform_search_with_system(params, resource_id) if token_search_params.present?
450
+
451
+ resources_returned
452
+ end
453
+
454
+ def perform_post_search(get_search_resources, params)
455
+ fhir_search resource_type, params: params, search_method: :post
456
+
457
+ check_search_response
458
+
459
+ post_search_resources = fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
460
+
461
+ filter_conditions(post_search_resources) if resource_type == 'Condition' && metadata.version == 'v5.0.1'
462
+ filter_devices(post_search_resources) if resource_type == 'Device'
463
+
464
+ get_resource_count = get_search_resources.length
465
+ post_resource_count = post_search_resources.length
466
+
467
+ search_variant_test_records[:post_variant] = true
468
+
469
+ assert get_resource_count == post_resource_count,
470
+ "Expected search by POST to return the same results as search by GET, " \
471
+ "but GET search returned #{get_resource_count} resources, and POST search " \
472
+ "returned #{post_resource_count} resources."
473
+ end
474
+
475
+ def filter_devices(resources)
476
+ codes_to_include = implantable_device_codes&.split(',')&.map(&:strip)
477
+ return resources if codes_to_include.blank?
478
+
479
+ resources.select! do |resource|
480
+ resource&.type&.coding&.any? { |coding| codes_to_include.include?(coding.code) }
481
+ end
482
+ end
483
+
484
+ def filter_conditions(resources)
485
+ # In order to distinguish which resources matches the current profile, Inferno has to manually filter
486
+ # the result of first search.
487
+ resources.select! do |resource|
488
+ resource.category.any? do |category|
489
+ category.coding.any? do |coding|
490
+ metadata.search_definitions[:category][:values].include? coding.code
491
+ end
492
+ end
493
+ end
494
+ end
495
+
496
+ def search_and_check_response(params, resource_type = self.resource_type)
497
+ fhir_search resource_type, params: params
498
+
499
+ check_search_response
500
+ end
501
+
502
+ def check_search_response
503
+ assert_response_status(200)
504
+ assert_resource_type(:bundle)
505
+ # NOTE: how do we want to handle validating Bundles?
506
+ end
507
+
508
+ def search_variant_test_records
509
+ @search_variant_test_records ||= initial_search_variant_test_records
510
+ end
511
+
512
+ def initial_search_variant_test_records
513
+ {}.tap do |records|
514
+ records[:post_variant] = false if test_post_search?
515
+ records[:reference_variants] = false if test_reference_variants?
516
+ records[:token_variants] = false if token_search_params.present?
517
+ records[:comparator_searches] = Set.new if params_with_comparators.present?
518
+ end
519
+ end
520
+
521
+ def all_search_variants_tested?
522
+ search_variant_test_records.all? { |_variant, tested| tested.present? } &&
523
+ all_comparator_searches_tested?
524
+ end
525
+
526
+ def all_comparator_searches_tested?
527
+ return true if params_with_comparators.blank?
528
+
529
+ Set.new(params_with_comparators) == search_variant_test_records[:comparator_searches]
530
+ end
531
+
532
+ def date_comparator_value(comparator, date)
533
+ date = date.start || date.end if date.is_a? FHIR::Period
534
+ case comparator
535
+ when 'lt', 'le'
536
+ comparator + (DateTime.xmlschema(date) + 1).xmlschema
537
+ when 'gt', 'ge'
538
+ comparator + (DateTime.xmlschema(date) - 1).xmlschema
539
+ else
540
+ # ''
541
+ raise "Unsupported comparator '#{comparator}'"
542
+ end
543
+ end
544
+
545
+ def required_comparators(name)
546
+ metadata
547
+ .search_definitions
548
+ .dig(name.to_sym, :comparators)
549
+ .select { |_comparator, expectation| expectation == 'SHALL' }
550
+ .keys
551
+ .map(&:to_s)
552
+ end
553
+
554
+ def perform_comparator_searches(params, resource_id)
555
+ params_with_comparators.each do |name|
556
+ next if search_variant_test_records[:comparator_searches].include? name
557
+
558
+ required_comparators(name).each do |comparator|
559
+ paths = search_param_paths(name).first
560
+ date_element = find_a_value_at(scratch_resources_for_resource(resource_id), paths)
561
+ params_with_comparator = params.merge(name => date_comparator_value(comparator, date_element))
562
+
563
+ search_and_check_response(params_with_comparator)
564
+
565
+ fetch_all_bundled_resources.each do |resource|
566
+ check_resource_against_params(resource, params_with_comparator) if resource.resourceType == resource_type
567
+ end
568
+ end
569
+
570
+ search_variant_test_records[:comparator_searches] << name
571
+ end
572
+ end
573
+
574
+ def perform_reference_with_type_search(params, resource_count)
575
+ return if resource_count == 0
576
+ return if search_variant_test_records[:reference_variants]
577
+
578
+ new_search_params = params.merge(resource_type.underscore => "#{resource_type}/#{params['resource']}")
579
+ search_and_check_response(new_search_params)
580
+
581
+ reference_with_type_resources = fetch_all_bundled_resources.select { |resource| resource.resourceType == resource_type }
582
+
583
+
584
+ new_resource_count = reference_with_type_resources.count
585
+
586
+ assert new_resource_count == resource_count,
587
+ "Expected search by `#{params['resource']}` to to return the same results as searching " \
588
+ "by `#{new_search_params['resource']}`, but found #{resource_count} resources with " \
589
+ "`#{params['resource']}` and #{new_resource_count} with `#{new_search_params['resource']}`"
590
+
591
+ search_variant_test_records[:reference_variants] = true
592
+ end
593
+
594
+ def perform_search_with_system(params, resource_id)
595
+ return if search_variant_test_records[:token_variants]
596
+
597
+ new_search_params = search_params_with_values(token_search_params, resource_id, include_system: true)
598
+ return if new_search_params.any? { |_name, value| value.blank? }
599
+
600
+ search_params = params.merge(new_search_params)
601
+ search_and_check_response(search_params)
602
+
603
+ resources_returned =
604
+ fetch_all_bundled_resources
605
+ .select { |resource| resource.resourceType == resource_type }
606
+
607
+ assert resources_returned.present?, "No resources were returned when searching by `system|code`"
608
+
609
+ search_variant_test_records[:token_variants] = true
610
+ end
611
+
612
+ def perform_search_with_status(
613
+ original_params,
614
+ resource_id,
615
+ status_search_values: self.status_search_values,
616
+ resource_type: self.resource_type
617
+ )
618
+ assert resource.is_a?(FHIR::OperationOutcome), "Server returned a status of 400 without an OperationOutcome"
619
+ # TODO: warn about documenting status requirements
620
+ status_search_values.flat_map do |status_value|
621
+ search_params = original_params.merge("#{status_search_param_name}": status_value)
622
+
623
+ search_and_check_response(search_params)
624
+
625
+ entries = resource.entry.select { |entry| entry.resource.resourceType == resource_type }
626
+
627
+ if entries.present?
628
+ original_params.merge!("#{status_search_param_name}": status_value)
629
+ break
630
+ end
631
+ end
632
+ end
633
+
634
+ def status_search_param_name
635
+ @status_search_param_name ||=
636
+ metadata.search_definitions.keys.find { |key| key.to_s.include? 'status' }
637
+ end
638
+
639
+ def status_search_values
640
+ default_search_values(status_search_param_name)
641
+ end
642
+
643
+ def default_search_values(param_name)
644
+ definition = metadata.search_definitions[param_name]
645
+ return [] if definition.blank?
646
+
647
+ definition[:multiple_or] == 'SHALL' ? [definition[:values].join(',')] : Array.wrap(definition[:values])
648
+ end
649
+
650
+
651
+ def perform_multiple_or_search_test
652
+ resolved_one = false
653
+
654
+ all_search_params.each do |resource_id, params_list|
655
+ next unless params_list.present?
656
+
657
+ search_params = params_list.first
658
+ existing_values = {}
659
+ missing_values = {}
660
+
661
+ multiple_or_search_params.each do |param_name|
662
+ search_value = default_search_values(param_name.to_sym)
663
+ search_params = search_params.merge("#{param_name}" => search_value)
664
+ existing_values[param_name.to_sym] = scratch_resources_for_resource(resource_id).map(&param_name.to_sym).compact.uniq
665
+ end
666
+
667
+ # skip resources without multiple-or values
668
+ next if existing_values.values.any?(&:empty?)
669
+
670
+ resolved_one = true
671
+
672
+ search_and_check_response(search_params)
673
+
674
+ resources_returned =
675
+ fetch_all_bundled_resources
676
+ .select { |resource| resource.resourceType == resource_type }
677
+
678
+ multiple_or_search_params.each do |param_name|
679
+ missing_values[param_name.to_sym] = existing_values[param_name.to_sym] - resources_returned.map(&param_name.to_sym)
680
+ end
681
+
682
+ missing_value_message = missing_values
683
+ .reject { |_param_name, missing_value| missing_value.empty? }
684
+ .map { |param_name, missing_value| "#{missing_value.join(',')} values from #{param_name}" }
685
+ .join(' and ')
686
+
687
+ assert missing_value_message.blank?, "Could not find #{missing_value_message} in any of the resources returned for #{resource_type}/#{resource_id}"
688
+
689
+ break if resolved_one
690
+ end
691
+ end
692
+
693
+ def all_scratch_resources
694
+ scratch_resources[:all] ||= []
695
+ end
696
+
697
+ def additional_scratch_resources
698
+ scratch_additional_resources[:all] ||= []
699
+ end
700
+
701
+ def scratch_resources_for_resource(resource_id)
702
+ return all_scratch_resources if resource_id.nil?
703
+
704
+ scratch_resources[resource_id] ||= []
705
+ end
706
+
707
+ def references_to_save(resource_type = nil)
708
+ reference_metadata = resource_type == 'Provenance' ? additional_metadata : metadata
709
+ reference_metadata.delayed_references
710
+ end
711
+
712
+ def fixed_value_search_param_name
713
+ (search_param_names - ['resource']).first
714
+ end
715
+
716
+ def fixed_value_search_param_values
717
+ metadata.search_definitions[fixed_value_search_param_name.to_sym][:values]
718
+ end
719
+
720
+ def fixed_value_search_params(value, resource_id)
721
+ search_param_names.each_with_object({}) do |name, params|
722
+ resource_id_param?(name) ? params[name] = resource_id : params[name] = value
723
+ end
724
+ end
725
+
726
+ def search_params_with_values(search_param_names, resource_id, include_system: false)
727
+ resources = scratch_resources_for_resource(resource_id)
728
+ if resources.empty?
729
+ return search_param_names.each_with_object({}) do |name, params|
730
+ value = resource_id_param?(name) ? resource_id : nil
731
+ params[name] = value
732
+ end
733
+ end
734
+
735
+ params_with_partial_value = resources.each_with_object({}) do |resource, outer_params|
736
+ results_from_one_resource = search_param_names.each_with_object({}) do |name, params|
737
+ value = search_param_value(name, resource, include_system: include_system)
738
+ params[name] = value
739
+ end
740
+
741
+ outer_params.merge!(results_from_one_resource)
742
+
743
+ # stop if all parameter values are found
744
+ return outer_params if outer_params.all? { |_key, value| value.present? }
745
+ end
746
+
747
+ params_with_partial_value
748
+ end
749
+
750
+ def resources_with_all_search_params_with_values(search_param_names)
751
+ resources = all_scratch_resources
752
+
753
+ candidate_resources = resources.select do |resource|
754
+ search_param_names.all? { |param| !search_param_value(param, resource).nil?}
755
+ end
756
+ skip_if candidate_resources.empty?, "No resources populate all base search parameters."
757
+ candidate_resources
758
+ end
759
+
760
+ def search_param_values_from_same_resource(search_param_names, resource)
761
+ param_hash = search_param_names.each_with_object({}) do |name, params|
762
+ value = search_param_value(name, resource)
763
+ params[name] = value
764
+ end
765
+ param_hash
766
+ end
767
+
768
+ def resource_id_list
769
+ return [nil] unless respond_to? :resource_ids
770
+ resource_ids.split(',').map(&:strip)
771
+ end
772
+
773
+ def resource_search?
774
+ search_param_names.any? { |name| resource_id_param? name }
775
+ end
776
+
777
+ def resource_id_param?(name)
778
+ name == '_id'
779
+ end
780
+
781
+ def search_param_paths(name, resource = resource_type)
782
+ resource_metadata = resource == resource_type ? metadata : additional_metadata
783
+ paths = resource_metadata.search_definitions[name.to_sym][:paths]
784
+ if paths.first =='class'
785
+ paths[0] = 'local_class'
786
+ end
787
+
788
+ paths.map { |path| path.delete_prefix("Resource.") }
789
+ end
790
+
791
+ def all_search_params_present?(params)
792
+ params.all? { |_name, value| value.present? }
793
+ end
794
+
795
+ def array_of_codes(array)
796
+ array.map { |name| "`#{name}`" }.join(', ')
797
+ end
798
+
799
+ def unable_to_resolve_params_message
800
+ "Could not find values for all search params #{array_of_codes(search_param_names)}"
801
+ end
802
+
803
+ def unable_to_find_base_message(resource_type, param)
804
+ "Unable to find any #{resource_type} with the #{param} field populated from
805
+ previously gathered resources. Please return more resources or provide a base id."
806
+ end
807
+
808
+ def no_instance_gathering_message
809
+ "Unable to find previously gathered instances of #{additional_resource_type}, please provide ids or
810
+ \"Run All Tests\" from suite level"
811
+ end
812
+
813
+ def no_forward_chain_resource_found_message
814
+ "Unable to find any previously returned #{additional_resource_type} instances with the
815
+ #{chain_param} field populated."
816
+ end
817
+
818
+ def no_reverse_chain_resource_found_message
819
+ "Unable to find any previously returned #{additional_resource_type} instances with both
820
+ #{reverse_chain_param} and #{reverse_chain_target} fields populated. Please \"Run All Tests\"
821
+ from suite level or provide specific field values."
822
+ end
823
+
824
+ def forward_chain_conformance_error_message
825
+ "Unable to find any returned #{resource_type} instances that reference #{additional_resource_type} instances
826
+ where the #{chain_param} field is populated with the value used in the request."
827
+ end
828
+
829
+ def forward_chaining_incorrect_reference_error_message(violating_resource)
830
+ "#{resource_type} instance #{search_param_value("_id", violating_resource)} references
831
+ #{search_param_value(chain_param_base, violating_resource)} which does not have #{chain_param} value
832
+ #{additional_resource(chain_param)}"
833
+ end
834
+
835
+ def reverse_chaining_incorrect_reference_error_message(violating_resource)
836
+ "Found #{resource_type} instance #{search_param_value("_id", violating_resource)} that is not referenced by any
837
+ #{additional_resource_type} that have a #{reverse_chain_param} value of #{additional_resource(reverse_chain_param)}"
838
+ end
839
+
840
+ def empty_search_params_message(empty_search_params)
841
+ "Could not find values for the search parameters #{array_of_codes(empty_search_params.keys)}"
842
+ end
843
+
844
+ def no_resources_skip_message(resource_type = self.resource_type)
845
+ msg = "No #{resource_type} resources appear to be available"
846
+
847
+ if (!revinclude_param.nil? && include_param.nil?)
848
+ msg.concat(" Please choose a base resource that is referenced by a #{additional_resource_type}")
849
+ end
850
+
851
+ if (revinclude_param.nil? && !include_param.nil?)
852
+ msg.concat(" Please choose a base resource that is references a #{additional_resource_type}")
853
+ end
854
+
855
+ "#{msg}."
856
+ end
857
+
858
+ def fetch_all_bundled_resources(
859
+ reply_handler: nil,
860
+ max_pages: 0,
861
+ additional_resource_types: [],
862
+ resource_type: self.resource_type
863
+ )
864
+ page_count = 1
865
+ resources = []
866
+ bundle = resource
867
+ resources += bundle&.entry&.map { |entry| entry&.resource }
868
+
869
+ until bundle.nil? || (page_count == max_pages && max_pages != 0)
870
+
871
+ next_bundle_link = bundle&.link&.find { |link| link.relation == 'next' }&.url
872
+ reply_handler&.call(response)
873
+
874
+ break if next_bundle_link.blank?
875
+
876
+ reply = fhir_client.raw_read_url(next_bundle_link)
877
+
878
+ store_request('outgoing') { reply }
879
+ error_message = cant_resolve_next_bundle_message(next_bundle_link)
880
+
881
+ assert_response_status(200)
882
+ assert_valid_json(reply.body, error_message)
883
+
884
+ bundle = fhir_client.parse_reply(FHIR::Bundle, fhir_client.default_format, reply)
885
+ resources += bundle&.entry&.map { |entry| entry&.resource }
886
+
887
+ page_count += 1
888
+ end
889
+
890
+ valid_resource_types = [resource_type, 'OperationOutcome'].concat(additional_resource_types)
891
+
892
+ invalid_resource_types =
893
+ resources.reject { |entry| valid_resource_types.include? entry.resourceType }
894
+ .map(&:resourceType)
895
+ .uniq
896
+
897
+ if invalid_resource_types.any?
898
+ info "Received resource type(s) #{invalid_resource_types.join(', ')} in search bundle, " \
899
+ "but only expected resource types #{valid_resource_types.join(', ')}. " + \
900
+ "This is unusual but allowed if the server believes additional resource types are relevant."
901
+ end
902
+
903
+ resources
904
+ end
905
+
906
+ def fetch_matching_bundled_resources(
907
+ max_pages: 20,
908
+ max_instances: 200,
909
+ resource_type: self.resource_type
910
+ )
911
+ page_count = 0
912
+ resources = []
913
+ bundle = resource
914
+
915
+ loop do
916
+ bundle&.entry&.each do |a_entry|
917
+ an_instance = a_entry.resource
918
+ if ( an_instance &&
919
+ an_instance.resourceType == resource_type &&
920
+ # Plan Net Specific Special Case
921
+ !DaVinciPlanNetTestKit::SpecialCases::filter_instance_for_parameterless_gathering?(metadata.profile_url, an_instance)
922
+ )
923
+ resources << an_instance
924
+ break if resources.size >= max_instances
925
+ end
926
+ end
927
+ break if resources.size >= max_instances
928
+
929
+ page_count += 1
930
+ break if page_count >= max_pages
931
+
932
+ next_bundle_link = bundle&.link&.find { |link| link.relation == 'next' }&.url
933
+ break if next_bundle_link.blank?
934
+
935
+ reply = fhir_client.raw_read_url(next_bundle_link)
936
+
937
+ store_request('outgoing') { reply }
938
+ error_message = cant_resolve_next_bundle_message(next_bundle_link)
939
+
940
+ assert_response_status(200)
941
+ assert_valid_json(reply.body, error_message)
942
+
943
+ bundle = fhir_client.parse_reply(FHIR::Bundle, fhir_client.default_format, reply)
944
+ end
945
+
946
+ resources
947
+ end
948
+
949
+ def cant_resolve_next_bundle_message(link)
950
+ "Could not resolve next bundle: #{link}"
951
+ end
952
+
953
+ def search_param_value(name, resource, include_system: false)
954
+ paths = search_param_paths(name, resource.resourceType)
955
+ search_value = nil
956
+ paths.each do |path|
957
+ element = find_a_value_at(resource, path) { |element| element_has_valid_value?(element, include_system) }
958
+ search_value =
959
+ case element
960
+ when FHIR::Period
961
+ if element.start.present?
962
+ 'gt' + (DateTime.xmlschema(element.start) - 1).xmlschema
963
+ else
964
+ end_datetime = get_fhir_datetime_range(element.end)[:end]
965
+ 'lt' + (end_datetime + 1).xmlschema
966
+ end
967
+ when FHIR::Reference
968
+ element.reference
969
+ when FHIR::CodeableConcept
970
+ if include_system
971
+ coding =
972
+ find_a_value_at(element, 'coding') { |coding| coding.code.present? && coding.system.present? }
973
+ "#{coding.system}|#{coding.code}"
974
+ else
975
+ find_a_value_at(element, 'coding.code')
976
+ end
977
+ when FHIR::Identifier
978
+ include_system ? "#{element.system}|#{element.value}" : element.value
979
+ when FHIR::Coding
980
+ include_system ? "#{element.system}|#{element.code}" : element.code
981
+ when FHIR::HumanName
982
+ element.family || element.given&.first || element.text
983
+ when FHIR::Address
984
+ element.text || element.city || element.state || element.postalCode || element.country
985
+ when FHIR::Extension
986
+ element.valueReference.reference #Should this be more flexible? Does it need to read for any value[x]? PDEX Plan Net only
987
+ else
988
+ element
989
+ end
990
+
991
+ break if search_value.present?
992
+ end
993
+
994
+ escaped_value = search_value&.gsub(',', '\,')
995
+ escaped_value
996
+ end
997
+
998
+ def element_has_valid_value?(element, include_system)
999
+ case element
1000
+ when FHIR::Reference
1001
+ element.reference.present?
1002
+ when FHIR::CodeableConcept
1003
+ if include_system
1004
+ coding =
1005
+ find_a_value_at(element, 'coding') { |coding| coding.code.present? && coding.system.present? }
1006
+ coding.present?
1007
+ else
1008
+ find_a_value_at(element, 'coding.code').present?
1009
+ end
1010
+ when FHIR::Identifier
1011
+ include_system ? element.value.present? && element.system.present? : element.value.present?
1012
+ when FHIR::Coding
1013
+ include_system ? element.code.present? && element.system.present? : element.code.present?
1014
+ when FHIR::HumanName
1015
+ (element.family || element.given&.first || element.text).present?
1016
+ when FHIR::Address
1017
+ (element.text || element.city || element.state || element.postalCode || element.country).present?
1018
+ else
1019
+ true
1020
+ end
1021
+ end
1022
+
1023
+ def save_resource_reference(resource_type, reference)
1024
+ scratch[:references] ||= {}
1025
+ scratch[:references][resource_type] ||= Set.new
1026
+ scratch[:references][resource_type] << reference
1027
+ end
1028
+
1029
+ def save_delayed_references(resources, containing_resource_type = self.resource_type)
1030
+ resources.each do |resource|
1031
+ references_to_save(containing_resource_type).each do |reference_to_save|
1032
+ resolve_path(resource, reference_to_save[:path])
1033
+ .select { |reference| reference.is_a?(FHIR::Reference) && !reference.contained? }
1034
+ .each do |reference|
1035
+ resource_type = reference.resource_class.name.demodulize
1036
+ need_to_save = reference_to_save[:resources].include?(resource_type)
1037
+ next unless need_to_save
1038
+
1039
+ save_resource_reference(resource_type, reference)
1040
+ end
1041
+ end
1042
+ end
1043
+ end
1044
+
1045
+ #### RESULT CHECKING ####
1046
+ def resource_fields_conform_to_params?(resource, params)
1047
+ params.all? do |name, escaped_search_value|
1048
+ #unescape search value
1049
+ search_value = escaped_search_value&.gsub('\\,', ',')
1050
+ paths = search_param_paths(name, resource.resourceType)
1051
+
1052
+ match_found = false
1053
+ values_found = []
1054
+ resource_metadata = resource.resourceType == resource_type ? metadata : additional_metadata
1055
+ paths.each do |path|
1056
+ type = resource_metadata.search_definitions[name.to_sym][:type]
1057
+ values_found =
1058
+ resolve_path(resource, path)
1059
+ .flat_map do |value|
1060
+ case value
1061
+ when FHIR::Reference
1062
+ value.reference
1063
+ when FHIR::Extension
1064
+ value.valueReference.reference
1065
+ else
1066
+ value
1067
+ end
1068
+ end
1069
+
1070
+ match_found =
1071
+ case type
1072
+ when 'Period', 'date', 'instant', 'dateTime'
1073
+ values_found.any? { |date| validate_date_search(search_value, date) }
1074
+ when 'HumanName'
1075
+ # When a string search parameter refers to the types HumanName and Address,
1076
+ # the search covers the elements of type string, and does not cover elements such as use and period
1077
+ # https://www.hl7.org/fhir/search.html#string
1078
+ search_value_downcase = search_value.downcase
1079
+ values_found.any? do |name|
1080
+ name&.text&.downcase&.start_with?(search_value_downcase) ||
1081
+ name&.family&.downcase&.start_with?(search_value_downcase) ||
1082
+ name&.given&.any? { |given| given.downcase.start_with?(search_value_downcase) } ||
1083
+ name&.prefix&.any? { |prefix| prefix.downcase.start_with?(search_value_downcase) } ||
1084
+ name&.suffix&.any? { |suffix| suffix.downcase.start_with?(search_value_downcase) }
1085
+ end
1086
+ when 'Address'
1087
+ search_value_downcase = search_value.downcase
1088
+ values_found.any? do |address|
1089
+ address&.text&.downcase&.start_with?(search_value_downcase) ||
1090
+ address&.city&.downcase&.start_with?(search_value_downcase) ||
1091
+ address&.state&.downcase&.start_with?(search_value_downcase) ||
1092
+ address&.postalCode&.downcase&.start_with?(search_value_downcase) ||
1093
+ address&.country&.downcase&.start_with?(search_value_downcase)
1094
+ end
1095
+ when 'CodeableConcept'
1096
+ # FHIR token search (https://www.hl7.org/fhir/search.html#token): "When in doubt, servers SHOULD
1097
+ # treat tokens in a case-insensitive manner, on the grounds that including undesired data has
1098
+ # less safety implications than excluding desired behavior".
1099
+ codings = values_found.flat_map(&:coding)
1100
+ if search_value.include? '|'
1101
+ system = search_value.split('|').first
1102
+ code = search_value.split('|').last
1103
+ codings&.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
1104
+ else
1105
+ codings&.any? { |coding| coding.code&.casecmp?(search_value) }
1106
+ end
1107
+ when 'Coding'
1108
+ if search_value.include? '|'
1109
+ system = search_value.split('|').first
1110
+ code = search_value.split('|').last
1111
+ values_found.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
1112
+ else
1113
+ values_found.any? { |coding| coding.code&.casecmp?(search_value) }
1114
+ end
1115
+ when 'Identifier'
1116
+ if search_value.include? '|'
1117
+ values_found.any? { |identifier| "#{identifier.system}|#{identifier.value}" == search_value }
1118
+ else
1119
+ values_found.any? { |identifier| identifier.value == search_value }
1120
+ end
1121
+ when 'string'
1122
+ searched_values = search_value.downcase.split(/(?<!\\\\),/).map{ |string| string.gsub('\\,', ',') }
1123
+ values_found.any? do |value_found|
1124
+ searched_values.any? { |searched_value| value_found.downcase.starts_with? searched_value || is_reference_match?(searched_value, value_found) }
1125
+ end
1126
+ else
1127
+ search_values = search_value.split(/(?<!\\\\),/).map { |string| string.gsub('\\,', ',') }
1128
+ values_found.any? do |value_found|
1129
+ search_values.any? { |search_val| value_found == search_values || is_reference_match?(search_val, value_found) }
1130
+ end
1131
+ end
1132
+
1133
+ break if match_found
1134
+ end
1135
+ match_found
1136
+ end
1137
+ end
1138
+
1139
+ def check_resource_against_params(resource, params)
1140
+ params.each do |name, escaped_search_value|
1141
+ #unescape search value
1142
+ search_value = escaped_search_value&.gsub('\\,', ',')
1143
+ paths = search_param_paths(name, resource.resourceType)
1144
+
1145
+ match_found = false
1146
+ values_found = []
1147
+ resource_metadata = resource.resourceType == resource_type ? metadata : additional_metadata
1148
+ paths.each do |path|
1149
+ type = resource_metadata.search_definitions[name.to_sym][:type]
1150
+ values_found =
1151
+ resolve_path(resource, path)
1152
+ .flat_map do |value|
1153
+ case value
1154
+ when FHIR::Reference
1155
+ value.reference
1156
+ when FHIR::Extension
1157
+ value.valueReference.reference
1158
+ else
1159
+ value
1160
+ end
1161
+ end
1162
+
1163
+ match_found =
1164
+ case type
1165
+ when 'Period', 'date', 'instant', 'dateTime'
1166
+ values_found.any? { |date| validate_date_search(search_value, date) }
1167
+ when 'HumanName'
1168
+ # When a string search parameter refers to the types HumanName and Address,
1169
+ # the search covers the elements of type string, and does not cover elements such as use and period
1170
+ # https://www.hl7.org/fhir/search.html#string
1171
+ search_value_downcase = search_value.downcase
1172
+ values_found.any? do |name|
1173
+ name&.text&.downcase&.start_with?(search_value_downcase) ||
1174
+ name&.family&.downcase&.start_with?(search_value_downcase) ||
1175
+ name&.given&.any? { |given| given.downcase.start_with?(search_value_downcase) } ||
1176
+ name&.prefix&.any? { |prefix| prefix.downcase.start_with?(search_value_downcase) } ||
1177
+ name&.suffix&.any? { |suffix| suffix.downcase.start_with?(search_value_downcase) }
1178
+ end
1179
+ when 'Address'
1180
+ search_value_downcase = search_value.downcase
1181
+ values_found.any? do |address|
1182
+ address&.text&.downcase&.start_with?(search_value_downcase) ||
1183
+ address&.city&.downcase&.start_with?(search_value_downcase) ||
1184
+ address&.state&.downcase&.start_with?(search_value_downcase) ||
1185
+ address&.postalCode&.downcase&.start_with?(search_value_downcase) ||
1186
+ address&.country&.downcase&.start_with?(search_value_downcase)
1187
+ end
1188
+ when 'CodeableConcept'
1189
+ # FHIR token search (https://www.hl7.org/fhir/search.html#token): "When in doubt, servers SHOULD
1190
+ # treat tokens in a case-insensitive manner, on the grounds that including undesired data has
1191
+ # less safety implications than excluding desired behavior".
1192
+ codings = values_found.flat_map(&:coding)
1193
+ if search_value.include? '|'
1194
+ system = search_value.split('|').first
1195
+ code = search_value.split('|').last
1196
+ codings&.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
1197
+ else
1198
+ codings&.any? { |coding| coding.code&.casecmp?(search_value) }
1199
+ end
1200
+ when 'Coding'
1201
+ if search_value.include? '|'
1202
+ system = search_value.split('|').first
1203
+ code = search_value.split('|').last
1204
+ values_found.any? { |coding| coding.system == system && coding.code&.casecmp?(code) }
1205
+ else
1206
+ values_found.any? { |coding| coding.code&.casecmp?(search_value) }
1207
+ end
1208
+ when 'Identifier'
1209
+ if search_value.include? '|'
1210
+ values_found.any? { |identifier| "#{identifier.system}|#{identifier.value}" == search_value }
1211
+ else
1212
+ values_found.any? { |identifier| identifier.value == search_value }
1213
+ end
1214
+ when 'string'
1215
+ searched_values = search_value.downcase.split(/(?<!\\\\),/).map{ |string| string.gsub('\\,', ',') }
1216
+ values_found.any? do |value_found|
1217
+ searched_values.any? { |searched_value| value_found.downcase.starts_with? searched_value || is_reference_match?(searched_value, value_found) }
1218
+ end
1219
+ else
1220
+ search_values = search_value.split(/(?<!\\\\),/).map { |string| string.gsub('\\,', ',') }
1221
+ values_found.any? do |value_found|
1222
+ search_values.any? { |search_val| value_found == search_values || is_reference_match?(search_val, value_found) }
1223
+ end
1224
+
1225
+ end
1226
+
1227
+ break if match_found
1228
+ end
1229
+
1230
+ assert match_found,
1231
+ "#{resource_type}/#{resource.id} did not match the search parameters:\n" \
1232
+ "* Expected: #{search_value}\n" \
1233
+ "* Found: #{values_found.map(&:inspect).join(', ')}"
1234
+ end
1235
+ end
1236
+
1237
+
1238
+ def is_reference_match? (reference, local_reference)
1239
+ regex_pattern = /^(#{Regexp.escape(local_reference)}|\S+\/#{Regexp.escape(local_reference)}(?:[\/|]\S+)*)$/
1240
+ regex_pattern_local = /^(#{Regexp.escape(reference)}|\S+\/#{Regexp.escape(reference)}(?:[\/|]\S+)*)$/
1241
+ reference.match?(regex_pattern) || local_reference.match?(regex_pattern_local)
1242
+ end
1243
+
1244
+
1245
+ ### PARSING (Remove if methods exist elsewhere already)
1246
+ def param_to_method(param)
1247
+ param = param.split('-').collect(&:capitalize).join
1248
+ param = "healthcareService" if param == "Service"
1249
+ param[0].downcase + param[1..]
1250
+ end
1251
+ end
1252
+ end