onc_certification_g10_test_kit 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno/terminology/expected_manifest.yml +36 -693
  3. data/lib/inferno/terminology/fhir_package_manager.rb +16 -14
  4. data/lib/inferno/terminology/loader.rb +25 -3
  5. data/lib/inferno/terminology/tasks/create_value_set_validators.rb +3 -3
  6. data/lib/inferno/terminology/tasks/download_umls.rb +3 -2
  7. data/lib/inferno/terminology/tasks/expand_value_set_to_file.rb +1 -1
  8. data/lib/inferno/terminology/tasks/run_umls_jar.rb +2 -1
  9. data/lib/inferno/terminology/tasks/validate_code.rb +1 -1
  10. data/lib/inferno/terminology/terminology_validation.rb +1 -1
  11. data/lib/inferno/terminology/validator.rb +9 -9
  12. data/lib/inferno/terminology/value_set.rb +65 -63
  13. data/lib/onc_certification_g10_test_kit/authorization_request_builder.rb +2 -2
  14. data/lib/onc_certification_g10_test_kit/bulk_data_authorization.rb +4 -4
  15. data/lib/onc_certification_g10_test_kit/bulk_data_group_export_stu1.rb +3 -1
  16. data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +7 -4
  17. data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +5 -14
  18. data/lib/onc_certification_g10_test_kit/configuration_checker.rb +23 -1
  19. data/lib/onc_certification_g10_test_kit/export_kick_off_performer.rb +2 -2
  20. data/lib/onc_certification_g10_test_kit/g10_options.rb +46 -0
  21. data/lib/onc_certification_g10_test_kit/incorrectly_permitted_tls_versions_messages_setup_test.rb +34 -0
  22. data/lib/onc_certification_g10_test_kit/limited_scope_grant_test.rb +3 -1
  23. data/lib/onc_certification_g10_test_kit/multi_patient_api_stu1.rb +11 -0
  24. data/lib/onc_certification_g10_test_kit/multi_patient_api_stu2.rb +10 -0
  25. data/lib/onc_certification_g10_test_kit/onc_program_procedure.yml +1 -0
  26. data/lib/onc_certification_g10_test_kit/patient_scope_test.rb +25 -0
  27. data/lib/onc_certification_g10_test_kit/profile_selector.rb +33 -25
  28. data/lib/onc_certification_g10_test_kit/resource_access_test.rb +1 -2
  29. data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +2 -2
  30. data/lib/onc_certification_g10_test_kit/short_id_manager.rb +46 -0
  31. data/lib/onc_certification_g10_test_kit/short_id_map.yml +1538 -0
  32. data/lib/onc_certification_g10_test_kit/single_patient_api_group.rb +4 -0
  33. data/lib/onc_certification_g10_test_kit/single_patient_us_core_4_api_group.rb +4 -0
  34. data/lib/onc_certification_g10_test_kit/single_patient_us_core_5_api_group.rb +4 -0
  35. data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +2 -2
  36. data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group.rb +27 -4
  37. data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group_stu2.rb +27 -4
  38. data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +58 -7
  39. data/lib/onc_certification_g10_test_kit/smart_invalid_pkce_group.rb +1 -1
  40. data/lib/onc_certification_g10_test_kit/smart_invalid_token_group.rb +1 -1
  41. data/lib/onc_certification_g10_test_kit/smart_invalid_token_group_stu2.rb +1 -1
  42. data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +3 -2
  43. data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +4 -2
  44. data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +57 -6
  45. data/lib/onc_certification_g10_test_kit/tasks/test_procedure.rb +1 -1
  46. data/lib/onc_certification_g10_test_kit/terminology_binding_validator.rb +1 -1
  47. data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +7 -4
  48. data/lib/onc_certification_g10_test_kit/version.rb +1 -1
  49. data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +52 -2
  50. data/lib/onc_certification_g10_test_kit/well_known_capabilities_test.rb +3 -1
  51. data/lib/onc_certification_g10_test_kit.rb +41 -23
  52. metadata +22 -17
@@ -0,0 +1,46 @@
1
+ module ONCCertificationG10TestKit
2
+ module G10Options
3
+ US_CORE_3 = 'us_core_3'.freeze
4
+ US_CORE_4 = 'us_core_4'.freeze
5
+ US_CORE_5 = 'us_core_5'.freeze
6
+
7
+ BULK_DATA_1 = 'multi_patient_api_stu1'.freeze
8
+ BULK_DATA_2 = 'multi_patient_api_stu2'.freeze
9
+
10
+ SMART_1 = 'smart_app_launch_1'.freeze
11
+ SMART_2 = 'smart_app_launch_2'.freeze
12
+
13
+ US_CORE_3_REQUIREMENT = { us_core_version: US_CORE_3 }.freeze
14
+ US_CORE_4_REQUIREMENT = { us_core_version: US_CORE_4 }.freeze
15
+ US_CORE_5_REQUIREMENT = { us_core_version: US_CORE_5 }.freeze
16
+
17
+ BULK_DATA_1_REQUIREMENT = { multi_patient_version: BULK_DATA_1 }.freeze
18
+ BULK_DATA_2_REQUIREMENT = { multi_patient_version: BULK_DATA_2 }.freeze
19
+
20
+ SMART_1_REQUIREMENT = { smart_app_launch_version: SMART_1 }.freeze
21
+ SMART_2_REQUIREMENT = { smart_app_launch_version: SMART_2 }.freeze
22
+
23
+ def us_core_version
24
+ suite_options[:us_core_version]
25
+ end
26
+
27
+ def using_us_core_3?
28
+ us_core_version == US_CORE_3
29
+ end
30
+
31
+ def using_us_core_5?
32
+ us_core_version == US_CORE_5
33
+ end
34
+
35
+ def versioned_us_core_module
36
+ case us_core_version
37
+ when US_CORE_5
38
+ USCoreTestKit::USCoreV501
39
+ when US_CORE_4
40
+ USCoreTestKit::USCoreV400
41
+ else
42
+ USCoreTestKit::USCoreV311
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,34 @@
1
+ module ONCCertificationG10TestKit
2
+ class IncorrectlyPermittedTLSVersionsMessagesSetupTest < Inferno::Test
3
+ id :g10_incorrectly_permitted_tls_versions_messages_setup
4
+ title 'Handle TLS Warning Messages'
5
+
6
+ input :incorrectly_permitted_tls_versions_messages
7
+ output :unique_incorrectly_permitted_tls_versions_messages,
8
+ :tls_documentation_required
9
+
10
+ run do
11
+ pass_if incorrectly_permitted_tls_versions_messages.blank?
12
+
13
+ warning do
14
+ new_warning_messages = incorrectly_permitted_tls_versions_messages&.split("\n")
15
+
16
+ pass_if new_warning_messages.blank?
17
+
18
+ raw_previous_warning_messages =
19
+ Inferno::Repositories::SessionData.new.load(
20
+ test_session_id:,
21
+ name: 'unique_incorrectly_permitted_tls_versions_messages'
22
+ )
23
+
24
+ previous_warning_messages =
25
+ raw_previous_warning_messages.blank? ? [] : raw_previous_warning_messages.split("\n")
26
+
27
+ warning_messages = (previous_warning_messages + new_warning_messages).uniq
28
+
29
+ output unique_incorrectly_permitted_tls_versions_messages: warning_messages.join("\n"),
30
+ tls_documentation_required: 'true'
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,5 +1,7 @@
1
1
  module ONCCertificationG10TestKit
2
2
  class LimitedScopeGrantTest < Inferno::Test
3
+ include G10Options
4
+
3
5
  title 'OAuth token exchange response grants scope that is limited to those selected by user'
4
6
  description %(
5
7
  The ONC certification criteria requires that patients are capable of
@@ -33,7 +35,7 @@ module ONCCertificationG10TestKit
33
35
  (POSSIBLE_RESOURCES + ['Encounter', 'ServiceRequest']).freeze
34
36
 
35
37
  def possible_resources
36
- return V5_POSSIBLE_RESOURCES if suite_options[:us_core_version] == 'us_core_5'
38
+ return V5_POSSIBLE_RESOURCES if using_us_core_5?
37
39
 
38
40
  POSSIBLE_RESOURCES
39
41
  end
@@ -1,6 +1,7 @@
1
1
  require_relative 'bulk_data_authorization'
2
2
  require_relative 'bulk_data_group_export_stu1'
3
3
  require_relative 'bulk_data_group_export_validation'
4
+ require_relative 'incorrectly_permitted_tls_versions_messages_setup_test'
4
5
 
5
6
  module ONCCertificationG10TestKit
6
7
  class MultiPatientAPIGroupSTU1 < Inferno::TestGroup
@@ -62,7 +63,17 @@ module ONCCertificationG10TestKit
62
63
  This test returns an access token.
63
64
  DESCRIPTION
64
65
 
66
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
67
+ id: :g10_bulk_auth_tls_messages_setup
68
+
65
69
  group from: :bulk_data_group_export
70
+
71
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
72
+ id: :g10_bulk_group_export_tls_messages_setup
73
+
66
74
  group from: :bulk_data_group_export_validation
75
+
76
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
77
+ id: :g10_bulk_group_export_validation_messages_setup
67
78
  end
68
79
  end
@@ -62,7 +62,17 @@ module ONCCertificationG10TestKit
62
62
  This test returns an access token.
63
63
  DESCRIPTION
64
64
 
65
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
66
+ id: :g10_bulk_auth_tls_messages_setup
67
+
65
68
  group from: :bulk_data_group_export_stu2
69
+
70
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
71
+ id: :g10_bulk_group_export_tls_messages_setup
72
+
66
73
  group from: :bulk_data_group_export_validation
74
+
75
+ test from: :g10_incorrectly_permitted_tls_versions_messages_setup,
76
+ id: :g10_bulk_group_export_validation_messages_setup
67
77
  end
68
78
  end
@@ -92,6 +92,7 @@ procedure:
92
92
  - 9.8.06
93
93
  - 9.9.03
94
94
  - 9.9.06
95
+ - 9.10.15
95
96
  inferno_notes: |
96
97
  Inferno tests that all endpoints provided support at least TLS
97
98
  version 1.2, and rejects all requests for TLS version 1.1 or below.
@@ -0,0 +1,25 @@
1
+ module ONCCertificationG10TestKit
2
+ class PatientScopeTest < Inferno::Test
3
+ title 'Patient-level scopes were granted'
4
+ description %(
5
+ Systems are required to support the `permission-patient` capability as
6
+ part of the [Clinician Access for EHR Launch Capability
7
+ Set.](http://hl7.org/fhir/smart-app-launch/1.0.0/conformance/index.html#clinician-access-for-ehr-launch)
8
+
9
+ This test verifies that systems are capable of granting patient-level
10
+ scopes during an EHR Launch.
11
+ )
12
+ id :g10_patient_scope
13
+ input :received_scopes
14
+
15
+ run do
16
+ expected_scope = if config.options[:scope_version] == :v2
17
+ 'patient/Patient.rs'
18
+ else
19
+ 'patient/Patient.read'
20
+ end
21
+ assert received_scopes&.include?(expected_scope),
22
+ "#{expected_scope} scope was requested, but not received. Received: `#{received_scopes}`"
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,9 @@
1
+ require_relative 'g10_options'
2
+
1
3
  module ONCCertificationG10TestKit
2
4
  module ProfileSelector
5
+ include G10Options
6
+
3
7
  def extract_profile(profile)
4
8
  case profile
5
9
  when 'Medication'
@@ -28,8 +32,8 @@ module ONCCertificationG10TestKit
28
32
  def select_profile(resource) # rubocop:disable Metrics/CyclomaticComplexity
29
33
  case resource.resourceType
30
34
  when 'Condition'
31
- case suite_options[:us_core_version]
32
- when 'us_core_5'
35
+ case us_core_version
36
+ when US_CORE_5
33
37
  if resource_contains_category(resource, 'encounter-diagnosis', 'http://terminology.hl7.org/CodeSystem/condition-category')
34
38
  extract_profile('ConditionEncounterDiagnosis')
35
39
  elsif resource_contains_category(resource, 'problem-list-item',
@@ -56,15 +60,15 @@ module ONCCertificationG10TestKit
56
60
  return extract_profile('PulseOximetry') if observation_contains_code(resource, '59408-5')
57
61
 
58
62
  if observation_contains_code(resource, '8289-1')
59
- case suite_options[:us_core_version]
60
- when 'us_core_3'
63
+ case us_core_version
64
+ when US_CORE_3
61
65
  return extract_profile('HeadCircumference')
62
66
  else
63
67
  return extract_profile('HeadCircumferencePercentile')
64
68
  end
65
69
  end
66
70
 
67
- if observation_contains_code(resource, '9843-4') && suite_options[:us_core_version] != 'us_core_3'
71
+ if observation_contains_code(resource, '9843-4') && !using_us_core_3?
68
72
  return extract_profile('HeadCircumference')
69
73
  end
70
74
 
@@ -73,13 +77,11 @@ module ONCCertificationG10TestKit
73
77
  # Body Mass Index is replaced by :pediatric_bmi_age Profile
74
78
  # Systolic Blood Pressure, Diastolic Blood Pressure are covered by :blood_pressure Profile
75
79
  # Head Circumference is replaced by US Core Head Occipital-frontal Circumference Percentile Profile
76
- if observation_contains_code(resource, '39156-5') && suite_options[:us_core_version] != 'us_core_3'
77
- return extract_profile('Bmi')
78
- end
80
+ return extract_profile('Bmi') if observation_contains_code(resource, '39156-5') && !using_us_core_3?
79
81
 
80
82
  if observation_contains_code(resource, '85354-9')
81
- case suite_options[:us_core_version]
82
- when 'us_core_3'
83
+ case us_core_version
84
+ when US_CORE_3
83
85
  return extract_profile('Bp')
84
86
  else
85
87
  return extract_profile('BloodPressure')
@@ -87,8 +89,8 @@ module ONCCertificationG10TestKit
87
89
  end
88
90
 
89
91
  if observation_contains_code(resource, '8302-2')
90
- case suite_options[:us_core_version]
91
- when 'us_core_3'
92
+ case us_core_version
93
+ when US_CORE_3
92
94
  return extract_profile('Bodyheight')
93
95
  else
94
96
  return extract_profile('BodyHeight')
@@ -96,8 +98,8 @@ module ONCCertificationG10TestKit
96
98
  end
97
99
 
98
100
  if observation_contains_code(resource, '8310-5')
99
- case suite_options[:us_core_version]
100
- when 'us_core_3'
101
+ case us_core_version
102
+ when US_CORE_3
101
103
  return extract_profile('Bodytemp')
102
104
  else
103
105
  return extract_profile('BodyTemperature')
@@ -105,8 +107,8 @@ module ONCCertificationG10TestKit
105
107
  end
106
108
 
107
109
  if observation_contains_code(resource, '29463-7')
108
- case suite_options[:us_core_version]
109
- when 'us_core_3'
110
+ case us_core_version
111
+ when US_CORE_3
110
112
  return extract_profile('Bodyweight')
111
113
  else
112
114
  return extract_profile('BodyWeight')
@@ -114,8 +116,8 @@ module ONCCertificationG10TestKit
114
116
  end
115
117
 
116
118
  if observation_contains_code(resource, '8867-4')
117
- case suite_options[:us_core_version]
118
- when 'us_core_3'
119
+ case us_core_version
120
+ when US_CORE_3
119
121
  return extract_profile('Heartrate')
120
122
  else
121
123
  return extract_profile('HeartRate')
@@ -123,31 +125,37 @@ module ONCCertificationG10TestKit
123
125
  end
124
126
 
125
127
  if observation_contains_code(resource, '9279-1')
126
- case suite_options[:us_core_version]
127
- when 'us_core_3'
128
+ case us_core_version
129
+ when US_CORE_3
128
130
  return extract_profile('Resprate')
129
131
  else
130
132
  return extract_profile('RespiratoryRate')
131
133
  end
132
134
  end
133
135
 
134
- if suite_options[:us_core_version] == 'us_core_5' &&
136
+ if using_us_core_5? &&
135
137
  resource_contains_category(
136
- resource, 'clinical-test', 'http://terminology.hl7.org/CodeSystem/observation-category'
138
+ resource, 'clinical-test', 'http://hl7.org/fhir/us/core/CodeSystem/us-core-observation-category'
137
139
  )
138
140
  return extract_profile('ObservationClinicalTest')
139
141
  end
140
142
 
141
- if suite_options[:us_core_version] == 'us_core_5' && observation_contains_code(resource, '76690-7')
143
+ if using_us_core_5? && observation_contains_code(resource, '76690-7')
142
144
  return extract_profile('ObservationSexualOrientation')
143
145
  end
144
146
 
145
- if suite_options[:us_core_version] == 'us_core_5' &&
147
+ if using_us_core_5? &&
146
148
  resource_contains_category(resource, 'social-history',
147
149
  'http://terminology.hl7.org/CodeSystem/observation-category')
148
150
  return extract_profile('ObservationSocialHistory')
149
151
  end
150
152
 
153
+ if using_us_core_5? &&
154
+ resource_contains_category(resource, 'imaging',
155
+ 'http://terminology.hl7.org/CodeSystem/observation-category')
156
+ return extract_profile('ObservationImaging')
157
+ end
158
+
151
159
  # We will simply match all Observations of category "survey" to SDOH,
152
160
  # and do not look at the category "sdoh". US Core spec team says that
153
161
  # support for the "sdoh" category is limited, and the validation rules
@@ -159,7 +167,7 @@ module ONCCertificationG10TestKit
159
167
  # `resource_contains_category(resource, 'sdoh',
160
168
  # 'http://terminology.hl7.org/CodeSystem/observation-category') &&`
161
169
  # along with a specific extract_profile('ObservationSurvey') to catch non-sdoh.
162
- if suite_options[:us_core_version] == 'us_core_5' &&
170
+ if using_us_core_5? &&
163
171
  resource_contains_category(resource, 'survey',
164
172
  'http://terminology.hl7.org/CodeSystem/observation-category')
165
173
 
@@ -74,10 +74,9 @@ module ONCCertificationG10TestKit
74
74
  body of the response.
75
75
  )
76
76
  begin
77
+ assert_valid_json(response[:body])
77
78
  parsed_body = JSON.parse(response[:body])
78
79
  assert parsed_body['resourceType'] == 'OperationOutcome', error_message
79
- rescue JSON::ParserError
80
- assert false, error_message
81
80
  end
82
81
  fhir_search(
83
82
  resource_type,
@@ -323,7 +323,7 @@ module ONCCertificationG10TestKit
323
323
  )
324
324
  id :g10_encounter_restricted_access
325
325
 
326
- required_suite_options us_core_version: 'us_core_5'
326
+ required_suite_options G10Options::US_CORE_5_REQUIREMENT
327
327
 
328
328
  def resource_group
329
329
  USCoreTestKit::USCoreV501::EncounterGroup
@@ -343,7 +343,7 @@ module ONCCertificationG10TestKit
343
343
  )
344
344
  id :g10_service_request_restricted_access
345
345
 
346
- required_suite_options us_core_version: 'us_core_5'
346
+ required_suite_options G10Options::US_CORE_5_REQUIREMENT
347
347
 
348
348
  def resource_group
349
349
  USCoreTestKit::USCoreV501::ServiceRequestGroup
@@ -0,0 +1,46 @@
1
+ module ONCCertificationG10TestKit
2
+ # @private
3
+ # This module ensures that short test ids don't change
4
+ module ShortIDManager
5
+ class << self
6
+ def all_children(runnable)
7
+ runnable
8
+ .children
9
+ .flat_map { |child| [child] + all_children(child) }
10
+ end
11
+
12
+ def short_id_file_path
13
+ File.join(__dir__, 'short_id_map.yml')
14
+ end
15
+
16
+ def short_id_map
17
+ @short_id_map ||= YAML.load_file(short_id_file_path)
18
+ end
19
+
20
+ def assign_short_ids
21
+ all_children(G10CertificationSuite).each do |runnable|
22
+ short_id = short_id_map.fetch(runnable.id)
23
+ runnable.define_singleton_method(:short_id) do
24
+ short_id
25
+ end
26
+ rescue KeyError
27
+ Inferno::Application['logger'].warn("No short id defined for #{runnable.id}")
28
+ end
29
+ end
30
+
31
+ ### The methods below are only for creating an initial list of short ids
32
+
33
+ # Run this in an inferno console to save the current short ids
34
+ def save_current_short_id_map
35
+ File.write(short_id_file_path, current_short_id_map.to_yaml)
36
+ end
37
+
38
+ def current_short_id_map
39
+ @current_short_id_map ||=
40
+ all_children(G10CertificationSuite).each_with_object({}) do |runnable, mapping|
41
+ mapping[runnable.id] = runnable.short_id
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end