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.
- checksums.yaml +4 -4
- data/lib/inferno/terminology/expected_manifest.yml +36 -693
- data/lib/inferno/terminology/fhir_package_manager.rb +16 -14
- data/lib/inferno/terminology/loader.rb +25 -3
- data/lib/inferno/terminology/tasks/create_value_set_validators.rb +3 -3
- data/lib/inferno/terminology/tasks/download_umls.rb +3 -2
- data/lib/inferno/terminology/tasks/expand_value_set_to_file.rb +1 -1
- data/lib/inferno/terminology/tasks/run_umls_jar.rb +2 -1
- data/lib/inferno/terminology/tasks/validate_code.rb +1 -1
- data/lib/inferno/terminology/terminology_validation.rb +1 -1
- data/lib/inferno/terminology/validator.rb +9 -9
- data/lib/inferno/terminology/value_set.rb +65 -63
- data/lib/onc_certification_g10_test_kit/authorization_request_builder.rb +2 -2
- data/lib/onc_certification_g10_test_kit/bulk_data_authorization.rb +4 -4
- data/lib/onc_certification_g10_test_kit/bulk_data_group_export_stu1.rb +3 -1
- data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +7 -4
- data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +5 -14
- data/lib/onc_certification_g10_test_kit/configuration_checker.rb +23 -1
- data/lib/onc_certification_g10_test_kit/export_kick_off_performer.rb +2 -2
- data/lib/onc_certification_g10_test_kit/g10_options.rb +46 -0
- data/lib/onc_certification_g10_test_kit/incorrectly_permitted_tls_versions_messages_setup_test.rb +34 -0
- data/lib/onc_certification_g10_test_kit/limited_scope_grant_test.rb +3 -1
- data/lib/onc_certification_g10_test_kit/multi_patient_api_stu1.rb +11 -0
- data/lib/onc_certification_g10_test_kit/multi_patient_api_stu2.rb +10 -0
- data/lib/onc_certification_g10_test_kit/onc_program_procedure.yml +1 -0
- data/lib/onc_certification_g10_test_kit/patient_scope_test.rb +25 -0
- data/lib/onc_certification_g10_test_kit/profile_selector.rb +33 -25
- data/lib/onc_certification_g10_test_kit/resource_access_test.rb +1 -2
- data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +2 -2
- data/lib/onc_certification_g10_test_kit/short_id_manager.rb +46 -0
- data/lib/onc_certification_g10_test_kit/short_id_map.yml +1538 -0
- data/lib/onc_certification_g10_test_kit/single_patient_api_group.rb +4 -0
- data/lib/onc_certification_g10_test_kit/single_patient_us_core_4_api_group.rb +4 -0
- data/lib/onc_certification_g10_test_kit/single_patient_us_core_5_api_group.rb +4 -0
- data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +2 -2
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group.rb +27 -4
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group_stu2.rb +27 -4
- data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +58 -7
- data/lib/onc_certification_g10_test_kit/smart_invalid_pkce_group.rb +1 -1
- data/lib/onc_certification_g10_test_kit/smart_invalid_token_group.rb +1 -1
- data/lib/onc_certification_g10_test_kit/smart_invalid_token_group_stu2.rb +1 -1
- data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +3 -2
- data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +4 -2
- data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +57 -6
- data/lib/onc_certification_g10_test_kit/tasks/test_procedure.rb +1 -1
- data/lib/onc_certification_g10_test_kit/terminology_binding_validator.rb +1 -1
- data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +7 -4
- data/lib/onc_certification_g10_test_kit/version.rb +1 -1
- data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +52 -2
- data/lib/onc_certification_g10_test_kit/well_known_capabilities_test.rb +3 -1
- data/lib/onc_certification_g10_test_kit.rb +41 -23
- 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
|
data/lib/onc_certification_g10_test_kit/incorrectly_permitted_tls_versions_messages_setup_test.rb
ADDED
@@ -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
|
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
|
@@ -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
|
32
|
-
when
|
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
|
60
|
-
when
|
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') &&
|
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') &&
|
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
|
82
|
-
when
|
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
|
91
|
-
when
|
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
|
100
|
-
when
|
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
|
109
|
-
when
|
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
|
118
|
-
when
|
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
|
127
|
-
when
|
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
|
136
|
+
if using_us_core_5? &&
|
135
137
|
resource_contains_category(
|
136
|
-
resource, 'clinical-test', 'http://
|
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
|
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
|
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
|
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
|
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
|
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
|