onc_certification_g10_test_kit 3.8.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno/terminology/expected_manifest.yml +58 -53
  3. data/lib/inferno/terminology/fhir_package_manager.rb +2 -1
  4. data/lib/inferno/terminology/loader.rb +7 -3
  5. data/lib/inferno/terminology/tasks/check_built_terminology.rb +17 -1
  6. data/lib/inferno/terminology/tasks/download_fhir_terminology.rb +2 -1
  7. data/lib/inferno/terminology/tasks/download_umls.rb +2 -1
  8. data/lib/inferno/terminology/tasks/expand_value_set_to_file.rb +1 -1
  9. data/lib/inferno/terminology/tasks/run_umls_jar.rb +2 -1
  10. data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +185 -0
  11. data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +4 -0
  12. data/lib/onc_certification_g10_test_kit/g10_options.rb +8 -0
  13. data/lib/onc_certification_g10_test_kit/igs/CodeSystem-observation-category.json +83 -0
  14. data/lib/onc_certification_g10_test_kit/igs/StructureDefinition-condition-assertedDate.json +280 -0
  15. data/lib/onc_certification_g10_test_kit/igs/ValueSet-observation-category.json +48 -0
  16. data/lib/onc_certification_g10_test_kit/igs/ValueSet-servicerequest-category.json +69 -0
  17. data/lib/onc_certification_g10_test_kit/limited_scope_grant_test.rb +5 -0
  18. data/lib/onc_certification_g10_test_kit/multi_patient_api_stu1.rb +10 -9
  19. data/lib/onc_certification_g10_test_kit/multi_patient_api_stu2.rb +10 -9
  20. data/lib/onc_certification_g10_test_kit/profile_selector.rb +72 -46
  21. data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +118 -21
  22. data/lib/onc_certification_g10_test_kit/short_id_manager.rb +2 -0
  23. data/lib/onc_certification_g10_test_kit/short_id_map.yml +579 -0
  24. data/lib/onc_certification_g10_test_kit/single_patient_api_group.rb +2 -1
  25. data/lib/onc_certification_g10_test_kit/single_patient_us_core_4_api_group.rb +33 -18
  26. data/lib/onc_certification_g10_test_kit/single_patient_us_core_5_api_group.rb +46 -24
  27. data/lib/onc_certification_g10_test_kit/single_patient_us_core_6_api_group.rb +203 -0
  28. data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +14 -4
  29. data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +106 -31
  30. data/lib/onc_certification_g10_test_kit/version.rb +1 -1
  31. data/lib/onc_certification_g10_test_kit/well_known_capabilities_test.rb +1 -1
  32. data/lib/onc_certification_g10_test_kit.rb +14 -1
  33. metadata +13 -8
@@ -4,23 +4,23 @@ module ONCCertificationG10TestKit
4
4
  module ProfileSelector
5
5
  include G10Options
6
6
 
7
- def extract_profile(profile)
8
- case profile
7
+ def extract_profile(resource_type)
8
+ case resource_type
9
9
  when 'Medication'
10
10
  return versioned_us_core_module.const_get('USCoreTestSuite').metadata.find do |meta|
11
- meta.resource == profile
11
+ meta.resource == resource_type
12
12
  end.profile_url
13
13
  when 'Location'
14
14
  return 'http://hl7.org/fhir/StructureDefinition/Location'
15
15
  end
16
- versioned_us_core_module.const_get("#{profile}Group").metadata.profile_url
16
+ versioned_us_core_module.const_get("#{resource_type}Group").metadata.profile_url
17
17
  end
18
18
 
19
- def observation_contains_code(observation_resource, code)
19
+ def observation_contains_code?(observation_resource, code)
20
20
  observation_resource&.code&.coding&.any? { |coding| coding&.code == code }
21
21
  end
22
22
 
23
- def resource_contains_category(resource, category_code, category_system = nil) # rubocop:disable Metrics/CyclomaticComplexity
23
+ def resource_contains_category?(resource, category_code, category_system = nil) # rubocop:disable Metrics/CyclomaticComplexity
24
24
  resource&.category&.any? do |category|
25
25
  category.coding&.any? do |coding|
26
26
  coding.code == category_code &&
@@ -35,35 +35,35 @@ module ONCCertificationG10TestKit
35
35
  case resource.resourceType
36
36
  when 'Condition'
37
37
  case us_core_version
38
- when US_CORE_5
39
- if resource_contains_category(resource, 'encounter-diagnosis', 'http://terminology.hl7.org/CodeSystem/condition-category')
38
+ when US_CORE_5, US_CORE_6
39
+ if resource_contains_category?(resource, 'encounter-diagnosis', 'http://terminology.hl7.org/CodeSystem/condition-category')
40
40
  profiles << extract_profile('ConditionEncounterDiagnosis')
41
- elsif resource_contains_category(resource, 'problem-list-item',
42
- 'http://terminology.hl7.org/CodeSystem/condition-category') ||
43
- resource_contains_category(resource, 'health-concern', 'http://hl7.org/fhir/us/core/CodeSystem/condition-category')
41
+ elsif resource_contains_category?(resource, 'problem-list-item',
42
+ 'http://terminology.hl7.org/CodeSystem/condition-category') ||
43
+ resource_contains_category?(resource, 'health-concern', 'http://hl7.org/fhir/us/core/CodeSystem/condition-category')
44
44
  profiles << extract_profile('ConditionProblemsHealthConcerns')
45
45
  end
46
46
  else
47
47
  profiles << extract_profile(resource.resourceType)
48
48
  end
49
49
  when 'DiagnosticReport'
50
- profiles << if resource_contains_category(resource, 'LAB', 'http://terminology.hl7.org/CodeSystem/v2-0074')
50
+ profiles << if resource_contains_category?(resource, 'LAB', 'http://terminology.hl7.org/CodeSystem/v2-0074')
51
51
  extract_profile('DiagnosticReportLab')
52
52
  else
53
53
  extract_profile('DiagnosticReportNote')
54
54
  end
55
55
  when 'Observation'
56
- profiles << extract_profile('Smokingstatus') if observation_contains_code(resource, '72166-2')
56
+ profiles << extract_profile('Smokingstatus') if observation_contains_code?(resource, '72166-2')
57
57
 
58
- profiles << extract_profile('ObservationLab') if resource_contains_category(resource, 'laboratory', 'http://terminology.hl7.org/CodeSystem/observation-category')
58
+ profiles << extract_profile('ObservationLab') if resource_contains_category?(resource, 'laboratory', 'http://terminology.hl7.org/CodeSystem/observation-category')
59
59
 
60
- profiles << extract_profile('PediatricBmiForAge') if observation_contains_code(resource, '59576-9')
60
+ profiles << extract_profile('PediatricBmiForAge') if observation_contains_code?(resource, '59576-9')
61
61
 
62
- profiles << extract_profile('PediatricWeightForHeight') if observation_contains_code(resource, '77606-2')
62
+ profiles << extract_profile('PediatricWeightForHeight') if observation_contains_code?(resource, '77606-2')
63
63
 
64
- profiles << extract_profile('PulseOximetry') if observation_contains_code(resource, '59408-5')
64
+ profiles << extract_profile('PulseOximetry') if observation_contains_code?(resource, '59408-5')
65
65
 
66
- if observation_contains_code(resource, '8289-1')
66
+ if observation_contains_code?(resource, '8289-1')
67
67
  profiles << case us_core_version
68
68
  when US_CORE_3
69
69
  extract_profile('HeadCircumference')
@@ -72,7 +72,7 @@ module ONCCertificationG10TestKit
72
72
  end
73
73
  end
74
74
 
75
- if observation_contains_code(resource, '9843-4') && !using_us_core_3?
75
+ if observation_contains_code?(resource, '9843-4') && !using_us_core_3?
76
76
  profiles << extract_profile('HeadCircumference')
77
77
  end
78
78
 
@@ -81,9 +81,9 @@ module ONCCertificationG10TestKit
81
81
  # Body Mass Index is replaced by :pediatric_bmi_age Profile
82
82
  # Systolic Blood Pressure, Diastolic Blood Pressure are covered by :blood_pressure Profile
83
83
  # Head Circumference is replaced by US Core Head Occipital-frontal Circumference Percentile Profile
84
- profiles << extract_profile('Bmi') if observation_contains_code(resource, '39156-5') && !using_us_core_3?
84
+ profiles << extract_profile('Bmi') if observation_contains_code?(resource, '39156-5') && !using_us_core_3?
85
85
 
86
- if observation_contains_code(resource, '85354-9')
86
+ if observation_contains_code?(resource, '85354-9')
87
87
  profiles << case us_core_version
88
88
  when US_CORE_3
89
89
  extract_profile('Bp')
@@ -92,7 +92,7 @@ module ONCCertificationG10TestKit
92
92
  end
93
93
  end
94
94
 
95
- if observation_contains_code(resource, '8302-2')
95
+ if observation_contains_code?(resource, '8302-2')
96
96
  profiles << case us_core_version
97
97
  when US_CORE_3
98
98
  extract_profile('Bodyheight')
@@ -101,7 +101,7 @@ module ONCCertificationG10TestKit
101
101
  end
102
102
  end
103
103
 
104
- if observation_contains_code(resource, '8310-5')
104
+ if observation_contains_code?(resource, '8310-5')
105
105
  profiles << case us_core_version
106
106
  when US_CORE_3
107
107
  extract_profile('Bodytemp')
@@ -110,7 +110,7 @@ module ONCCertificationG10TestKit
110
110
  end
111
111
  end
112
112
 
113
- if observation_contains_code(resource, '29463-7')
113
+ if observation_contains_code?(resource, '29463-7')
114
114
  profiles << case us_core_version
115
115
  when US_CORE_3
116
116
  extract_profile('Bodyweight')
@@ -119,7 +119,7 @@ module ONCCertificationG10TestKit
119
119
  end
120
120
  end
121
121
 
122
- if observation_contains_code(resource, '8867-4')
122
+ if observation_contains_code?(resource, '8867-4')
123
123
  profiles << case us_core_version
124
124
  when US_CORE_3
125
125
  extract_profile('Heartrate')
@@ -128,7 +128,7 @@ module ONCCertificationG10TestKit
128
128
  end
129
129
  end
130
130
 
131
- if observation_contains_code(resource, '9279-1')
131
+ if observation_contains_code?(resource, '9279-1')
132
132
  profiles << case us_core_version
133
133
  when US_CORE_3
134
134
  extract_profile('Resprate')
@@ -138,44 +138,70 @@ module ONCCertificationG10TestKit
138
138
  end
139
139
 
140
140
  if using_us_core_5? &&
141
- resource_contains_category(
141
+ resource_contains_category?(
142
142
  resource, 'clinical-test', 'http://hl7.org/fhir/us/core/CodeSystem/us-core-observation-category'
143
143
  )
144
144
  profiles << extract_profile('ObservationClinicalTest')
145
145
  end
146
146
 
147
- if using_us_core_5? && observation_contains_code(resource, '76690-7')
147
+ if (using_us_core_5? || using_us_core_6?) && observation_contains_code?(resource, '76690-7')
148
148
  profiles << extract_profile('ObservationSexualOrientation')
149
149
  end
150
150
 
151
151
  if using_us_core_5? &&
152
- resource_contains_category(resource, 'social-history',
153
- 'http://terminology.hl7.org/CodeSystem/observation-category')
152
+ resource_contains_category?(resource, 'social-history',
153
+ 'http://terminology.hl7.org/CodeSystem/observation-category')
154
154
  profiles << extract_profile('ObservationSocialHistory')
155
155
  end
156
156
 
157
157
  if using_us_core_5? &&
158
- resource_contains_category(resource, 'imaging',
159
- 'http://terminology.hl7.org/CodeSystem/observation-category')
158
+ resource_contains_category?(resource, 'imaging',
159
+ 'http://terminology.hl7.org/CodeSystem/observation-category')
160
160
  profiles << extract_profile('ObservationImaging')
161
161
  end
162
162
 
163
- # We will simply match all Observations of category "survey" to SDOH,
164
- # and do not look at the category "sdoh". US Core spec team says that
165
- # support for the "sdoh" category is limited, and the validation rules
166
- # allow for very generic surveys to validate against this profile.
167
- # And will not validate against the ObservationSurvey profile itself.
168
- # This may not be exactly precise but it works out the same
163
+ if resource_contains_category?(resource, 'survey',
164
+ 'http://terminology.hl7.org/CodeSystem/observation-category')
165
+ if using_us_core_5?
166
+ # We will simply match all Observations of category "survey" to SDOH,
167
+ # and do not look at the category "sdoh". US Core spec team says that
168
+ # support for the "sdoh" category is limited, and the validation rules
169
+ # allow for very generic surveys to validate against this profile.
170
+ # And will not validate against the ObservationSurvey profile itself.
171
+ # This may not be exactly precise but it works out the same
172
+
173
+ # if we wanted to be more specific here, we would add:
174
+ # `resource_contains_category?(resource, 'sdoh',
175
+ # 'http://terminology.hl7.org/CodeSystem/observation-category') &&`
176
+ # along with a specific extract_profile('ObservationSurvey') to catch non-sdoh.
177
+ profiles << extract_profile('ObservationSdohAssessment')
178
+ elsif using_us_core_6?
179
+ profiles << extract_profile('ObservationScreeningAssessment')
180
+ end
181
+ end
169
182
 
170
- # if we wanted to be more specific here, we would add:
171
- # `resource_contains_category(resource, 'sdoh',
172
- # 'http://terminology.hl7.org/CodeSystem/observation-category') &&`
173
- # along with a specific extract_profile('ObservationSurvey') to catch non-sdoh.
174
- if using_us_core_5? &&
175
- resource_contains_category(resource, 'survey',
176
- 'http://terminology.hl7.org/CodeSystem/observation-category')
183
+ if using_us_core_6? && observation_contains_code?(resource, '11341-5')
184
+ profiles << extract_profile('ObservationOccupation')
185
+ end
186
+
187
+ if using_us_core_6? && observation_contains_code?(resource, '86645-9')
188
+ profiles << extract_profile('ObservationPregnancyintent')
189
+ end
190
+
191
+ if using_us_core_6? && observation_contains_code?(resource, '82810-3')
192
+ profiles << extract_profile('ObservationPregnancystatus')
193
+ end
194
+
195
+ clinical_result_categories = [
196
+ 'laboratory', 'exam', 'therpay', 'imaging', 'procedure', 'vital-signs', 'activity'
197
+ ]
177
198
 
178
- profiles << extract_profile('ObservationSdohAssessment')
199
+ if using_us_core_6? && clinical_result_categories.any? do |category|
200
+ resource_contains_category?(
201
+ resource, category, 'http://terminology.hl7.org/CodeSystem/observation-category'
202
+ )
203
+ end
204
+ profiles << extract_profile('ObservationClinicalResult')
179
205
  end
180
206
 
181
207
  nil
@@ -14,20 +14,25 @@ module ONCCertificationG10TestKit
14
14
 
15
15
  Resources that can be mapped to USCDI are checked in this test, including:
16
16
 
17
- * AllergyIntolerance
18
- * CarePlan
19
- * CareTeam
20
- * Condition
21
- * Device
22
- * DiagnosticReport
23
- * DocumentReference
24
- * Goal
25
- * Immunization
26
- * MedicationRequest
27
- * Observation
28
- * Procedure
29
-
30
- If testing against USCDI v2, ServiceRequest is also checked.
17
+ * AllergyIntolerance
18
+ * CarePlan
19
+ * CareTeam
20
+ * Condition
21
+ * Device
22
+ * DiagnosticReport
23
+ * DocumentReference
24
+ * Goal
25
+ * Immunization
26
+ * MedicationRequest
27
+ * Observation
28
+ * Patient
29
+ * Procedure
30
+
31
+ If testing against USCDI v2, Encounter and ServiceRequest are also
32
+ checked.
33
+
34
+ If testing against USCDI v3, Encounter, ServiceRequest, Coverage,
35
+ and MedicationDispense are also checked.
31
36
 
32
37
  For each of the resources that can be mapped to USCDI data class or
33
38
  elements, this set of tests performs a minimum number of requests to
@@ -42,16 +47,28 @@ module ONCCertificationG10TestKit
42
47
  This set of tests does not attempt to access resources that do not
43
48
  directly map to USCDI. For USCDI v1 this includes:
44
49
 
45
- * Encounter
46
- * Location
47
- * Organization
48
- * Practitioner
50
+ * Encounter
51
+ * Location
52
+ * Organization
53
+ * Practitioner
49
54
 
50
55
  For USCDI v2 this includes:
51
56
 
52
- * Location
53
- * Organization
54
- * Practitioner
57
+ * Location
58
+ * Organization
59
+ * Practitioner
60
+
61
+ For USCDI v3 this includes:
62
+
63
+ * Location
64
+ * Organization
65
+ * Practitioner
66
+ * RelatedPerson
67
+ * Specimen
68
+
69
+ It also does not test Provenance, as this resource type is accessed by
70
+ queries through other resource types. These resources types are accessed
71
+ in the more comprehensive Single Patient Query tests.
55
72
 
56
73
  If the tester chooses to not grant access to a resource, the queries
57
74
  associated with that resource must result in either a 401 (Unauthorized)
@@ -349,5 +366,85 @@ module ONCCertificationG10TestKit
349
366
  USCoreTestKit::USCoreV501::ServiceRequestGroup
350
367
  end
351
368
  end
369
+
370
+ test from: :g10_restricted_access_test do
371
+ title 'Access to Encounter resources are restricted properly based on patient-selected scope'
372
+ description %(
373
+ This test ensures that access to the Encounter is granted or
374
+ denied based on the selection by the tester prior to the execution of
375
+ the test. If the tester indicated that access will be granted to this
376
+ resource, this test verifies that a search by patient in this resource
377
+ does not result in an access denied result. If the tester indicated that
378
+ access will be denied for this resource, this verifies that search by
379
+ patient in the resource results in an access denied result.
380
+ )
381
+ id :g10_us_core_6_encounter_restricted_access
382
+
383
+ required_suite_options G10Options::US_CORE_6_REQUIREMENT
384
+
385
+ def resource_group
386
+ USCoreTestKit::USCoreV610::EncounterGroup
387
+ end
388
+ end
389
+
390
+ test from: :g10_restricted_access_test do
391
+ title 'Access to ServiceRequest resources are restricted properly based on patient-selected scope'
392
+ description %(
393
+ This test ensures that access to the ServiceRequest is granted or
394
+ denied based on the selection by the tester prior to the execution of
395
+ the test. If the tester indicated that access will be granted to this
396
+ resource, this test verifies that a search by patient in this resource
397
+ does not result in an access denied result. If the tester indicated that
398
+ access will be denied for this resource, this verifies that search by
399
+ patient in the resource results in an access denied result.
400
+ )
401
+ id :g10_us_core_6_service_request_restricted_access
402
+
403
+ required_suite_options G10Options::US_CORE_6_REQUIREMENT
404
+
405
+ def resource_group
406
+ USCoreTestKit::USCoreV610::ServiceRequestGroup
407
+ end
408
+ end
409
+
410
+ test from: :g10_restricted_access_test do
411
+ title 'Access to Coverage resources are restricted properly based on patient-selected scope'
412
+ description %(
413
+ This test ensures that access to the Coverage is granted or
414
+ denied based on the selection by the tester prior to the execution of
415
+ the test. If the tester indicated that access will be granted to this
416
+ resource, this test verifies that a search by patient in this resource
417
+ does not result in an access denied result. If the tester indicated that
418
+ access will be denied for this resource, this verifies that search by
419
+ patient in the resource results in an access denied result.
420
+ )
421
+ id :g10_us_core_6_coverage_restricted_access
422
+
423
+ required_suite_options G10Options::US_CORE_6_REQUIREMENT
424
+
425
+ def resource_group
426
+ USCoreTestKit::USCoreV610::CoverageGroup
427
+ end
428
+ end
429
+
430
+ test from: :g10_restricted_access_test do
431
+ title 'Access to MedicationDispense resources are restricted properly based on patient-selected scope'
432
+ description %(
433
+ This test ensures that access to the MedicationDispense is granted or
434
+ denied based on the selection by the tester prior to the execution of
435
+ the test. If the tester indicated that access will be granted to this
436
+ resource, this test verifies that a search by patient in this resource
437
+ does not result in an access denied result. If the tester indicated that
438
+ access will be denied for this resource, this verifies that search by
439
+ patient in the resource results in an access denied result.
440
+ )
441
+ id :g10_us_core_6_medication_dispense_restricted_access
442
+
443
+ required_suite_options G10Options::US_CORE_6_REQUIREMENT
444
+
445
+ def resource_group
446
+ USCoreTestKit::USCoreV610::MedicationDispenseGroup
447
+ end
448
+ end
352
449
  end
353
450
  end
@@ -26,6 +26,8 @@ module ONCCertificationG10TestKit
26
26
  rescue KeyError
27
27
  Inferno::Application['logger'].warn("No short id defined for #{runnable.id}")
28
28
  end
29
+ rescue Errno::ENOENT
30
+ Inferno::Application['logger'].warn('No short id map found')
29
31
  end
30
32
 
31
33
  ### The methods below are only for creating an initial list of short ids