us_core_test_kit 0.6.5 → 0.7.1

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