davinci_plan_net_test_kit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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