bulk_data_test_kit 0.9.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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/lib/bulk_data_test_kit/bulk_data_jwks.json +58 -0
- data/lib/bulk_data_test_kit/bulk_data_test_kit_properties.rb +20 -0
- data/lib/bulk_data_test_kit/bulk_export_validation_tester.rb +214 -0
- data/lib/bulk_data_test_kit/export_cancel_tests.rb +43 -0
- data/lib/bulk_data_test_kit/export_kick_off_performer.rb +26 -0
- data/lib/bulk_data_test_kit/export_operation_tests.rb +171 -0
- data/lib/bulk_data_test_kit/export_parameters_tests.rb +49 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_cancel_test.rb +35 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_kick_off_test.rb +37 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_operation_support_test.rb +46 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_export_tests_test_group.rb +41 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_group_export_test_group.rb +24 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_multiple_patients_test.rb +23 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_ndjson_download_test.rb +33 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_no_auth_test.rb +35 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_output_check_test.rb +45 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_patient_export_test_group.rb +24 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_smart_backend_services_group.rb +21 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_status_check_test.rb +43 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_system_export_test_group.rb +24 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_test_suite.rb +166 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_valid_resources_test.rb +30 -0
- data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_cancel_group.rb +32 -0
- data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_group.rb +102 -0
- data/lib/bulk_data_test_kit/v1.0.1/group/bulk_data_group_export_validation_group.rb +51 -0
- data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_cancel_group.rb +32 -0
- data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_group.rb +108 -0
- data/lib/bulk_data_test_kit/v1.0.1/patient/bulk_data_patient_export_validation_group.rb +63 -0
- data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_cancel_group.rb +32 -0
- data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_group.rb +108 -0
- data/lib/bulk_data_test_kit/v1.0.1/system_export/bulk_data_system_export_validation_group.rb +63 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_export_cancel_test.rb +28 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_export_tests_test_group.rb +41 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_group_export_test_group.rb +35 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_outputFormat_param_test.rb +36 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_patient_export_test_group.rb +35 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_since_param_test.rb +48 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_system_export_test_group.rb +35 -0
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_test_suite.rb +165 -0
- data/lib/bulk_data_test_kit/v2.0.0/group/bulk_data_group_export_cancel_group.rb +15 -0
- data/lib/bulk_data_test_kit/v2.0.0/group/bulk_data_group_export_parameters_group.rb +40 -0
- data/lib/bulk_data_test_kit/v2.0.0/patient/bulk_data_patient_export_cancel_group.rb +18 -0
- data/lib/bulk_data_test_kit/v2.0.0/patient/bulk_data_patient_export_parameters_group.rb +37 -0
- data/lib/bulk_data_test_kit/v2.0.0/system_export/bulk_data_system_export_cancel_group.rb +18 -0
- data/lib/bulk_data_test_kit/v2.0.0/system_export/bulk_data_system_export_parameters_group.rb +37 -0
- data/lib/bulk_data_test_kit/version.rb +5 -0
- data/lib/bulk_data_test_kit.rb +4 -0
- 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
|