onc_certification_g10_test_kit 2.0.0 → 2.1.0.rc1

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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno/terminology/tasks/check_built_terminology.rb +14 -12
  3. data/lib/onc_certification_g10_test_kit/bulk_data_authorization.rb +7 -4
  4. data/lib/onc_certification_g10_test_kit/bulk_data_group_export.rb +60 -17
  5. data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +10 -6
  6. data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +37 -16
  7. data/lib/onc_certification_g10_test_kit/configuration_checker.rb +6 -5
  8. data/lib/onc_certification_g10_test_kit/multi_patient_api.rb +11 -0
  9. data/lib/onc_certification_g10_test_kit/onc_program_procedure.yml +1451 -0
  10. data/lib/onc_certification_g10_test_kit/profile_guesser.rb +2 -2
  11. data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +13 -13
  12. data/lib/onc_certification_g10_test_kit/single_patient_api_group.rb +89 -0
  13. data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +13 -12
  14. data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +11 -5
  15. data/lib/onc_certification_g10_test_kit/smart_invalid_launch_group.rb +13 -16
  16. data/lib/onc_certification_g10_test_kit/smart_invalid_token_group.rb +11 -4
  17. data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +18 -4
  18. data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group.rb +15 -3
  19. data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +8 -3
  20. data/lib/onc_certification_g10_test_kit/tasks/generate_matrix.rb +243 -0
  21. data/lib/onc_certification_g10_test_kit/tasks/test_procedure.rb +65 -0
  22. data/lib/onc_certification_g10_test_kit/token_revocation_group.rb +60 -60
  23. data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +13 -13
  24. data/lib/onc_certification_g10_test_kit/version.rb +1 -1
  25. data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +7 -6
  26. data/lib/onc_certification_g10_test_kit.rb +15 -82
  27. metadata +16 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76c238a8340939555c2dd9b3450dc05a2d00cfa2f2da7e95c8d573e6e15bdfc9
4
- data.tar.gz: 3b86e20c0f6b4e5039f9e50ee63cdc7dddd6968723cb02d2e05556add8c52f98
3
+ metadata.gz: 136583ee432ecaa86193ce86c3e09ba9c3fd69cd745d6663243a8fc4b0ab2071
4
+ data.tar.gz: b914f640ba8c3c577d1d531952944027fec53582f6faa22efedbb62d5fe018a7
5
5
  SHA512:
6
- metadata.gz: cfd506cb46b30d272ca38c7e8cce955a1c2e3216c5b06f398ccc19f50137791b50fd36704eb7b010cc8c8fccc5923bf8ea4e82ae544409f58fbbd3975a860a75
7
- data.tar.gz: 1f75ae0d2285fea70386f16a8f49a4ad7c255d5436470978de68b8012245059191b16e0799d915ead8061b1327bbb943f98d7c5110a6636bca1215b54e0cfd37
6
+ metadata.gz: 6e0b7538709edc9dc43a3069197df5550ba403193d12dea576851fba09b472679c3475f9d47e3d3f6496d6c8dd35c20981fe46f968824919b1dce7e3ae4c0032
7
+ data.tar.gz: 18ad6fce7e21583ef641a74765a58ffdccc559a5a8b70038330368c6bbafe29584a5204cc36bbc1bb62122aea2b89c321b9fa76865ccd768355e6df7e03f091a
@@ -4,9 +4,11 @@ module Inferno
4
4
  module Terminology
5
5
  module Tasks
6
6
  class CheckBuiltTerminology
7
- MIME_TYPE_SYSTEMS = [
7
+ NON_UMLS_SYSTEMS = [
8
8
  'http://hl7.org/fhir/ValueSet/mimetypes',
9
- 'urn:ietf:bcp:13'
9
+ 'urn:ietf:bcp:13',
10
+ 'http://hl7.org/fhir/us/core/ValueSet/simple-language',
11
+ 'urn:ietf:bcp:47'
10
12
  ].freeze
11
13
 
12
14
  def run
@@ -15,16 +17,16 @@ module Inferno
15
17
  return
16
18
  end
17
19
 
18
- if only_mime_types_mismatch?
19
- Inferno.logger.info <<~MIME
20
+ if only_non_umls_mismatch?
21
+ Inferno.logger.info <<~NON_UMLS
20
22
  Terminology built successfully.
21
23
 
22
- Mime-type based terminology did not match, but this can be a
23
- result of using a newer version of the `mime-types-data` gem and
24
- does not necessarily reflect a problem with the terminology build.
25
- The expected mime-types codes were generated with version
26
- `mime-types-data` version `3.2021.0901`.
27
- MIME
24
+ Some terminology not based on UMLS did not match, but this can be
25
+ a result of these terminologies having a different update schedule
26
+ than UMLS. As long as the actual number of codes is close to the
27
+ expected number, this does not does not reflect a problem with the
28
+ terminology build.
29
+ NON_UMLS
28
30
  else
29
31
  Inferno.logger.info 'Terminology build results different than expected.'
30
32
  end
@@ -61,8 +63,8 @@ module Inferno
61
63
  new_manifest.find { |value_set| value_set[:url] == url }
62
64
  end
63
65
 
64
- def only_mime_types_mismatch?
65
- mismatched_value_sets.all? { |value_set| MIME_TYPE_SYSTEMS.include? value_set[:url] }
66
+ def only_non_umls_mismatch?
67
+ mismatched_value_sets.all? { |value_set| NON_UMLS_SYSTEMS.include? value_set[:url] }
66
68
  end
67
69
 
68
70
  def mismatched_value_set_message(expected_value_set)
@@ -21,8 +21,9 @@ module ONCCertificationG10TestKit
21
21
 
22
22
  input :bulk_token_endpoint,
23
23
  title: 'Backend Services Token Endpoint',
24
- description: 'The OAuth 2.0 Token Endpoint used by the Backend Services specification
25
- to provide bearer tokens.'
24
+ description: <<~DESCRIPTION
25
+ The OAuth 2.0 Token Endpoint used by the Backend Services specification to provide bearer tokens.
26
+ DESCRIPTION
26
27
  input :bulk_client_id,
27
28
  title: 'Bulk Data Client ID',
28
29
  description: 'Client ID provided at registration to the Inferno application.'
@@ -32,8 +33,10 @@ module ONCCertificationG10TestKit
32
33
  default: 'system/*.read'
33
34
  input :bulk_encryption_method,
34
35
  title: 'Encryption Method',
35
- description: 'The server is required to suport either ES384 or RS384 encryption methods
36
- for JWT signature verification. Select which method to use.',
36
+ description: <<~DESCRIPTION,
37
+ The server is required to suport either ES384 or RS384 encryption methods for JWT signature verification.
38
+ Select which method to use.
39
+ DESCRIPTION
37
40
  type: 'radio',
38
41
  default: 'ES384',
39
42
  options: {
@@ -19,11 +19,12 @@ module ONCCertificationG10TestKit
19
19
  description: 'The Group ID associated with the group of patients to be exported.'
20
20
  input :bulk_timeout,
21
21
  title: 'Export Times Out after (1-600)',
22
- description: 'While testing, Inferno waits for the server to complete the exporting task.
23
- If the calculated totalTime is greater than the timeout value specified here,
24
- Inferno bulk client stops testing. Please enter an integer for the maximum wait time in seconds.
25
- If timeout is less than 1, Inferno uses default value 180.
26
- If the timeout is greater than 600 (10 minutes), Inferno uses the maximum value 600.',
22
+ description: <<~DESCRIPTION,
23
+ While testing, Inferno waits for the server to complete the exporting task. If the calculated totalTime is
24
+ greater than the timeout value specified here, Inferno bulk client stops testing. Please enter an integer
25
+ for the maximum wait time in seconds. If timeout is less than 1, Inferno uses default value 180. If the
26
+ timeout is greater than 600 (10 minutes), Inferno uses the maximum value 600.
27
+ DESCRIPTION
27
28
  default: 180
28
29
 
29
30
  output :requires_access_token, :status_output, :bulk_download_url
@@ -56,9 +57,30 @@ module ONCCertificationG10TestKit
56
57
  test do
57
58
  title 'Bulk Data Server declares support for Group export operation in CapabilityStatement'
58
59
  description <<~DESCRIPTION
59
- The Bulk Data Server SHALL declare support for Group/[id]/$export operation in its server CapabilityStatement
60
+ This test verifies that the Bulk Data Server declares support for
61
+ Group/[id]/$export operation in its server CapabilityStatement.
62
+
63
+ Given flexibility in the FHIR specification for declaring constrained
64
+ OperationDefinitions, this test only verifies that the server declares
65
+ any operation on the Group resource. It does not verify that it
66
+ declares the standard group export OperationDefinition provided in the
67
+ Bulk Data specification, nor does it attempt to resolve any non-standard
68
+ OperationDefinitions to verify if it is a constrained version of the
69
+ standard OperationDefintion.
70
+
71
+ This test will provide a warning if no operations are declared at
72
+ `Group/[id]/$export`, via the
73
+ `CapabilityStatement.rest.resource.operation.name` element. It will
74
+ also provide an informational message if an operation on the Group
75
+ resource exists, but does not point to the standard OperationDefinition
76
+ canonical URL:
77
+ http://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export
78
+
79
+ Additionally, this test provides a warning if the bulk data server does
80
+ not include the following URL in its `CapabilityStatement.instantiates`
81
+ element: http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data
82
+
60
83
  DESCRIPTION
61
- # link 'http://hl7.org/fhir/uv/bulkdata/STU1/OperationDefinition-group-export.html'
62
84
 
63
85
  run do
64
86
  fhir_get_capability_statement(client: :bulk_server)
@@ -67,18 +89,39 @@ module ONCCertificationG10TestKit
67
89
  assert_valid_json(request.response_body)
68
90
  capability_statement = FHIR.from_contents(request.response_body)
69
91
 
70
- has_export_operation = capability_statement&.rest&.any? do |rest|
71
- rest.resource&.any? do |resource|
72
- resource.type == 'Group' &&
73
- resource.respond_to?(:operation) &&
74
- resource.operation&.find do |operation|
75
- operation.definition&.match(%r{^http://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export(\|\S+)?})
76
- end
92
+ warning do
93
+ has_instantiates = capability_statement&.instantiates&.any? do |canonical|
94
+ canonical.match(%r{^http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data(\|\S+)?$})
95
+ end
96
+ assert has_instantiates,
97
+ 'Server did not declare conformance to the Bulk Data IG by including ' \
98
+ "'http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data' in " \
99
+ " CapabilityStatement.instantiates element (#{capability_statement&.instantiates})"
100
+ end
101
+
102
+ group_resource_capabilities = nil
103
+
104
+ capability_statement&.rest&.each do |rest|
105
+ group_resource_capabilities = rest.resource&.find do |resource|
106
+ resource.type == 'Group'
77
107
  end
78
108
  end
79
109
 
80
- assert has_export_operation,
81
- 'Server CapabilityStatement did not declare support for export operation in Group resource'
110
+ assert group_resource_capabilities.respond_to?(:operation) && group_resource_capabilities.operation&.any?,
111
+ 'Server CapabilityStatement did not declare support for any operations on the Group resource'
112
+
113
+ has_export_operation = group_resource_capabilities.operation&.any? do |operation|
114
+ name_match = (operation.name == 'export')
115
+ if name_match && !operation.definition&.match(%r{^http://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export(\|\S+)?$})
116
+ info('Server CapabilityStatement does not include export operation with definition http://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export')
117
+ end
118
+ name_match
119
+ end
120
+ warning do
121
+ assert has_export_operation,
122
+ 'Server CapabilityStatement did not declare support for an operation named "export" in the Group ' \
123
+ ' resource (operation.name should be "export")'
124
+ end
82
125
  end
83
126
  end
84
127
 
@@ -161,7 +204,7 @@ module ONCCertificationG10TestKit
161
204
  start = Time.now
162
205
 
163
206
  loop do
164
- get(polling_url, headers: { authorization: "Bearer #{bearer_token}" })
207
+ get(polling_url, headers: { authorization: "Bearer #{bearer_token}", accept: 'application/json' })
165
208
 
166
209
  retry_after_val = request.response_header('retry-after')&.value.to_i
167
210
 
@@ -17,14 +17,18 @@ module ONCCertificationG10TestKit
17
17
  optional: true
18
18
  input :bulk_patient_ids_in_group,
19
19
  title: 'Patient IDs in exported Group',
20
- description: 'Comma separated list of every Patient ID that is in the specified Group. This information is
21
- provided by the system under test to verify that data returned matches expectations. Leave blank to not
22
- verify Group inclusion.'
20
+ description: <<~DESCRIPTION
21
+ Comma separated list of every Patient ID that is in the specified Group. This information is provided by
22
+ the system under test to verify that data returned matches expectations. Leave blank to not verify Group
23
+ inclusion.
24
+ DESCRIPTION
23
25
  input :bulk_device_types_in_group,
24
26
  title: 'Implantable Device Type Codes in exported Group',
25
- description: 'Comma separated list of every Implantable Device type that is in the specified Group. This
26
- information is provided by the system under test to verify that data returned matches expectations. Leave
27
- blank to verify all Device resources against the Implantable Device profile.',
27
+ description: <<~DESCRIPTION,
28
+ Comma separated list of every Implantable Device type that is in the specified Group. This information is
29
+ provided by the system under test to verify that data returned matches expectations. Leave blank to verify
30
+ all Device resources against the Implantable Device profile.
31
+ DESCRIPTION
28
32
  optional: true
29
33
 
30
34
  test from: :tls_version_test do
@@ -13,23 +13,26 @@ module ONCCertificationG10TestKit
13
13
 
14
14
  def observation_metadata
15
15
  [
16
- USCoreTestKit::PediatricBmiForAgeGroup.metadata,
17
- USCoreTestKit::PediatricWeightForHeightGroup.metadata,
18
- USCoreTestKit::ObservationLabGroup.metadata,
19
- USCoreTestKit::PulseOximetryGroup.metadata,
20
- USCoreTestKit::SmokingstatusGroup.metadata,
21
- USCoreTestKit::HeadCircumferenceGroup.metadata,
22
- USCoreTestKit::BpGroup.metadata,
23
- USCoreTestKit::BodyheightGroup.metadata,
24
- USCoreTestKit::BodytempGroup.metadata,
25
- USCoreTestKit::BodyweightGroup.metadata,
26
- USCoreTestKit::HeartrateGroup.metadata,
27
- USCoreTestKit::ResprateGroup.metadata
16
+ USCoreTestKit::USCoreV311::PediatricBmiForAgeGroup.metadata,
17
+ USCoreTestKit::USCoreV311::PediatricWeightForHeightGroup.metadata,
18
+ USCoreTestKit::USCoreV311::ObservationLabGroup.metadata,
19
+ USCoreTestKit::USCoreV311::PulseOximetryGroup.metadata,
20
+ USCoreTestKit::USCoreV311::SmokingstatusGroup.metadata,
21
+ USCoreTestKit::USCoreV311::HeadCircumferenceGroup.metadata,
22
+ USCoreTestKit::USCoreV311::BpGroup.metadata,
23
+ USCoreTestKit::USCoreV311::BodyheightGroup.metadata,
24
+ USCoreTestKit::USCoreV311::BodytempGroup.metadata,
25
+ USCoreTestKit::USCoreV311::BodyweightGroup.metadata,
26
+ USCoreTestKit::USCoreV311::HeartrateGroup.metadata,
27
+ USCoreTestKit::USCoreV311::ResprateGroup.metadata
28
28
  ]
29
29
  end
30
30
 
31
31
  def diagnostic_metadata
32
- [USCoreTestKit::DiagnosticReportLabGroup.metadata, USCoreTestKit::DiagnosticReportNoteGroup.metadata]
32
+ [
33
+ USCoreTestKit::USCoreV311::DiagnosticReportLabGroup.metadata,
34
+ USCoreTestKit::USCoreV311::DiagnosticReportNoteGroup.metadata
35
+ ]
33
36
  end
34
37
 
35
38
  def determine_metadata
@@ -37,11 +40,11 @@ module ONCCertificationG10TestKit
37
40
  return diagnostic_metadata if resource_type == 'DiagnosticReport'
38
41
 
39
42
  if resource_type == 'Location' || resource_type == 'Medication'
40
- return Array.wrap(USCoreTestKit::USCoreTestSuite.metadata.find do |meta|
43
+ return Array.wrap(USCoreTestKit::USCoreV311::USCoreTestSuite.metadata.find do |meta|
41
44
  meta.resource == resource_type
42
45
  end)
43
46
  end
44
- ["USCoreTestKit::#{resource_type}Group".constantize.metadata]
47
+ ["USCoreTestKit::USCoreV311::#{resource_type}Group".constantize.metadata]
45
48
  end
46
49
 
47
50
  def metadata_list
@@ -58,7 +61,7 @@ module ONCCertificationG10TestKit
58
61
  headers
59
62
  end
60
63
 
61
- def stream_ndjson(endpoint, headers, process_chunk_line, process_response)
64
+ def stream_ndjson(endpoint, headers, process_chunk_line, process_response) # rubocop:disable Metrics/CyclomaticComplexity
62
65
  hanging_chunk = String.new
63
66
 
64
67
  process_body = proc { |chunk|
@@ -74,6 +77,24 @@ module ONCCertificationG10TestKit
74
77
 
75
78
  stream(process_body, endpoint, headers: headers)
76
79
 
80
+ max_redirect = 5
81
+
82
+ while [301, 302, 303, 307].include?(response[:status]) &&
83
+ request.response_header('location')&.value.present? &&
84
+ max_redirect.positive?
85
+
86
+ max_redirect -= 1
87
+
88
+ redirect_url = request.response_header('location')&.value
89
+
90
+ # handle relative redirects
91
+ redirect_url = URI.parse(endpoint).merge(redirect_url).to_s unless redirect_url.start_with?('http')
92
+
93
+ redirect_headers = headers.reject { |key, _value| key == :authorization }
94
+
95
+ stream(process_body, redirect_url, headers: redirect_headers)
96
+ end
97
+
77
98
  process_chunk_line.call(hanging_chunk)
78
99
  process_response.call(response)
79
100
  end
@@ -55,7 +55,7 @@ module ONCCertificationG10TestKit
55
55
  success_messages << "* `#{url}`: #{actual_value_set[:count]} codes"
56
56
  elsif actual_value_set.nil?
57
57
  error_messages << "* `#{url}`: Not loaded"
58
- elsif terminology_checker.class::MIME_TYPE_SYSTEMS.include? url
58
+ elsif terminology_checker.class::NON_UMLS_SYSTEMS.include? url
59
59
  warning_messages <<
60
60
  "* `#{url}`: Expected codes: #{expected_value_set[:count]} Actual codes: #{actual_value_set[:count]}"
61
61
  else
@@ -74,10 +74,11 @@ module ONCCertificationG10TestKit
74
74
 
75
75
  if warning_messages.present?
76
76
  warning_message = <<~WARNING
77
- Mime-type based terminology did not exactly match. This can be the
78
- result of using a slightly different version of the `mime-types-data`
79
- gem and does not reflect a problem with the terminology build as long
80
- as the expected and actual number of codes are close to each other.
77
+ Some terminology not based on UMLS did not match, but this can be a
78
+ result of these terminologies having a different update schedule than
79
+ UMLS. As long as the actual number of codes is close to the expected
80
+ number, this does not does not reflect a problem with the terminology
81
+ build.
81
82
  WARNING
82
83
  messages << {
83
84
  type: 'warning',
@@ -36,6 +36,17 @@ module ONCCertificationG10TestKit
36
36
  id :multi_patient_api
37
37
  run_as_group
38
38
 
39
+ input_order :bulk_server_url,
40
+ :bulk_token_endpoint,
41
+ :bulk_client_id,
42
+ :bulk_scope,
43
+ :bulk_encryption_method,
44
+ :group_id,
45
+ :bulk_patient_ids_in_group,
46
+ :bulk_device_types_in_group,
47
+ :lines_to_validate,
48
+ :bulk_timeout
49
+
39
50
  group from: :bulk_data_authorization
40
51
  group from: :bulk_data_group_export
41
52
  group from: :bulk_data_group_export_validation