bulk_data_test_kit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/lib/bulk_data_test_kit/bulk_data_jwks.json +58 -0
  4. data/lib/bulk_data_test_kit/bulk_data_test_kit_properties.rb +20 -0
  5. data/lib/bulk_data_test_kit/bulk_export_validation_tester.rb +214 -0
  6. data/lib/bulk_data_test_kit/export_cancel_tests.rb +43 -0
  7. data/lib/bulk_data_test_kit/export_kick_off_performer.rb +26 -0
  8. data/lib/bulk_data_test_kit/export_operation_tests.rb +171 -0
  9. data/lib/bulk_data_test_kit/export_parameters_tests.rb +49 -0
  10. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_cancel_test.rb +35 -0
  11. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_kick_off_test.rb +37 -0
  12. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_operation_support_test.rb +46 -0
  13. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_tests_test_group.rb +41 -0
  14. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_group_export_test_group.rb +24 -0
  15. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_multiple_patients_test.rb +23 -0
  16. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_ndjson_download_test.rb +33 -0
  17. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_no_auth_test.rb +35 -0
  18. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_output_check_test.rb +45 -0
  19. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_patient_export_test_group.rb +24 -0
  20. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_smart_backend_services_group.rb +21 -0
  21. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_status_check_test.rb +43 -0
  22. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_system_export_test_group.rb +24 -0
  23. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_test_suite.rb +166 -0
  24. data/lib/bulk_data_test_kit/v1.0.1/bulk_data_valid_resources_test.rb +30 -0
  25. data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_cancel_group.rb +32 -0
  26. data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_group.rb +102 -0
  27. data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_validation_group.rb +51 -0
  28. data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_cancel_group.rb +32 -0
  29. data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_group.rb +108 -0
  30. data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_validation_group.rb +63 -0
  31. data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_cancel_group.rb +32 -0
  32. data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_group.rb +108 -0
  33. data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_validation_group.rb +63 -0
  34. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_export_cancel_test.rb +28 -0
  35. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_export_tests_test_group.rb +41 -0
  36. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_group_export_test_group.rb +35 -0
  37. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_outputFormat_param_test.rb +36 -0
  38. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_patient_export_test_group.rb +35 -0
  39. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_since_param_test.rb +48 -0
  40. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_system_export_test_group.rb +35 -0
  41. data/lib/bulk_data_test_kit/v2.0.0/bulk_data_test_suite.rb +165 -0
  42. data/lib/bulk_data_test_kit/v2.0.0/group/bulk_data_group_export_cancel_group.rb +15 -0
  43. data/lib/bulk_data_test_kit/v2.0.0/group/bulk_data_group_export_parameters_group.rb +40 -0
  44. data/lib/bulk_data_test_kit/v2.0.0/patient/bulk_data_patient_export_cancel_group.rb +18 -0
  45. data/lib/bulk_data_test_kit/v2.0.0/patient/bulk_data_patient_export_parameters_group.rb +37 -0
  46. data/lib/bulk_data_test_kit/v2.0.0/system_export/bulk_data_system_export_cancel_group.rb +18 -0
  47. data/lib/bulk_data_test_kit/v2.0.0/system_export/bulk_data_system_export_parameters_group.rb +37 -0
  48. data/lib/bulk_data_test_kit/version.rb +5 -0
  49. data/lib/bulk_data_test_kit.rb +4 -0
  50. metadata +289 -0
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'export_kick_off_performer'
4
+ require_relative 'bulk_data_test_kit_properties'
5
+
6
+ module BulkDataTestKit
7
+ module BulkDataExportOperationTests
8
+ extend Forwardable
9
+
10
+ def_delegators 'self.class', :properties
11
+ def_delegators 'properties',
12
+ :resource_type,
13
+ :bulk_export_url
14
+
15
+ def check_export_support
16
+ fhir_get_capability_statement(client: :bulk_server)
17
+ assert_response_status([200, 201])
18
+
19
+ assert_valid_json(request.response_body)
20
+ capability_statement = FHIR.from_contents(request.response_body)
21
+
22
+ warning do
23
+ has_instantiates = capability_statement&.instantiates&.any? do |canonical|
24
+ canonical.match(%r{^http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data(\|\S+)?$})
25
+ end
26
+ assert has_instantiates,
27
+ 'Server did not declare conformance to the Bulk Data IG by including ' \
28
+ "'http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data' in " \
29
+ "CapabilityStatement.instantiates element (#{capability_statement&.instantiates})"
30
+ end
31
+
32
+ group_resource_capabilities = nil
33
+
34
+ capability_statement&.rest&.each do |rest|
35
+ group_resource_capabilities = if resource_type == 'system'
36
+ rest
37
+ else
38
+ rest.resource&.find do |resource|
39
+ resource.type == resource_type
40
+ end
41
+ end
42
+ end
43
+
44
+ assert group_resource_capabilities.respond_to?(:operation) && group_resource_capabilities.operation&.any?,
45
+ "Server CapabilityStatement did not declare support for any operations on the #{resource_type} resource"
46
+
47
+ has_export_operation = group_resource_capabilities.operation&.any? do |operation|
48
+ name_match = (operation.name == 'export')
49
+ operationDefURL = resource_type == 'system' ? 'export' : "#{resource_type.downcase}-export"
50
+
51
+ if name_match && !operation.definition&.match(%r{^http://hl7.org/fhir/uv/bulkdata/OperationDefinition/#{operationDefURL}(\|\S+)?$})
52
+ info("Server CapabilityStatement does not include export operation with definition http://hl7.org/fhir/uv/bulkdata/OperationDefinition/#{operationDefURL}")
53
+ end
54
+ name_match
55
+ end
56
+ warning do
57
+ assert has_export_operation,
58
+ "Server CapabilityStatement did not declare support for an operation named export in the #{resource_type} " \
59
+ 'resource (operation.name should be export)'
60
+ end
61
+ end
62
+
63
+ def rejects_without_authorization
64
+ skip_if bearer_token.blank?, 'Bearer token is not set and thus not required to connect to server.'
65
+
66
+ url = bulk_export_url.dup
67
+ url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
68
+
69
+ perform_export_kick_off_request(use_token: false, url:)
70
+ assert_response_status([400, 401])
71
+ end
72
+
73
+ def export_kick_off_success
74
+ use_token = !bearer_token.blank?
75
+
76
+ url = bulk_export_url.dup
77
+ url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
78
+
79
+ perform_export_kick_off_request(use_token:, url:)
80
+ assert_response_status(202)
81
+
82
+ polling_url = request.response_header('content-location')&.value
83
+ assert polling_url.present?, 'Export response headers did not include "Content-Location"'
84
+
85
+ polling_url
86
+ end
87
+
88
+ def export_status_check_success(status_polling_url)
89
+ skip 'Server response did not have Content-Location in header' unless status_polling_url.present?
90
+
91
+ timeout = bulk_timeout.to_i
92
+
93
+ if !timeout.positive?
94
+ timeout = 180
95
+ elsif timeout > 600
96
+ timeout = 600
97
+ end
98
+
99
+ wait_time = 1
100
+ start = Time.now
101
+ used_time = 0
102
+
103
+ loop do
104
+ get(status_polling_url, headers: { authorization: "Bearer #{bearer_token}", accept: 'application/json' })
105
+
106
+ retry_after_val = request.response_header('retry-after')&.value.to_i
107
+
108
+ wait_time = retry_after_val.positive? ? retry_after_val : wait_time *= 2
109
+
110
+ used_time = Time.now - start
111
+
112
+ total_time_to_next_poll = Time.now - start + wait_time
113
+
114
+ break if response[:status] != 202 || total_time_to_next_poll > timeout
115
+
116
+ sleep wait_time
117
+ end
118
+
119
+ if response[:status] == 202
120
+ skip "Server already used #{used_time} seconds processing this request, " \
121
+ "and next poll is #{wait_time} seconds after. " \
122
+ "The total wait time for next poll is more than #{timeout} seconds time out setting."
123
+ end
124
+
125
+ assert_response_status(200)
126
+
127
+ assert request.response_header('content-type')&.value&.include?('application/json'),
128
+ 'Content-Type not application/json'
129
+
130
+ assert_valid_json(response[:body])
131
+ response_body = JSON.parse(response[:body])
132
+
133
+ %w[transactionTime request requiresAccessToken output error].each do |key|
134
+ assert response_body.key?(key), "Complete Status response did not contain \"#{key}\" as required"
135
+ end
136
+
137
+ requires_access_token = response_body['requiresAccessToken'].to_s.downcase
138
+ status_response = response[:body]
139
+
140
+ [requires_access_token, status_response]
141
+ end
142
+
143
+ def check_bulk_data_output(export_status_response)
144
+ assert export_status_response.present?, 'Bulk Data Server status response not found'
145
+
146
+ assert_valid_json(export_status_response)
147
+ status_output = JSON.parse(export_status_response)['output']
148
+ assert status_output, 'Bulk Data Server status response does not contain output'
149
+
150
+ skip_if status_output.empty?, 'Bulk Data Server status response does not contain any data in the output'
151
+
152
+ begin
153
+ status_output_json = status_output.to_json
154
+ bulk_download_url = status_output[0]['url']
155
+
156
+ [status_output_json, bulk_download_url]
157
+ ensure
158
+ status_output.each do |file|
159
+ %w[type url].each do |key|
160
+ assert file.key?(key), "Output file did not contain \"#{key}\" as required"
161
+ end
162
+
163
+ if config.options[:require_absolute_urls_in_output]
164
+ assert file['url'].to_s.match?(%r{\Ahttps?://}),
165
+ "URLs in output file must be absolute, but found `#{file['url']}`."
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'export_kick_off_performer'
4
+ require_relative 'bulk_data_test_kit_properties'
5
+
6
+ module BulkDataTestKit
7
+ module BulkDataExportParametersTests
8
+ extend Forwardable
9
+
10
+ def_delegators 'self.class', :properties
11
+ def_delegators 'properties',
12
+ :resource_type,
13
+ :bulk_export_url
14
+
15
+ def perform_outputFormat_param_test
16
+ url = bulk_export_url.dup
17
+ url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
18
+
19
+ ['application/fhir+ndjson', 'application/ndjson', 'ndjson'].each do |format|
20
+ kickoff_url = url.dup
21
+ perform_export_kick_off_request(params: { _outputFormat: format }, url: kickoff_url)
22
+ assert_response_status(202)
23
+
24
+ delete_export_kick_off_request
25
+ end
26
+ end
27
+
28
+ def perform_since_param_test(since_timestamp_param)
29
+ fhir_instant_regex = /
30
+ ([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)
31
+ -(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])
32
+ T([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)
33
+ ?(Z|(\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00))
34
+ /x
35
+
36
+ url = bulk_export_url.dup
37
+ url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
38
+
39
+ assert since_timestamp_param.match?(fhir_instant_regex),
40
+ "The provided `_since` timestamp `#{since_timestamp_param}` is not a valid " \
41
+ '[FHIR instant](https://www.hl7.org/fhir/datatypes.html#instant).'
42
+
43
+ perform_export_kick_off_request(params: { _since: since_timestamp_param }, url:)
44
+ assert_response_status(202)
45
+
46
+ delete_export_kick_off_request
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_cancel_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataExportCancelTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportCancelTests
9
+ include BulkDataTestKit::ExportKickOffPerformer
10
+
11
+ id :bulk_data_export_cancel
12
+
13
+ title 'Bulk Data Server returns "202 Accepted" for delete request'
14
+ description <<~DESCRIPTION
15
+ After a bulk data request has been started, a client MAY send a delete request to the URL provided in the Content-Location header to cancel the request.
16
+ Bulk Data Server MUST support client's delete request and return HTTP Status Code of "202 Accepted"
17
+ DESCRIPTION
18
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#bulk-data-delete-request'
19
+
20
+ output :cancelled_polling_url
21
+
22
+ def self.properties
23
+ @properties ||= BulkDataTestKitProperties.new(
24
+ resource_type: config.options[:resource_type],
25
+ bulk_export_url: config.options[:bulk_export_url]
26
+ )
27
+ end
28
+
29
+ run do
30
+ cancelled_polling_url = perform_export_cancel_test
31
+ output cancelled_polling_url:
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_operation_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataKickOffTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportOperationTests
9
+ include BulkDataTestKit::ExportKickOffPerformer
10
+
11
+ id :bulk_data_kick_off
12
+
13
+ title 'Bulk Data Server returns "202 Accepted" and "Content-location" for bulk data $export operations'
14
+ description <<~DESCRIPTION
15
+ Response - Success
16
+
17
+ * HTTP Status Code of 202 Accepted
18
+ * Content-Location header with the absolute URL of an endpoint for subsequent status requests (polling location)
19
+ DESCRIPTION
20
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#response---success'
21
+
22
+ output :polling_url
23
+
24
+ def self.properties
25
+ @properties ||= BulkDataTestKitProperties.new(
26
+ resource_type: config.options[:resource_type],
27
+ bulk_export_url: config.options[:bulk_export_url]
28
+ )
29
+ end
30
+
31
+ run do
32
+ polling_url = export_kick_off_success
33
+ output polling_url:
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_operation_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataExportOperationSupportTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportOperationTests
9
+
10
+ id :bulk_data_export_operation_support
11
+ title 'Bulk Data Server declares support for particular bulk data export operation in CapabilityStatement'
12
+ description <<~DESCRIPTION
13
+ This test verifies that the Bulk Data Server declares support for
14
+ a particular bulk data operation in its server CapabilityStatement.
15
+
16
+ Given flexibility in the FHIR specification for declaring constrained
17
+ OperationDefinitions, this test only verifies that the server declares
18
+ any operation for the specific resource in the CapabilityStatement. It does not verify that it
19
+ declares the standard bulk data export OperationDefinition provided in the
20
+ Bulk Data specification, nor does it attempt to resolve any non-standard
21
+ OperationDefinitions to verify if it is a constrained version of the
22
+ standard OperationDefintion.
23
+
24
+ This test will provide a warning if no operations are declared via the
25
+ `CapabilityStatement.rest.resource.operation.name` element. It will
26
+ also provide an informational message if an operation on the particular
27
+ resource exists, but does not point to the standard OperationDefinition
28
+ canonical URL.
29
+
30
+ Additionally, this test provides a warning if the bulk data server does
31
+ not include the following URL in its `CapabilityStatement.instantiates`
32
+ element: http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data
33
+ DESCRIPTION
34
+
35
+ def self.properties
36
+ @properties ||= BulkDataTestKitProperties.new(
37
+ resource_type: config.options[:resource_type]
38
+ )
39
+ end
40
+
41
+ run do
42
+ check_export_support
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bulk_data_group_export_test_group'
4
+ require_relative 'bulk_data_patient_export_test_group'
5
+ require_relative 'bulk_data_system_export_test_group'
6
+
7
+ module BulkDataTestKit
8
+ module BulkDataV101
9
+ class BulkDataSmartBackendServicesGroupV101 < Inferno::TestGroup
10
+ id :bulk_data_export_tests_v101
11
+ title 'Bulk Data Export Tests'
12
+
13
+ group do
14
+ id :bulk_data_server_tests
15
+ title 'Bulk Data Server TLS Tests'
16
+ run_as_group
17
+
18
+ test from: :tls_version_test do
19
+ title 'Bulk Data Server is secured by transport layer security'
20
+ description <<~DESCRIPTION
21
+ [§170.315(g)(10) Test
22
+ Procedure](https://www.healthit.gov/test-method/standardized-api-patient-and-population-services)
23
+ requires that all exchanges described herein between a client and a
24
+ server SHALL be secured using Transport Layer Security (TLS) Protocol
25
+ Version 1.2 (RFC5246).
26
+ DESCRIPTION
27
+ id :bulk_data_server_tls_version
28
+
29
+ config(
30
+ inputs: { url: { name: :bulk_server_url } },
31
+ options: { minimum_allowed_version: OpenSSL::SSL::TLS1_2_VERSION }
32
+ )
33
+ end
34
+ end
35
+
36
+ group from: :bulk_data_group_export_v101
37
+ group from: :bulk_data_patient_export_v101
38
+ group from: :bulk_data_system_export_v101
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'group/bulk_data_group_export_group'
4
+ require_relative 'group/bulk_data_group_export_cancel_group'
5
+ require_relative 'group/bulk_data_group_export_validation_group'
6
+
7
+ module BulkDataTestKit
8
+ module BulkDataV101
9
+ class BulkDataGroupTestGroup < Inferno::TestGroup
10
+ title 'Bulk Data Group API Tests'
11
+ id :bulk_data_group_export_v101
12
+ run_as_group
13
+
14
+ description %(
15
+ The Bulk Data Access API Tests evaluate the ability of a system (Bulk Data Server)
16
+ to support required Bulk Data Group $export operation.
17
+ )
18
+
19
+ group from: :bulk_data_group_export_group
20
+ group from: :bulk_data_group_export_validation
21
+ group from: :bulk_data_group_export_cancel_group
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../bulk_export_validation_tester'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataMultiplePatientsTest < Inferno::Test
8
+ include BulkDataTestKit::BulkExportValidationTester
9
+
10
+ id :bulk_data_multiple_patients
11
+
12
+ title 'Export has at least two patients'
13
+ description <<~DESCRIPTION
14
+ This test verifies that the bulk data export has at least two patients.
15
+ DESCRIPTION
16
+ # link 'http://ndjson.org/'
17
+
18
+ run do
19
+ export_multiple_patients_check
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../bulk_export_validation_tester'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataNDJSONDownloadTest < Inferno::Test
8
+ include BulkDataTestKit::BulkExportValidationTester
9
+
10
+ id :bulk_data_ndjson_download
11
+
12
+ title 'NDJSON download requires access token if requireAccessToken is true'
13
+ description <<~DESCRIPTION
14
+ If the requiresAccessToken field in the Complete Status body is set to true, the request SHALL include a valid#{' '}
15
+ access token.
16
+
17
+ [FHIR R4 Security](https://www.hl7.org/fhir/security.html#AccessDenied) and
18
+ [The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750#section-3.1)
19
+ recommend using HTTP status code 401 for invalid token but also allow the actual result be controlled by policy#{' '}
20
+ and context.
21
+ DESCRIPTION
22
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#file-request'
23
+
24
+ input :bulk_download_url
25
+ input :requires_access_token
26
+
27
+ run do
28
+ ndjson_download_requiresAccessToken_check(bulk_data_download_url: bulk_download_url,
29
+ bulk_requires_access_token: requires_access_token)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_operation_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataExportNoAuthRejectTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportOperationTests
9
+ include BulkDataTestKit::ExportKickOffPerformer
10
+
11
+ id :bulk_data_no_auth_reject
12
+
13
+ title 'Bulk Data Server rejects $export request without authorization'
14
+ description <<~DESCRIPTION
15
+ The FHIR server SHALL limit the data returned to only those FHIR resources for which the client is authorized.
16
+
17
+ [FHIR R4 Security](https://www.hl7.org/fhir/security.html#AccessDenied) and
18
+ [The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750#section-3.1)
19
+ recommend using HTTP status code 401 for invalid token but also allow the actual result be controlled by policy and context.
20
+ DESCRIPTION
21
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#bulk-data-kick-off-request'
22
+
23
+ def self.properties
24
+ @properties ||= BulkDataTestKitProperties.new(
25
+ resource_type: config.options[:resource_type],
26
+ bulk_export_url: config.options[:bulk_export_url]
27
+ )
28
+ end
29
+
30
+ run do
31
+ rejects_without_authorization
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_operation_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataOutputCheckTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportOperationTests
9
+
10
+ id :bulk_data_output_check
11
+
12
+ title 'Bulk Data Server returns output with type and url for status complete'
13
+ description <<~DESCRIPTION
14
+ The value of output field is an array of file items with one entry for each generated file.
15
+ If no resources are returned from the kick-off request, the server SHOULD return an empty array.
16
+
17
+ Each file item SHALL contain the following fields:
18
+
19
+ * type - the FHIR resource type that is contained in the file.
20
+
21
+ Each file SHALL contain resources of only one type, but a server MAY create more than one file for each resource type returned.
22
+
23
+ * url - the path to the file. The format of the file SHOULD reflect that requested in the _outputFormat parameter of the initial kick-off request.
24
+ DESCRIPTION
25
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#response---complete-status'
26
+
27
+ input :status_response
28
+
29
+ output :status_output, :bulk_download_url
30
+
31
+ def self.properties
32
+ @properties ||= BulkDataTestKitProperties.new(
33
+ resource_type: config.options[:resource_type]
34
+ )
35
+ end
36
+
37
+ run do
38
+ status_output, bulk_download_url = check_bulk_data_output(status_response)
39
+
40
+ output status_output:,
41
+ bulk_download_url:
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'patient/bulk_data_patient_export_group'
4
+ require_relative 'patient/bulk_data_patient_export_cancel_group'
5
+ require_relative 'patient/bulk_data_patient_export_validation_group'
6
+
7
+ module BulkDataTestKit
8
+ module BulkDataV101
9
+ class BulkDataPatientTestGroup < Inferno::TestGroup
10
+ title 'Bulk Data Patient API Tests'
11
+ id :bulk_data_patient_export_v101
12
+ run_as_group
13
+
14
+ description %(
15
+ The Bulk Data Access API Tests evaluate the ability of a system (Bulk Data Server)
16
+ to support required Bulk Data Patient $export operation.
17
+ )
18
+
19
+ group from: :bulk_data_patient_export_group
20
+ group from: :bulk_data_patient_export_validation
21
+ group from: :bulk_data_patient_export_cancel_group
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smart_app_launch/smart_stu2_suite'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataSmartBackendServicesGroup < Inferno::TestGroup
8
+ title 'SMART Backend Services'
9
+ id :bulk_data_smart_backend_services
10
+ run_as_group
11
+ optional
12
+
13
+ group from: :smart_discovery_stu2,
14
+ config: {
15
+ inputs: { url: { name: :bulk_server_url } }
16
+ }
17
+
18
+ group from: :backend_services_authorization
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../export_operation_tests'
4
+
5
+ module BulkDataTestKit
6
+ module BulkDataV101
7
+ class BulkDataStatusCheckTest < Inferno::Test
8
+ include BulkDataTestKit::BulkDataExportOperationTests
9
+
10
+ id :bulk_data_status_check
11
+
12
+ title 'Bulk Data Server returns "202 Accepted" or "200 OK" for status check'
13
+ description <<~DESCRIPTION
14
+ Clients SHOULD follow an exponential backoff approach when polling for status. Servers SHOULD respond with
15
+
16
+ * In-Progress Status: HTTP Status Code of 202 Accepted
17
+ * Complete Status: HTTP status of 200 OK and Content-Type header of application/json
18
+
19
+ The JSON object of Complete Status SHALL contain these required field:
20
+
21
+ * transactionTime, request, requiresAccessToken, output, and error
22
+ DESCRIPTION
23
+ # link 'http://hl7.org/fhir/uv/bulkdata/STU1.0.1/export/index.html#bulk-data-status-request'
24
+
25
+ input :polling_url
26
+
27
+ output :status_response, :requires_access_token
28
+
29
+ def self.properties
30
+ @properties ||= BulkDataTestKitProperties.new(
31
+ resource_type: config.options[:resource_type]
32
+ )
33
+ end
34
+
35
+ run do
36
+ requires_access_token, status_response = export_status_check_success(polling_url)
37
+
38
+ output(requires_access_token:)
39
+ output status_response:
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'system_export/bulk_data_system_export_group'
4
+ require_relative 'system_export/bulk_data_system_export_cancel_group'
5
+ require_relative 'system_export/bulk_data_system_export_validation_group'
6
+
7
+ module BulkDataTestKit
8
+ module BulkDataV101
9
+ class BulkDataSystemExportTestGroup < Inferno::TestGroup
10
+ title 'Bulk Data System Level Export API Tests'
11
+ id :bulk_data_system_export_v101
12
+ run_as_group
13
+
14
+ description %(
15
+ The Bulk Data Access API Tests evaluate the ability of a system (Bulk Data Server)
16
+ to support required Bulk Data system $export operation.
17
+ )
18
+
19
+ group from: :bulk_data_system_export_group
20
+ group from: :bulk_data_system_export_validation
21
+ group from: :bulk_data_system_export_cancel_group
22
+ end
23
+ end
24
+ end