onc_certification_g10_test_kit 3.1.0 → 3.3.0

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 (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