us_core_test_kit 0.6.5 → 0.7.1

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/us_core_test_kit/custom_groups/base_smart_granular_scopes_group.rb +44 -12
  3. data/lib/us_core_test_kit/custom_groups/granted_granular_scopes_test.rb +61 -0
  4. data/lib/us_core_test_kit/custom_groups/screening_assessment_category_test.rb +75 -0
  5. data/lib/us_core_test_kit/custom_groups/smart_scopes_constants.rb +5 -8
  6. data/lib/us_core_test_kit/custom_groups/v6.1.0/screening_assessment_group.rb +45 -0
  7. data/lib/us_core_test_kit/custom_groups/v6.1.0/smart_granular_scopes_group.rb +94 -41
  8. data/lib/us_core_test_kit/custom_groups/v7.0.0-ballot/screening_assessment_group.rb +48 -0
  9. data/lib/us_core_test_kit/custom_groups/v7.0.0-ballot/smart_granular_scopes_group.rb +6 -0
  10. data/lib/us_core_test_kit/fhir_resource_navigation.rb +16 -1
  11. data/lib/us_core_test_kit/generated/v3.1.1/metadata.yml +3 -0
  12. data/lib/us_core_test_kit/generated/v3.1.1/patient/metadata.yml +3 -0
  13. data/lib/us_core_test_kit/generated/v3.1.1/us_core_test_suite.rb +5 -4
  14. data/lib/us_core_test_kit/generated/v4.0.0/metadata.yml +3 -0
  15. data/lib/us_core_test_kit/generated/v4.0.0/patient/metadata.yml +3 -0
  16. data/lib/us_core_test_kit/generated/v4.0.0/us_core_test_suite.rb +5 -4
  17. data/lib/us_core_test_kit/generated/v5.0.1/condition_encounter_diagnosis/metadata.yml +1 -0
  18. data/lib/us_core_test_kit/generated/v5.0.1/condition_problems_health_concerns/metadata.yml +1 -0
  19. data/lib/us_core_test_kit/generated/v5.0.1/metadata.yml +8 -0
  20. data/lib/us_core_test_kit/generated/v5.0.1/patient/metadata.yml +4 -0
  21. data/lib/us_core_test_kit/generated/v5.0.1/questionnaire_response/metadata.yml +2 -0
  22. data/lib/us_core_test_kit/generated/v5.0.1/us_core_test_suite.rb +5 -4
  23. data/lib/us_core_test_kit/generated/v6.1.0/condition_encounter_diagnosis/metadata.yml +23 -20
  24. data/lib/us_core_test_kit/generated/v6.1.0/condition_granular_scope1_group.rb +24 -20
  25. data/lib/us_core_test_kit/generated/v6.1.0/condition_problems_health_concerns/metadata.yml +1 -0
  26. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/condition_granular_scope_read_test.rb +32 -0
  27. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_abatement_date_granular_scope_test.rb → condition_patient_abatement_date_granular_scope_search_test.rb} +5 -5
  28. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_asserted_date_granular_scope_test.rb → condition_patient_asserted_date_granular_scope_search_test.rb} +5 -5
  29. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_category_clinical_status_granular_scope_test.rb → condition_patient_category_clinical_status_granular_scope_search_test.rb} +5 -5
  30. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_category_encounter_granular_scope_test.rb → condition_patient_category_encounter_granular_scope_search_test.rb} +5 -5
  31. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_category_granular_scope_test.rb → condition_patient_category_granular_scope_search_test.rb} +5 -5
  32. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_clinical_status_granular_scope_test.rb → condition_patient_clinical_status_granular_scope_search_test.rb} +5 -5
  33. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_code_granular_scope_test.rb → condition_patient_code_granular_scope_search_test.rb} +5 -5
  34. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_granular_scope_test.rb → condition_patient_granular_scope_search_test.rb} +5 -5
  35. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_onset_date_granular_scope_test.rb → condition_patient_onset_date_granular_scope_search_test.rb} +5 -5
  36. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/{condition_patient_recorded_date_granular_scope_test.rb → condition_patient_recorded_date_granular_scope_search_test.rb} +5 -5
  37. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/condition/metadata.yml +25 -22
  38. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/metadata.yml +14 -12
  39. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/observation_granular_scope_read_test.rb +32 -0
  40. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/{observation_patient_category_date_granular_scope_test.rb → observation_patient_category_date_granular_scope_search_test.rb} +5 -5
  41. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/{observation_patient_category_granular_scope_test.rb → observation_patient_category_granular_scope_search_test.rb} +5 -5
  42. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/{observation_patient_category_status_granular_scope_test.rb → observation_patient_category_status_granular_scope_search_test.rb} +5 -5
  43. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/{observation_patient_code_date_granular_scope_test.rb → observation_patient_code_date_granular_scope_search_test.rb} +5 -5
  44. data/lib/us_core_test_kit/generated/v6.1.0/granular_scope_tests/observation/{observation_patient_code_granular_scope_test.rb → observation_patient_code_granular_scope_search_test.rb} +5 -5
  45. data/lib/us_core_test_kit/generated/v6.1.0/granular_scopes1_group.rb +5 -1
  46. data/lib/us_core_test_kit/generated/v6.1.0/metadata.yml +43 -36
  47. data/lib/us_core_test_kit/generated/v6.1.0/observation_granular_scope1_group.rb +15 -11
  48. data/lib/us_core_test_kit/generated/v6.1.0/observation_lab/metadata.yml +12 -10
  49. data/lib/us_core_test_kit/generated/v6.1.0/patient/metadata.yml +5 -0
  50. data/lib/us_core_test_kit/generated/v6.1.0/questionnaire_response/metadata.yml +2 -0
  51. data/lib/us_core_test_kit/generated/v6.1.0/us_core_test_suite.rb +9 -6
  52. data/lib/us_core_test_kit/generated/v7.0.0-ballot/condition_encounter_diagnosis/metadata.yml +23 -20
  53. data/lib/us_core_test_kit/generated/v7.0.0-ballot/condition_granular_scope1_group.rb +22 -20
  54. data/lib/us_core_test_kit/generated/v7.0.0-ballot/condition_granular_scope2_group.rb +22 -20
  55. data/lib/us_core_test_kit/generated/v7.0.0-ballot/condition_problems_health_concerns/metadata.yml +1 -0
  56. data/lib/us_core_test_kit/generated/v7.0.0-ballot/diagnostic_report_granular_scope1_group.rb +14 -12
  57. data/lib/us_core_test_kit/generated/v7.0.0-ballot/diagnostic_report_granular_scope2_group.rb +14 -12
  58. data/lib/us_core_test_kit/generated/v7.0.0-ballot/diagnostic_report_note/metadata.yml +14 -12
  59. data/lib/us_core_test_kit/generated/v7.0.0-ballot/document_reference/metadata.yml +16 -14
  60. data/lib/us_core_test_kit/generated/v7.0.0-ballot/document_reference_granular_scope1_group.rb +16 -14
  61. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/condition_granular_scope_read_test.rb +32 -0
  62. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_abatement_date_granular_scope_test.rb → condition_patient_abatement_date_granular_scope_search_test.rb} +5 -5
  63. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_asserted_date_granular_scope_test.rb → condition_patient_asserted_date_granular_scope_search_test.rb} +5 -5
  64. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_category_clinical_status_granular_scope_test.rb → condition_patient_category_clinical_status_granular_scope_search_test.rb} +5 -5
  65. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_category_encounter_granular_scope_test.rb → condition_patient_category_encounter_granular_scope_search_test.rb} +5 -5
  66. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_category_granular_scope_test.rb → condition_patient_category_granular_scope_search_test.rb} +5 -5
  67. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_clinical_status_granular_scope_test.rb → condition_patient_clinical_status_granular_scope_search_test.rb} +5 -5
  68. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_code_granular_scope_test.rb → condition_patient_code_granular_scope_search_test.rb} +5 -5
  69. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_granular_scope_test.rb → condition_patient_granular_scope_search_test.rb} +5 -5
  70. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_onset_date_granular_scope_test.rb → condition_patient_onset_date_granular_scope_search_test.rb} +5 -5
  71. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/{condition_patient_recorded_date_granular_scope_test.rb → condition_patient_recorded_date_granular_scope_search_test.rb} +5 -5
  72. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/condition/metadata.yml +23 -20
  73. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/diagnostic_report_granular_scope_read_test.rb +32 -0
  74. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_category_date_granular_scope_test.rb → diagnostic_report_patient_category_date_granular_scope_search_test.rb} +5 -5
  75. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_category_granular_scope_test.rb → diagnostic_report_patient_category_granular_scope_search_test.rb} +5 -5
  76. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_code_date_granular_scope_test.rb → diagnostic_report_patient_code_date_granular_scope_search_test.rb} +5 -5
  77. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_code_granular_scope_test.rb → diagnostic_report_patient_code_granular_scope_search_test.rb} +5 -5
  78. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_granular_scope_test.rb → diagnostic_report_patient_granular_scope_search_test.rb} +5 -5
  79. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/{diagnostic_report_patient_status_granular_scope_test.rb → diagnostic_report_patient_status_granular_scope_search_test.rb} +5 -5
  80. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/diagnostic_report/metadata.yml +14 -12
  81. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/document_reference_granular_scope_read_test.rb +32 -0
  82. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_id_granular_scope_test.rb → document_reference_id_granular_scope_search_test.rb} +5 -5
  83. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_category_date_granular_scope_test.rb → document_reference_patient_category_date_granular_scope_search_test.rb} +5 -5
  84. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_category_granular_scope_test.rb → document_reference_patient_category_granular_scope_search_test.rb} +5 -5
  85. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_granular_scope_test.rb → document_reference_patient_granular_scope_search_test.rb} +5 -5
  86. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_status_granular_scope_test.rb → document_reference_patient_status_granular_scope_search_test.rb} +5 -5
  87. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_type_granular_scope_test.rb → document_reference_patient_type_granular_scope_search_test.rb} +5 -5
  88. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/{document_reference_patient_type_period_granular_scope_test.rb → document_reference_patient_type_period_granular_scope_search_test.rb} +5 -5
  89. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/document_reference/metadata.yml +16 -14
  90. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/metadata.yml +12 -10
  91. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/observation_granular_scope_read_test.rb +32 -0
  92. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/{observation_patient_category_date_granular_scope_test.rb → observation_patient_category_date_granular_scope_search_test.rb} +5 -5
  93. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/{observation_patient_category_granular_scope_test.rb → observation_patient_category_granular_scope_search_test.rb} +5 -5
  94. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/{observation_patient_category_status_granular_scope_test.rb → observation_patient_category_status_granular_scope_search_test.rb} +5 -5
  95. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/{observation_patient_code_date_granular_scope_test.rb → observation_patient_code_date_granular_scope_search_test.rb} +5 -5
  96. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/observation/{observation_patient_code_granular_scope_test.rb → observation_patient_code_granular_scope_search_test.rb} +5 -5
  97. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/metadata.yml +16 -14
  98. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/service_request_granular_scope_read_test.rb +32 -0
  99. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_id_granular_scope_test.rb → service_request_id_granular_scope_search_test.rb} +5 -5
  100. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_category_authored_granular_scope_test.rb → service_request_patient_category_authored_granular_scope_search_test.rb} +5 -5
  101. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_category_granular_scope_test.rb → service_request_patient_category_granular_scope_search_test.rb} +5 -5
  102. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_code_authored_granular_scope_test.rb → service_request_patient_code_authored_granular_scope_search_test.rb} +5 -5
  103. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_code_granular_scope_test.rb → service_request_patient_code_granular_scope_search_test.rb} +5 -5
  104. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_granular_scope_test.rb → service_request_patient_granular_scope_search_test.rb} +5 -5
  105. data/lib/us_core_test_kit/generated/v7.0.0-ballot/granular_scope_tests/service_request/{service_request_patient_status_granular_scope_test.rb → service_request_patient_status_granular_scope_search_test.rb} +5 -5
  106. data/lib/us_core_test_kit/generated/v7.0.0-ballot/medication_request/metadata.yml +1 -0
  107. data/lib/us_core_test_kit/generated/v7.0.0-ballot/metadata.yml +90 -70
  108. data/lib/us_core_test_kit/generated/v7.0.0-ballot/observation_granular_scope1_group.rb +12 -10
  109. data/lib/us_core_test_kit/generated/v7.0.0-ballot/observation_granular_scope2_group.rb +12 -10
  110. data/lib/us_core_test_kit/generated/v7.0.0-ballot/observation_lab/metadata.yml +12 -10
  111. data/lib/us_core_test_kit/generated/v7.0.0-ballot/patient/metadata.yml +5 -0
  112. data/lib/us_core_test_kit/generated/v7.0.0-ballot/questionnaire_response/metadata.yml +2 -0
  113. data/lib/us_core_test_kit/generated/v7.0.0-ballot/service_request/metadata.yml +16 -14
  114. data/lib/us_core_test_kit/generated/v7.0.0-ballot/service_request_granular_scope1_group.rb +16 -14
  115. data/lib/us_core_test_kit/generated/v7.0.0-ballot/service_request_granular_scope2_group.rb +16 -14
  116. data/lib/us_core_test_kit/generated/v7.0.0-ballot/us_core_test_suite.rb +8 -5
  117. data/lib/us_core_test_kit/generator/granular_scope_group_generator.rb +7 -0
  118. data/lib/us_core_test_kit/generator/granular_scope_read_test_generator.rb +102 -0
  119. data/lib/us_core_test_kit/generator/granular_scope_resource_type_group_generator.rb +1 -1
  120. data/lib/us_core_test_kit/generator/granular_scope_test_generator.rb +4 -4
  121. data/lib/us_core_test_kit/generator/group_metadata.rb +1 -1
  122. data/lib/us_core_test_kit/generator/must_support_metadata_extractor.rb +1 -0
  123. data/lib/us_core_test_kit/generator/must_support_metadata_extractor_us_core_4.rb +3 -0
  124. data/lib/us_core_test_kit/generator/must_support_metadata_extractor_us_core_5.rb +1 -0
  125. data/lib/us_core_test_kit/generator/special_cases.rb +3 -5
  126. data/lib/us_core_test_kit/generator/suite_generator.rb +14 -3
  127. data/lib/us_core_test_kit/generator.rb +2 -0
  128. data/lib/us_core_test_kit/granular_scope.rb +63 -0
  129. data/lib/us_core_test_kit/granular_scope_read_test.rb +71 -0
  130. data/lib/us_core_test_kit/{granular_scope_checker.rb → granular_scope_search_test.rb} +8 -47
  131. data/lib/us_core_test_kit/must_support_test.rb +27 -7
  132. data/lib/us_core_test_kit/primitive_type.rb +5 -0
  133. data/lib/us_core_test_kit/provenance_validator.rb +3 -4
  134. data/lib/us_core_test_kit/reference_resolution_test.rb +2 -1
  135. data/lib/us_core_test_kit/resource_search_param_checker.rb +139 -0
  136. data/lib/us_core_test_kit/search_test.rb +6 -0
  137. data/lib/us_core_test_kit/version.rb +1 -1
  138. metadata +72 -59
  139. data/lib/us_core_test_kit/generated/v6.1.0/condition_granular_scope2_group.rb +0 -43
  140. data/lib/us_core_test_kit/generated/v6.1.0/granular_scopes2_group.rb +0 -52
  141. data/lib/us_core_test_kit/generated/v6.1.0/observation_granular_scope2_group.rb +0 -32
@@ -5,6 +5,7 @@ require_relative '../../custom_groups/v4.0.0/clinical_notes_guidance_group'
5
5
  require_relative '../../custom_groups/data_absent_reason_group'
6
6
  require_relative '../../custom_groups/smart_app_launch_group'
7
7
  require_relative '../../custom_groups/v7.0.0-ballot/smart_granular_scopes_group'
8
+ require_relative '../../custom_groups/v7.0.0-ballot/screening_assessment_group'
8
9
  require_relative '../../provenance_validator'
9
10
  require_relative '../../us_core_options'
10
11
 
@@ -87,6 +88,7 @@ module USCoreTestKit
87
88
  /Provenance.agent\[\d*\]: Rule provenance-1/, #Invalid invariant in US Core v5.0.1
88
89
  %r{Unknown Code System 'http://hl7.org/fhir/us/core/CodeSystem/us-core-tags'}, # Validator has an issue with this US Core 5 code system in US Core 6 resource
89
90
  %r{URL value 'http://hl7.org/fhir/us/core/CodeSystem/us-core-tags' does not resolve}, # Validator has an issue with this US Core 5 code system in US Core 6 resource
91
+ /\A\S+: \S+: URL value '.*' does not resolve/,
90
92
  %r{Observation.component\[\d+\].value.ofType\(Quantity\): The code provided \(http://unitsofmeasure.org#L/min\) was not found in the value set 'Vital Signs Units'} # Known issue with the Pulse Oximetry Profile
91
93
  ].freeze
92
94
 
@@ -98,8 +100,10 @@ module USCoreTestKit
98
100
  end
99
101
  end
100
102
 
101
- validator do
102
- url ENV.fetch('V700_BALLOT_VALIDATOR_URL', 'http://validator_service:4567')
103
+ id :us_core_v700_ballot
104
+
105
+ fhir_resource_validator do
106
+ igs 'hl7.fhir.us.core#7.0.0-ballot'
103
107
  message_filters = VALIDATION_MESSAGE_FILTERS + VERSION_SPECIFIC_MESSAGE_FILTERS
104
108
 
105
109
  exclude_message do |message|
@@ -112,8 +116,6 @@ module USCoreTestKit
112
116
  end
113
117
  end
114
118
 
115
- id :us_core_v700_ballot
116
-
117
119
  input :url,
118
120
  title: 'FHIR Endpoint',
119
121
  description: 'URL of the FHIR endpoint'
@@ -206,10 +208,11 @@ module USCoreTestKit
206
208
  group from: :us_core_v700_ballot_related_person
207
209
  group from: :us_core_v700_ballot_specimen
208
210
  group from: :us_core_v400_clinical_notes_guidance
211
+ group from: :us_core_v700_ballot_screening_assessment
209
212
  group from: :us_core_311_data_absent_reason
210
213
  end
211
214
 
212
- group from: :us_core_v700_ballot_smart_granular_scopes,
215
+ group from: :'us_core_v700_ballot_smart_granular_scopes',
213
216
  required_suite_options: USCoreOptions::SMART_2_REQUIREMENT
214
217
 
215
218
  end
@@ -4,11 +4,18 @@ require_relative '../custom_groups/smart_scopes_constants'
4
4
  module USCoreTestKit
5
5
  class Generator
6
6
  class GranularScopeGroupGenerator
7
+ include SmartScopesConstants
8
+
7
9
  class << self
8
10
  def generate(ig_metadata, base_output_dir)
9
11
  return unless ['6', '7'].include? ig_metadata.ig_version[1]
10
12
 
11
13
  [1, 2].each do |group_number|
14
+ scopes =
15
+ SmartScopesConstants
16
+ .const_get("SMART_GRANULAR_SCOPES_GROUP#{group_number}")[ig_metadata.reformatted_version]
17
+ next if scopes.blank?
18
+
12
19
  new(ig_metadata, base_output_dir, group_number).generate
13
20
  end
14
21
  end
@@ -0,0 +1,102 @@
1
+ require_relative 'naming'
2
+ require_relative 'special_cases'
3
+ require_relative '../custom_groups/smart_scopes_constants'
4
+
5
+ module USCoreTestKit
6
+ class Generator
7
+ class GranularScopeReadTestGenerator
8
+ class << self
9
+ def generate(ig_metadata, base_output_dir)
10
+
11
+ return unless ['6', '7'].include? ig_metadata.ig_version[1]
12
+
13
+ scopes =
14
+ SmartScopesConstants::SMART_GRANULAR_SCOPES_GROUP1[ig_metadata.reformatted_version] +
15
+ (SmartScopesConstants::SMART_GRANULAR_SCOPES_GROUP2[ig_metadata.reformatted_version] || [])
16
+
17
+ SmartScopesConstants::SMART_GRANULAR_SCOPE_RESOURCES.each do |resource_type|
18
+ group = ig_metadata.groups.find { |group| group.resource == resource_type }
19
+
20
+ next if scopes.none? { |scope| scope.start_with? "patient/#{group.resource}" }
21
+
22
+ new(group, base_output_dir).generate
23
+ end
24
+ end
25
+ end
26
+
27
+ attr_accessor :group_metadata, :base_output_dir, :group_number
28
+
29
+ def initialize(group_metadata, base_output_dir)
30
+ self.group_metadata = group_metadata
31
+ self.base_output_dir = base_output_dir
32
+ end
33
+
34
+ def template
35
+ @template ||= File.read(File.join(__dir__, 'templates', 'granular_scope_read_test.rb.erb'))
36
+ end
37
+
38
+ def output
39
+ @output ||= ERB.new(template).result(binding)
40
+ end
41
+
42
+ def base_output_file_name
43
+ "#{class_name.underscore}.rb"
44
+ end
45
+
46
+ def output_file_directory
47
+ File.join(base_output_dir, 'granular_scope_tests', resource_type.underscore)
48
+ end
49
+
50
+ def output_file_name
51
+ File.join(output_file_directory, base_output_file_name)
52
+ end
53
+
54
+ def profile_identifier
55
+ Naming.snake_case_for_profile(group_metadata)
56
+ end
57
+
58
+ def test_id
59
+ "us_core_#{group_metadata.reformatted_version}_#{resource_type}_granular_scope_read_test"
60
+ end
61
+
62
+ def class_name
63
+ "#{resource_type}GranularScopeReadTest"
64
+ end
65
+
66
+ def module_name
67
+ "USCore#{group_metadata.reformatted_version.upcase}"
68
+ end
69
+
70
+ def resource_type
71
+ group_metadata.resource
72
+ end
73
+
74
+ def path_for_value(path)
75
+ path == 'class' ? 'local_class' : path
76
+ end
77
+
78
+ def array_of_strings(array)
79
+ quoted_strings = array.map { |element| "'#{element}'" }
80
+ "[#{quoted_strings.join(', ')}]"
81
+ end
82
+
83
+ def generate
84
+ FileUtils.mkdir_p(output_file_directory)
85
+ File.open(output_file_name, 'w') { |f| f.write(output) }
86
+
87
+ group_metadata.add_granular_scope_test(
88
+ id: test_id,
89
+ file_name: base_output_file_name
90
+ )
91
+ end
92
+
93
+ def description
94
+ <<~DESCRIPTION.gsub(/\n{3,}/, "\n\n")
95
+ This test attempts #{resource_type} reads
96
+ and verifies that the results have been
97
+ filtered based on the granted granular scopes.
98
+ DESCRIPTION
99
+ end
100
+ end
101
+ end
102
+ end
@@ -16,7 +16,7 @@ module USCoreTestKit
16
16
  .const_get("SMART_GRANULAR_SCOPES_GROUP#{group_number}")[ig_metadata.reformatted_version]
17
17
 
18
18
  groups.each do |group_metadata|
19
- next if scopes.none? { |scope| scope.start_with? "patient/#{group_metadata.resource}" }
19
+ next if scopes.blank? || scopes.none? { |scope| scope.start_with? "patient/#{group_metadata.resource}" }
20
20
 
21
21
  new(GroupMetadata.new(group_metadata.to_hash), ig_metadata, base_output_dir, group_number).generate
22
22
  end
@@ -11,12 +11,12 @@ module USCoreTestKit
11
11
 
12
12
  scopes =
13
13
  SmartScopesConstants::SMART_GRANULAR_SCOPES_GROUP1[ig_metadata.reformatted_version] +
14
- SmartScopesConstants::SMART_GRANULAR_SCOPES_GROUP2[ig_metadata.reformatted_version]
14
+ (SmartScopesConstants::SMART_GRANULAR_SCOPES_GROUP2[ig_metadata.reformatted_version] || [])
15
15
 
16
16
  SmartScopesConstants::SMART_GRANULAR_SCOPE_RESOURCES.each do |resource_type|
17
17
  group = ig_metadata.groups.find { |group| group.resource == resource_type }
18
18
 
19
- next if scopes.none? { |scope| scope.start_with? "patient/#{group.resource}" }
19
+ next if scopes.blank? || scopes.none? { |scope| scope.start_with? "patient/#{group.resource}" }
20
20
 
21
21
  group.searches
22
22
  .each { |search| new(group, search, base_output_dir).generate }
@@ -57,7 +57,7 @@ module USCoreTestKit
57
57
  end
58
58
 
59
59
  def test_id
60
- "us_core_#{group_metadata.reformatted_version}_#{resource_type}_#{search_identifier}_granular_scope_test"
60
+ "us_core_#{group_metadata.reformatted_version}_#{resource_type}_#{search_identifier}_granular_scope_search_test"
61
61
  end
62
62
 
63
63
  def search_identifier
@@ -69,7 +69,7 @@ module USCoreTestKit
69
69
  end
70
70
 
71
71
  def class_name
72
- "#{resource_type}#{search_title}GranularScopeTest"
72
+ "#{resource_type}#{search_title}GranularScopeSearchTest"
73
73
  end
74
74
 
75
75
  def module_name
@@ -56,7 +56,7 @@ module USCoreTestKit
56
56
  end
57
57
 
58
58
  def no_patient_searches?
59
- searches.none? { |search| search[:names].include? 'patient' }
59
+ searches.none? { |search| search[:names].include?('patient') && search[:expectation] == 'SHALL' }
60
60
  end
61
61
 
62
62
  def non_uscdi_resource?
@@ -48,6 +48,7 @@ module USCoreTestKit
48
48
  must_support_extension_elements.map do |element|
49
49
  {
50
50
  id: element.id,
51
+ path: element.path.gsub("#{resource}.", ''),
51
52
  url: element.type.first.profile.first
52
53
  }.tap do |metadata|
53
54
  if is_uscdi_requirement_element?(element)
@@ -52,16 +52,19 @@ module USCoreTestKit
52
52
  #US Core 4.0.0 Section 10.112.1.1 Additional USCDI v1 Requirement:
53
53
  must_supports[:extensions] << {
54
54
  id: 'Patient.extension:race',
55
+ path: 'extension',
55
56
  url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race',
56
57
  uscdi_only: true
57
58
  }
58
59
  must_supports[:extensions] << {
59
60
  id: 'Patient.extension:ethnicity',
61
+ path: 'extension',
60
62
  url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity',
61
63
  uscdi_only: true
62
64
  }
63
65
  must_supports[:extensions] << {
64
66
  id: 'Patient.extension:birthsex',
67
+ path: 'extension',
65
68
  url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex',
66
69
  uscdi_only: true
67
70
  }
@@ -54,6 +54,7 @@ module USCoreTestKit
54
54
 
55
55
  must_supports[:extensions] << {
56
56
  id: 'Patient.extension:genderIdentity',
57
+ path: 'extension',
57
58
  url: 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-genderIdentity',
58
59
  uscdi_only: true
59
60
  }
@@ -25,16 +25,14 @@ module USCoreTestKit
25
25
  'Encounter' => ['v311', 'v400'],
26
26
  'Location' => ['v311', 'v400', 'v501', 'v610'],
27
27
  'Organization' => ['v311', 'v400', 'v501', 'v610', 'v700_ballot'],
28
- 'Practitioner' => ['v311', 'v400'],
28
+ 'Practitioner' => ['v311', 'v400', 'v501', 'v610', 'v700_ballot'],
29
29
  'PractitionerRole' => ['v311', 'v400', 'v501', 'v610', 'v700_ballot'],
30
30
  'Provenance' => ['v311', 'v400', 'v501', 'v610', 'v700_ballot'],
31
- 'RelatedPerson' => ['v501', 'v610', 'v700_ballot'],
32
- 'Specimen' => ['v610', 'v700_ballot']
31
+ 'RelatedPerson' => ['v501', 'v610', 'v700_ballot']
33
32
  }.freeze
34
33
 
35
34
  SEARCHABLE_DELAYED_RESOURCES = {
36
- 'Location' => ['v700_ballot'],
37
- 'Practitioner' => ['v501', 'v610', 'v700_ballot']
35
+ 'Location' => ['v700_ballot']
38
36
  }.freeze
39
37
 
40
38
  ALL_VERSION_CATEGORY_FIRST_PROFILES = [
@@ -57,12 +57,15 @@ module USCoreTestKit
57
57
  "US Core #{ig_metadata.ig_version}"
58
58
  end
59
59
 
60
- def validator_env_name
61
- "#{ig_metadata.reformatted_version.upcase}_VALIDATOR_URL"
60
+ def ig_identifier
61
+ version = ig_metadata.ig_version[1..] # Remove leading 'v'
62
+ "hl7.fhir.us.core##{version}"
62
63
  end
63
64
 
64
65
  def ig_link
65
66
  case ig_metadata.ig_version
67
+ when 'v6.1.0'
68
+ 'http://hl7.org/fhir/us/core/STU6'
66
69
  when 'v5.0.1'
67
70
  'http://hl7.org/fhir/us/core/STU5.0.1'
68
71
  when 'v4.0.0'
@@ -72,7 +75,7 @@ module USCoreTestKit
72
75
  end
73
76
  end
74
77
 
75
- def test_granular_scopes?
78
+ def us_core_6_and_above?
76
79
  ig_metadata.ig_version[1].to_i > 5
77
80
  end
78
81
 
@@ -126,6 +129,14 @@ module USCoreTestKit
126
129
  def granular_scopes_id
127
130
  "us_core_#{ig_metadata.reformatted_version}_smart_granular_scopes"
128
131
  end
132
+
133
+ def screening_assessment_file_name
134
+ "../../custom_groups/#{ig_metadata.ig_version}/screening_assessment_group"
135
+ end
136
+
137
+ def screening_assessment_id
138
+ "us_core_#{ig_metadata.reformatted_version}_screening_assessment"
139
+ end
129
140
  end
130
141
  end
131
142
  end
@@ -6,6 +6,7 @@ require_relative 'generator/ig_metadata_extractor'
6
6
  require_relative 'generator/granular_scope_group_generator'
7
7
  require_relative 'generator/granular_scope_resource_type_group_generator'
8
8
  require_relative 'generator/granular_scope_test_generator'
9
+ require_relative 'generator/granular_scope_read_test_generator'
9
10
  require_relative 'generator/group_generator'
10
11
  require_relative 'generator/must_support_test_generator'
11
12
  require_relative 'generator/provenance_revinclude_search_test_generator'
@@ -104,6 +105,7 @@ module USCoreTestKit
104
105
 
105
106
  def generate_granular_scope_tests
106
107
  GranularScopeTestGenerator.generate(ig_metadata, base_output_dir)
108
+ GranularScopeReadTestGenerator.generate(ig_metadata, base_output_dir)
107
109
  end
108
110
 
109
111
  def generate_groups
@@ -0,0 +1,63 @@
1
+ module USCoreTestKit
2
+ module GranularScope
3
+
4
+ def granular_scopes
5
+ @granular_scopes ||=
6
+ received_scopes
7
+ .split(' ')
8
+ .select do |scope|
9
+ (scope.start_with?("patient/#{resource_type}") || scope.start_with?("user/#{resource_type}")) &&
10
+ scope.include?('?')
11
+ end
12
+ end
13
+
14
+ def granular_scope_search_params
15
+ @granular_scope_search_params ||=
16
+ granular_scopes.map do |scope|
17
+ _, granular_scope = scope.split('?')
18
+ name, value = granular_scope.split('=')
19
+
20
+ {
21
+ name:,
22
+ value:
23
+ }
24
+ end
25
+ end
26
+
27
+ def resource_specific_granular_scope_search_params
28
+ @resource_specific_granular_scope_search_params ||=
29
+ granular_scopes.select {|scope| scope.include?(resource_type)}.map do |scope|
30
+ _, granular_scope = scope.split('?')
31
+ name, value = granular_scope.split('=')
32
+ _, value = value.split('|')
33
+ {
34
+ name:,
35
+ value:
36
+ }
37
+ end
38
+ end
39
+
40
+ def previous_request_resources
41
+ first_request = previous_requests.first
42
+ next_page_url = nil
43
+ hash = Hash.new { |hash, key| hash[key] = [] }
44
+ previous_requests.each_with_object(hash) do |request, request_resource_hash|
45
+ request_resources =
46
+ if request.status == 200
47
+ request.resource.entry.map(&:resource).select { |resource| resource.resourceType == resource_type }
48
+ else
49
+ []
50
+ end
51
+
52
+ first_request = request if request.url != next_page_url
53
+
54
+ request_resource_hash[first_request].concat(request_resources)
55
+
56
+ next if request.resource&.resourceType != 'Bundle'
57
+
58
+ next_page_url = request.resource&.link&.find { |link| link.relation == 'next' }&.url
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,71 @@
1
+ require_relative 'resource_search_param_checker'
2
+ require_relative 'granular_scope'
3
+
4
+ module USCoreTestKit
5
+ module GranularScopeReadTest
6
+ extend Forwardable
7
+ include ResourceSearchParamChecker
8
+ include GranularScope
9
+
10
+ def_delegators 'self.class', :metadata
11
+ def self.included(klass)
12
+ klass.input(:received_scopes)
13
+ klass.attr_accessor :previous_requests
14
+ end
15
+
16
+ def run_scope_read_test
17
+ assert granular_scopes.present?, "No granular scopes were received for #{resource_type} resources"
18
+ resource_scopes = granular_scopes.select {|scope| scope.include?(resource_type)}
19
+
20
+ load_previous_requests
21
+ skip_if previous_requests.blank?,
22
+ "No #{resource_type} reads found"
23
+ previous_resources_for_reads = previous_request_resources.values.flatten
24
+
25
+ resource_specific_granular_scope_search_params.each do |scope|
26
+ current_scope = granular_scopes.find {|granular| granular.include?(scope[:name]) && granular.include?(scope[:value])}
27
+
28
+ resource_matching_scope = previous_resources_for_reads.find do |prev_resource|
29
+ resource_matches_param?(prev_resource, scope[:name], scope[:value])
30
+ end
31
+ skip_if resource_matching_scope.nil?, "Unable to find any resources to match scope #{current_scope}"
32
+
33
+ fhir_read resource_type, resource_matching_scope.id
34
+
35
+ assert_response_status(200)
36
+ assert_resource_type(resource_type)
37
+ end
38
+
39
+ nonmatching_resource = previous_resources_for_reads.find do |prev_resource|
40
+ resource_specific_granular_scope_search_params.none? do |scope|
41
+ resource_matches_param?(prev_resource, scope[:name], scope[:value])
42
+ end
43
+ end
44
+ if nonmatching_resource
45
+ fhir_read resource_type, nonmatching_resource.id
46
+ assert (response && response[:status]) != 200, "Server incorrectly responded with a successful status, read should fail due to scopes."
47
+ assert (resource && resource.resourceType != resource_type), "Server incorrectly returned a #{resource_type}, read should fail due to scopes"
48
+ else
49
+ info "Unable to find a resource that does not match scopes."
50
+ end
51
+ end
52
+
53
+ def load_previous_requests
54
+ params = metadata.searches.first[:names]
55
+ search_params_as_hash = params.each_with_object({}) do |name, hash|
56
+ hash[name] = nil
57
+ end
58
+ @previous_requests ||=
59
+ load_tagged_requests(search_params_tag(search_params_as_hash))
60
+ .sort_by { |request| request.index }
61
+ end
62
+
63
+ def unescape_search_value(value)
64
+ value&.gsub('\\,', ',')
65
+ end
66
+
67
+ def search_params_tag(params)
68
+ "#{resource_type}?#{params.keys.join('&')}"
69
+ end
70
+ end
71
+ end
@@ -1,11 +1,17 @@
1
+ require_relative 'resource_search_param_checker'
2
+ require_relative 'granular_scope'
3
+
1
4
  module USCoreTestKit
2
- module GranularScopeChecker
5
+ module GranularScopeSearchTest
6
+ include ResourceSearchParamChecker
7
+ include GranularScope
8
+
3
9
  def self.included(klass)
4
10
  klass.input(:received_scopes)
5
11
  klass.attr_accessor :previous_requests
6
12
  end
7
13
 
8
- def run_scope_check_test
14
+ def run_scope_search_test
9
15
  assert granular_scopes.present?, "No granular scopes were received for #{resource_type} resources"
10
16
 
11
17
  load_previous_requests
@@ -47,51 +53,6 @@ module USCoreTestKit
47
53
  end
48
54
  end
49
55
 
50
- def previous_request_resources
51
- first_request = previous_requests.first
52
- next_page_url = nil
53
- hash = Hash.new { |hash, key| hash[key] = [] }
54
- previous_requests.each_with_object(hash) do |request, request_resource_hash|
55
- request_resources =
56
- if request.status == 200
57
- request.resource.entry.map(&:resource).select { |resource| resource.resourceType == resource_type }
58
- else
59
- []
60
- end
61
-
62
- first_request = request if request.url != next_page_url
63
-
64
- request_resource_hash[first_request].concat(request_resources)
65
-
66
- next if request.resource&.resourceType != 'Bundle'
67
-
68
- next_page_url = request.resource&.link&.find { |link| link.relation == 'next' }&.url
69
- end
70
- end
71
-
72
- def granular_scopes
73
- @granular_scopes ||=
74
- received_scopes
75
- .split(' ')
76
- .select do |scope|
77
- (scope.start_with?("patient/#{resource_type}") || scope.start_with?("user/#{resource_type}")) &&
78
- scope.include?('?')
79
- end
80
- end
81
-
82
- def granular_scope_search_params
83
- @granular_scope_search_params ||=
84
- granular_scopes.map do |scope|
85
- _, granular_scope = scope.split('?')
86
- name, value = granular_scope.split('=')
87
-
88
- {
89
- name:,
90
- value:
91
- }
92
- end
93
- end
94
-
95
56
  def load_previous_requests
96
57
  search_params_as_hash = search_param_names.each_with_object({}) do |name, hash|
97
58
  hash[name] = nil
@@ -83,7 +83,17 @@ module USCoreTestKit
83
83
  @missing_extensions ||=
84
84
  must_support_extensions.select do |extension_definition|
85
85
  resources.none? do |resource|
86
- resource.extension.any? { |extension| extension.url == extension_definition[:url] }
86
+ path = extension_definition[:path]
87
+
88
+ if path == 'extension'
89
+ resource.extension.any? { |extension| extension.url == extension_definition[:url] }
90
+ else
91
+ extension = find_a_value_at(resource, path) do |el|
92
+ el.url == extension_definition[:url]
93
+ end
94
+
95
+ extension.present?
96
+ end
87
97
  end
88
98
  end
89
99
  end
@@ -100,14 +110,24 @@ module USCoreTestKit
100
110
  @missing_elements ||=
101
111
  must_support_elements.select do |element_definition|
102
112
  resources.none? do |resource|
103
- path = element_definition[:path] #.delete_suffix('[x]')
104
- value_found = find_a_value_at(resource, path) do |value|
105
- value_without_extensions =
106
- value.respond_to?(:to_hash) ? value.to_hash.reject { |key, _| key == 'extension' } : value
113
+ path = element_definition[:path]
114
+ ms_extension_urls = must_support_extensions.select { |ex| ex[:path] == "#{path}.extension" }
115
+ .map { |ex| ex[:url] }
107
116
 
108
- (value_without_extensions.present? || value_without_extensions == false) &&
117
+ value_found = find_a_value_at(resource, path) do |value|
118
+ if value.instance_of?(USCoreTestKit::PrimitiveType) && ms_extension_urls.present?
119
+ urls = value.extension&.map(&:url)
120
+ has_ms_extension = (urls & ms_extension_urls).present?
121
+ end
122
+
123
+ unless has_ms_extension
124
+ value = value.value if value.instance_of?(USCoreTestKit::PrimitiveType)
125
+ value_without_extensions =
126
+ value.respond_to?(:to_hash) ? value.to_hash.reject { |key, _| key == 'extension' } : value
127
+ end
128
+
129
+ (has_ms_extension || value_without_extensions.present? || value_without_extensions == false) &&
109
130
  (element_definition[:fixed_value].blank? || value == element_definition[:fixed_value])
110
-
111
131
  end
112
132
  # Note that false.present? => false, which is why we need to add this extra check
113
133
  value_found.present? || value_found == false
@@ -0,0 +1,5 @@
1
+ module USCoreTestKit
2
+ class PrimitiveType < FHIR::Element
3
+ attr_accessor :value
4
+ end
5
+ end
@@ -19,11 +19,10 @@ module USCoreTestKit
19
19
 
20
20
  failed_provenance =
21
21
  find_a_value_at(resource, 'agent') do |agent|
22
- ['Practitioner', 'Device'].any? { |resource_type| agent.who.reference&.include?(resource_type) } &&
23
- agent.onBehalfOf.nil?
22
+ ['Practitioner', 'Device'].any? { |resource_type| agent.who&.reference&.include?(resource_type) } &&
23
+ agent.onBehalfOf.nil?
24
24
  end
25
25
 
26
-
27
26
  if failed_provenance.present?
28
27
  validation_messages << {
29
28
  type: 'error',
@@ -34,4 +33,4 @@ module USCoreTestKit
34
33
  validation_messages
35
34
  end
36
35
  end
37
- end
36
+ end
@@ -165,7 +165,8 @@ module USCoreTestKit
165
165
 
166
166
  target_profile_with_version = target_profile.include?('|') ? target_profile : "#{target_profile}|#{metadata.profile_version}"
167
167
 
168
- outcome = FHIR::OperationOutcome.new(JSON.parse(validator.validate(resource, target_profile_with_version)))
168
+ validator_response = validator.validate(resource, target_profile_with_version)
169
+ outcome = validator.operation_outcome_from_hl7_wrapped_response(validator_response)
169
170
 
170
171
  message_hashes = outcome.issue&.map { |issue| validator.message_hash_from_issue(issue, resource) } || []
171
172