bulk_data_test_kit 0.13.2 → 0.14.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 +4 -4
- data/config/presets/bulk_data_v400_submit_consumer_demo.json.erb +65 -0
- data/config/presets/bulk_data_v400_submit_provider_demo.json +22 -0
- data/lib/bulk_data_test_kit/metadata.rb +20 -4
- data/lib/bulk_data_test_kit/requirements/generated/bulk_data_v101_requirements_coverage.csv +1 -1
- data/lib/bulk_data_test_kit/requirements/generated/bulk_data_v200_client_requirements_coverage.csv +1 -1
- data/lib/bulk_data_test_kit/requirements/generated/bulk_data_v200_requirements_coverage.csv +1 -1
- data/lib/bulk_data_test_kit/requirements/generated/bulk_data_v400_submit_consumer_requirements_coverage.csv +18 -0
- data/lib/bulk_data_test_kit/requirements/generated/bulk_data_v400_submit_provider_requirements_coverage.csv +4 -0
- data/lib/bulk_data_test_kit/v1.0.1/bulk_data_test_suite.rb +3 -3
- data/lib/bulk_data_test_kit/v2.0.0/bulk_data_test_suite.rb +3 -3
- data/lib/bulk_data_test_kit/v2.0.0_client/bulk_data_client_test_suite.rb +1 -1
- data/lib/bulk_data_test_kit/v2.0.0_client/docs/suite_description.md +4 -4
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/backend_services_group.rb +50 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/complete_poll_group.rb +105 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/docs/suite_description.md +49 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/endpoints/file_download.rb +39 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/endpoints/manifest.rb +56 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/helpers.rb +78 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/manifest_and_file_retrieval.rb +59 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/poll_group.rb +66 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/processing_wait_group.rb +53 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/status_submit_group.rb +78 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/submit_completed_group.rb +65 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/submit_group.rb +66 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/tags.rb +12 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/test_suite.rb +116 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/consumer/urls.rb +43 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/client_registration_group.rb +42 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/docs/suite_description.md +50 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/endpoints/poll.rb +90 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/endpoints/status.rb +63 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/endpoints/submit.rb +35 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/helpers.rb +222 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/manifest_and_file_retrieval.rb +165 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/poll_group.rb +36 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/processing_wait_group.rb +83 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/retrieval.rb +139 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/status_submit_group.rb +96 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/submit_group.rb +314 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/submit_stopped_group.rb +43 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/tags.rb +18 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/test_suite.rb +122 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/urls.rb +53 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/provider/wait_group.rb +73 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/shared/jwks.rb +27 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/shared/submission_status.rb +14 -0
- data/lib/bulk_data_test_kit/v4.0.0/submit/shared/submitter_identifier.rb +14 -0
- data/lib/bulk_data_test_kit/version.rb +2 -2
- data/lib/bulk_data_test_kit.rb +2 -0
- metadata +41 -2
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'retrieval'
|
|
4
|
+
|
|
5
|
+
module BulkDataTestKit
|
|
6
|
+
module BulkDataV400
|
|
7
|
+
module Submit
|
|
8
|
+
module Provider
|
|
9
|
+
class ProcessingWaitGroup < Inferno::TestGroup
|
|
10
|
+
include URLs
|
|
11
|
+
|
|
12
|
+
title 'Retrieve Submissions and Wait For Final Polls'
|
|
13
|
+
|
|
14
|
+
description %(
|
|
15
|
+
After the tester confirms that all submit requests have been sent,
|
|
16
|
+
Inferno retrieves each completed submission. It then pauses while
|
|
17
|
+
the Data Provider makes its final status polling requests.
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
id :bulk_data_v400_submit_provider_processing_wait
|
|
21
|
+
|
|
22
|
+
run_as_group
|
|
23
|
+
|
|
24
|
+
input :client_id,
|
|
25
|
+
title: 'Client Id',
|
|
26
|
+
type: 'text',
|
|
27
|
+
optional: true,
|
|
28
|
+
locked: true,
|
|
29
|
+
description: SMARTAppLaunch::INPUT_CLIENT_ID_DESCRIPTION_LOCKED
|
|
30
|
+
|
|
31
|
+
test do
|
|
32
|
+
id :bulk_data_v400_submit_provider_retrieve_submissions
|
|
33
|
+
include Helpers
|
|
34
|
+
include Retrieval
|
|
35
|
+
|
|
36
|
+
title 'Retrieve Completed Submissions and Wait For Final Polls'
|
|
37
|
+
|
|
38
|
+
output :provider_submission_outcomes, type: :textarea
|
|
39
|
+
|
|
40
|
+
run do
|
|
41
|
+
identities = completed_submission_identities
|
|
42
|
+
skip_if identities.empty?, 'No completed submissions were received.'
|
|
43
|
+
|
|
44
|
+
outcomes = identities.each_with_object({}) do |identity, submission_outcomes|
|
|
45
|
+
key = submission_key(identity)
|
|
46
|
+
|
|
47
|
+
begin
|
|
48
|
+
retrieve_submission(identity)
|
|
49
|
+
submission_outcomes[key] = {
|
|
50
|
+
status: 'succeeded',
|
|
51
|
+
submission_id: identity[:submission_id]
|
|
52
|
+
}
|
|
53
|
+
rescue StandardError
|
|
54
|
+
submission_outcomes[key] = {
|
|
55
|
+
status: 'failed',
|
|
56
|
+
submission_id: identity[:submission_id],
|
|
57
|
+
diagnostic: Retrieval::FAILURE_DIAGNOSTIC
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
output provider_submission_outcomes: outcomes.to_json
|
|
63
|
+
|
|
64
|
+
identifier = client_id.presence || test_session_id
|
|
65
|
+
wait(
|
|
66
|
+
identifier:,
|
|
67
|
+
message: %(
|
|
68
|
+
Inferno has finished retrieving the completed submissions.
|
|
69
|
+
The Data Provider may now make its final request to each
|
|
70
|
+
Content-Location returned by `$bulk-submit-status`.
|
|
71
|
+
|
|
72
|
+
[Click here](#{resume_pass_url}?id=#{identifier}) after all
|
|
73
|
+
final polling requests have been made.
|
|
74
|
+
),
|
|
75
|
+
timeout: 900
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'smart_app_launch_test_kit'
|
|
4
|
+
require_relative 'helpers'
|
|
5
|
+
|
|
6
|
+
module BulkDataTestKit
|
|
7
|
+
module BulkDataV400
|
|
8
|
+
module Submit
|
|
9
|
+
module Provider
|
|
10
|
+
module Retrieval
|
|
11
|
+
FAILURE_DIAGNOSTIC = 'Bulk Submit retrieval failed.'
|
|
12
|
+
|
|
13
|
+
def completed_submission_identities
|
|
14
|
+
completed_submission_timelines.keys
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def completed_submission_timelines
|
|
18
|
+
@completed_submission_timelines ||=
|
|
19
|
+
valid_completed_submission_timelines(parsed_submissions)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def parsed_submissions
|
|
23
|
+
@parsed_submissions ||= parsed_submission_parameters(load_tagged_requests(SUBMIT_TAG))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def retrieval_contexts(identity)
|
|
27
|
+
Array(completed_submission_timelines[identity]).flat_map do |parameters|
|
|
28
|
+
oauth_metadata_url = parameters.parameter.find do |parameter|
|
|
29
|
+
parameter.name == 'oauthMetadataUrl' && parameter.valueUrl.present?
|
|
30
|
+
end&.valueUrl
|
|
31
|
+
|
|
32
|
+
parameters.parameter.filter_map do |parameter|
|
|
33
|
+
next unless parameter.name == 'manifestUrl' && parameter.valueUrl.present?
|
|
34
|
+
|
|
35
|
+
{ manifest_url: parameter.valueUrl, oauth_metadata_url: }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def retrieve_submission(identity)
|
|
41
|
+
retrieval_contexts(identity).each do |context|
|
|
42
|
+
retrieve_manifest_and_files(context)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def retrieve_manifest_and_files(context)
|
|
47
|
+
headers = { 'Accept' => 'application/json' }
|
|
48
|
+
if context[:oauth_metadata_url]
|
|
49
|
+
headers['Authorization'] = "Bearer #{access_token(context[:oauth_metadata_url])}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
manifest_request = get(context[:manifest_url], headers:, tags: [MANIFEST_TAG])
|
|
53
|
+
require_success(manifest_request)
|
|
54
|
+
manifest = JSON.parse(manifest_request.response_body).deep_symbolize_keys
|
|
55
|
+
raise 'The retrieved manifest was not a JSON object' unless manifest.is_a?(Hash)
|
|
56
|
+
|
|
57
|
+
file_headers = { 'Accept' => 'application/fhir+ndjson' }
|
|
58
|
+
if context[:oauth_metadata_url] && manifest[:requiresAccessToken]
|
|
59
|
+
file_headers['Authorization'] = "Bearer #{access_token(context[:oauth_metadata_url])}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Array(manifest[:output]).each do |output|
|
|
63
|
+
file_request = get(
|
|
64
|
+
output[:url],
|
|
65
|
+
headers: file_headers,
|
|
66
|
+
tags: [FILE_DOWNLOAD_TAG, output[:type].to_s]
|
|
67
|
+
)
|
|
68
|
+
require_success(file_request)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def require_success(request)
|
|
73
|
+
return request if request.status.to_i == 200
|
|
74
|
+
|
|
75
|
+
raise "Retrieval request to #{request.url} failed with status #{request.status}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def oauth_metadata(metadata_url)
|
|
79
|
+
oauth_metadata_cache[metadata_url] ||= begin
|
|
80
|
+
metadata_request = get(metadata_url, tags: [OAUTH_METADATA_TAG])
|
|
81
|
+
require_success(metadata_request)
|
|
82
|
+
metadata = JSON.parse(metadata_request.response_body).deep_symbolize_keys
|
|
83
|
+
raise 'The retrieved OAuth metadata was not a JSON object' unless metadata.is_a?(Hash)
|
|
84
|
+
|
|
85
|
+
metadata
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def access_token(metadata_url)
|
|
90
|
+
token = token_response(metadata_url)[:access_token]
|
|
91
|
+
raise 'OAuth token response did not include an access token' if token.blank?
|
|
92
|
+
|
|
93
|
+
token
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def token_response(metadata_url)
|
|
97
|
+
token_response_cache[metadata_url] ||= begin
|
|
98
|
+
endpoint = oauth_metadata(metadata_url)[:token_endpoint]
|
|
99
|
+
raise 'OAuth metadata did not include a token endpoint' if endpoint.blank?
|
|
100
|
+
|
|
101
|
+
request_details = token_request(endpoint)
|
|
102
|
+
token_request_result = post(
|
|
103
|
+
endpoint,
|
|
104
|
+
body: request_details[:body],
|
|
105
|
+
headers: request_details[:headers],
|
|
106
|
+
tags: [TOKEN_TAG]
|
|
107
|
+
)
|
|
108
|
+
require_success(token_request_result)
|
|
109
|
+
response = JSON.parse(token_request_result.response_body).deep_symbolize_keys
|
|
110
|
+
raise 'The OAuth token response was not a JSON object' unless response.is_a?(Hash)
|
|
111
|
+
|
|
112
|
+
response
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def token_request(audience)
|
|
117
|
+
SMARTAppLaunch::BackendServicesAuthorizationRequestBuilder.build(
|
|
118
|
+
encryption_method: consumer_auth_info.encryption_algorithm,
|
|
119
|
+
scope: consumer_auth_info.requested_scopes,
|
|
120
|
+
iss: consumer_auth_info.client_id,
|
|
121
|
+
sub: consumer_auth_info.client_id,
|
|
122
|
+
aud: audience,
|
|
123
|
+
kid: consumer_auth_info.kid,
|
|
124
|
+
custom_jwks: consumer_auth_info.jwks
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def oauth_metadata_cache
|
|
129
|
+
@oauth_metadata_cache ||= {}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def token_response_cache
|
|
133
|
+
@token_response_cache ||= {}
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulkDataTestKit
|
|
4
|
+
module BulkDataV400
|
|
5
|
+
module Submit
|
|
6
|
+
module Provider
|
|
7
|
+
class StatusSubmitGroup < Inferno::TestGroup
|
|
8
|
+
include Helpers
|
|
9
|
+
|
|
10
|
+
title 'Bulk Submit Status Operation'
|
|
11
|
+
|
|
12
|
+
description %(
|
|
13
|
+
This group verifies that a provider successfully made a status submit request.
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
id :bulk_data_v400_submit_provider_status_submit
|
|
17
|
+
|
|
18
|
+
run_as_group
|
|
19
|
+
|
|
20
|
+
optional
|
|
21
|
+
|
|
22
|
+
test do
|
|
23
|
+
id :bulk_data_v400_submit_provider_status_submit_request
|
|
24
|
+
title 'Status Submit Request Was Made'
|
|
25
|
+
|
|
26
|
+
description %(
|
|
27
|
+
This test verifies that at least one status submit request was made.
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
run do
|
|
31
|
+
assert load_tagged_requests(STATUS_SUBMIT_TAG).any?, 'Did not receive a status submit request.'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test do
|
|
36
|
+
id :bulk_data_v400_submit_provider_status_submit_identity
|
|
37
|
+
title '`submitter` and `submissionId` Match Submission'
|
|
38
|
+
|
|
39
|
+
description %(
|
|
40
|
+
This test verifies that every status submission includes exactly one
|
|
41
|
+
populated `submitter` Identifier and `submissionId`, and that the
|
|
42
|
+
combination matches a submit request.
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
run do
|
|
46
|
+
validate_status_submission_identities(
|
|
47
|
+
load_tagged_requests(STATUS_SUBMIT_TAG),
|
|
48
|
+
load_tagged_requests(SUBMIT_TAG)
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
test do
|
|
54
|
+
id :bulk_data_v400_submit_provider_status_submit_submission_id
|
|
55
|
+
title 'Submission ID Provided via `submissionId`'
|
|
56
|
+
|
|
57
|
+
description %(
|
|
58
|
+
This test verifies that every status request includes exactly one
|
|
59
|
+
populated `submissionId` string parameter.
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
run do
|
|
63
|
+
submissions = load_tagged_requests(STATUS_SUBMIT_TAG)
|
|
64
|
+
validate_submission_ids(submissions, '$bulk-submit-status')
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test do
|
|
69
|
+
id :bulk_data_v400_submit_provider_status_submit_output_format
|
|
70
|
+
title 'Submission Provided optional `_outputFormat` with type `string`'
|
|
71
|
+
|
|
72
|
+
description %(
|
|
73
|
+
This test verifies that a submission included the optional `_outputFormat` parameter, and had type `string`.
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
optional
|
|
77
|
+
|
|
78
|
+
run do
|
|
79
|
+
submissions = load_tagged_requests(STATUS_SUBMIT_TAG)
|
|
80
|
+
output_format_parameters = submissions.flat_map do |request|
|
|
81
|
+
FHIR.from_contents(request.request_body).parameter
|
|
82
|
+
end.select do |parameter|
|
|
83
|
+
parameter.name == '_outputFormat'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
skip_if output_format_parameters.empty?,
|
|
87
|
+
'No submission included the optional `_outputFormat` parameter'
|
|
88
|
+
assert output_format_parameters.all? { |parameter| !parameter.valueString.nil? },
|
|
89
|
+
'`_outputFormat` must have type `string`'
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../shared/submission_status'
|
|
4
|
+
|
|
5
|
+
module BulkDataTestKit
|
|
6
|
+
module BulkDataV400
|
|
7
|
+
module Submit
|
|
8
|
+
module Provider
|
|
9
|
+
class SubmitGroup < Inferno::TestGroup
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
title 'Bulk Submit Operation'
|
|
13
|
+
|
|
14
|
+
description %(
|
|
15
|
+
This group verifies that a provider successfully made at least one
|
|
16
|
+
valid completed submission.
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
id :bulk_data_v400_submit_provider_submit
|
|
20
|
+
|
|
21
|
+
run_as_group
|
|
22
|
+
|
|
23
|
+
test do
|
|
24
|
+
id :bulk_data_v400_submit_provider_in_progress_submit
|
|
25
|
+
title 'In-Progress Submit Request Was Made'
|
|
26
|
+
|
|
27
|
+
description %(
|
|
28
|
+
This test verifies that at least one `in-progress` submit request was made.
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
optional
|
|
32
|
+
|
|
33
|
+
run do
|
|
34
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
35
|
+
found_in_progress = submissions.any? do |request|
|
|
36
|
+
request_has_submission_status?(request, 'in-progress')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
skip_if !found_in_progress, 'An `in-progress` submission was not detected.'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test do
|
|
44
|
+
id :bulk_data_v400_submit_provider_completed_submit
|
|
45
|
+
title 'Completed Submit Request Was Made'
|
|
46
|
+
|
|
47
|
+
description %(
|
|
48
|
+
This test verifies that at least one `completed` submit request was made.
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
run do
|
|
52
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
53
|
+
found_completed = submissions.any? do |request|
|
|
54
|
+
request_has_submission_status?(request, 'completed')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
assert found_completed, 'A `completed` submission was not detected.'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
test do
|
|
62
|
+
id :bulk_data_v400_submit_provider_submitter_identifier
|
|
63
|
+
title '`submitter` Identifier Is Valid and Consistent'
|
|
64
|
+
|
|
65
|
+
description %(
|
|
66
|
+
This test verifies that every submission includes exactly one
|
|
67
|
+
populated `submitter` Identifier and uses the same Identifier
|
|
68
|
+
throughout the submission.
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
run do
|
|
72
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
73
|
+
validate_submitter_identifiers(
|
|
74
|
+
submissions,
|
|
75
|
+
'$bulk-submit'
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test do
|
|
81
|
+
id :bulk_data_v400_submit_provider_submission_id
|
|
82
|
+
title 'Required Submission ID Provided via `submissionId`'
|
|
83
|
+
|
|
84
|
+
description %(
|
|
85
|
+
This test verifies that every submission request includes exactly one
|
|
86
|
+
populated `submissionId` string parameter.
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
run do
|
|
90
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
91
|
+
validate_submission_ids(submissions, '$bulk-submit')
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
test do
|
|
96
|
+
id :bulk_data_v400_submit_provider_submission_status
|
|
97
|
+
title 'Received `submissionStatus` has a valid Coding'
|
|
98
|
+
|
|
99
|
+
description %(
|
|
100
|
+
This test verifies that when a `submissionStatus` is included, its system and code are valid.
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
run do
|
|
104
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
105
|
+
validate_submission_statuses(submissions)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
test do
|
|
110
|
+
id :bulk_data_v400_submit_provider_manifest_url
|
|
111
|
+
title 'Submission Provided optional `manifestUrl` with type `url`'
|
|
112
|
+
|
|
113
|
+
description %(
|
|
114
|
+
This test verifies that a submission included the optional `manifestUrl` parameter, and had type `url`.
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
optional
|
|
118
|
+
|
|
119
|
+
run do
|
|
120
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
121
|
+
manifest_url_parameters = submissions.flat_map do |request|
|
|
122
|
+
FHIR.from_contents(request.request_body).parameter
|
|
123
|
+
end.select do |parameter|
|
|
124
|
+
parameter.name == 'manifestUrl'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
skip_if manifest_url_parameters.empty?, 'No submission included the optional `manifestUrl` parameter'
|
|
128
|
+
assert manifest_url_parameters.all? { |parameter| !parameter.valueUrl.nil? },
|
|
129
|
+
'`manifestUrl` must have type `url`'
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
test do
|
|
134
|
+
id :bulk_data_v400_submit_provider_replaces_manifest_url
|
|
135
|
+
title 'Submission Provided optional `replacesManifestUrl` with type `url`'
|
|
136
|
+
|
|
137
|
+
description %(
|
|
138
|
+
This test verifies that a submission included the optional `replacesManifestUrl` parameter, and had type `url`.
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
optional
|
|
142
|
+
|
|
143
|
+
run do
|
|
144
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
145
|
+
replaces_manifest_url_parameters = submissions.flat_map do |request|
|
|
146
|
+
FHIR.from_contents(request.request_body).parameter
|
|
147
|
+
end.select do |parameter|
|
|
148
|
+
parameter.name == 'replacesManifestUrl'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
skip_if replaces_manifest_url_parameters.empty?,
|
|
152
|
+
'No submission included the optional `replacesManifestUrl` parameter'
|
|
153
|
+
assert replaces_manifest_url_parameters.all? { |parameter| !parameter.valueUrl.nil? },
|
|
154
|
+
'`replacesManifestUrl` must have type `url`'
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
test do
|
|
159
|
+
id :bulk_data_v400_submit_provider_output_format
|
|
160
|
+
title 'Submission Provided optional `outputFormat` with type `string`'
|
|
161
|
+
|
|
162
|
+
description %(
|
|
163
|
+
This test verifies that a submission included the optional `outputFormat` parameter, and had type `string`.
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
optional
|
|
167
|
+
|
|
168
|
+
run do
|
|
169
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
170
|
+
output_format_parameters = submissions.flat_map do |request|
|
|
171
|
+
FHIR.from_contents(request.request_body).parameter
|
|
172
|
+
end.select do |parameter|
|
|
173
|
+
parameter.name == 'outputFormat'
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
skip_if output_format_parameters.empty?,
|
|
177
|
+
'No submission included the optional `outputFormat` parameter'
|
|
178
|
+
assert output_format_parameters.all? { |parameter| !parameter.valueString.nil? },
|
|
179
|
+
'`outputFormat` must have type `string`'
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
test do
|
|
184
|
+
id :bulk_data_v400_submit_provider_fhir_base_url
|
|
185
|
+
title 'Submission Provided optional `fhirBaseUrl` with type `url`'
|
|
186
|
+
|
|
187
|
+
description %(
|
|
188
|
+
This test verifies that a submission included the optional `fhirBaseUrl` parameter, and had type `url`.
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
optional
|
|
192
|
+
|
|
193
|
+
run do
|
|
194
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
195
|
+
fhir_base_url_parameters = submissions.flat_map do |request|
|
|
196
|
+
FHIR.from_contents(request.request_body).parameter
|
|
197
|
+
end.select do |parameter|
|
|
198
|
+
parameter.name == 'fhirBaseUrl'
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
skip_if fhir_base_url_parameters.empty?, 'No submission included the optional `fhirBaseUrl` parameter'
|
|
202
|
+
assert fhir_base_url_parameters.all? { |parameter| !parameter.valueUrl.nil? },
|
|
203
|
+
'`fhirBaseUrl` must have type `url`'
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
test do
|
|
208
|
+
id :bulk_data_v400_submit_provider_file_request_header
|
|
209
|
+
title 'Submission Provided optional `fileRequestHeader` with type `part`'
|
|
210
|
+
|
|
211
|
+
description %(
|
|
212
|
+
This test verifies that a submission included the optional `fileRequestHeader` parameter, and had type `part`.
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
optional
|
|
216
|
+
|
|
217
|
+
run do
|
|
218
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
219
|
+
validate_optional_part_parameter(submissions, 'fileRequestHeader')
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
test do
|
|
224
|
+
id :bulk_data_v400_submit_provider_oauth_metadata_url
|
|
225
|
+
title 'Submission Provided optional `oauthMetadataUrl` with type `url`'
|
|
226
|
+
|
|
227
|
+
description %(
|
|
228
|
+
This test verifies that a submission included the optional `oauthMetadataUrl` parameter, and had type `url`.
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
optional
|
|
232
|
+
|
|
233
|
+
run do
|
|
234
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
235
|
+
oauth_metadata_url_parameters = submissions.flat_map do |request|
|
|
236
|
+
FHIR.from_contents(request.request_body).parameter
|
|
237
|
+
end.select do |parameter|
|
|
238
|
+
parameter.name == 'oauthMetadataUrl'
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
skip_if oauth_metadata_url_parameters.empty?,
|
|
242
|
+
'No submission included the optional `oauthMetadataUrl` parameter'
|
|
243
|
+
assert oauth_metadata_url_parameters.all? { |parameter| !parameter.valueUrl.nil? },
|
|
244
|
+
'`oauthMetadataUrl` must have type `url`'
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
test do
|
|
249
|
+
id :bulk_data_v400_submit_provider_file_encryption_key
|
|
250
|
+
title 'Submission Provided optional `fileEncryptionKey` with type `part`'
|
|
251
|
+
|
|
252
|
+
description %(
|
|
253
|
+
This test verifies that a submission included the optional `fileEncryptionKey` parameter, and had type `part`.
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
optional
|
|
257
|
+
|
|
258
|
+
run do
|
|
259
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
260
|
+
validate_optional_part_parameter(submissions, 'fileEncryptionKey')
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
test do
|
|
265
|
+
id :bulk_data_v400_submit_provider_metadata
|
|
266
|
+
title 'Submission Provided optional `metadata` with type `part`'
|
|
267
|
+
|
|
268
|
+
description %(
|
|
269
|
+
This test verifies that a submission included the optional `metadata` parameter, and had type `part`.
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
optional
|
|
273
|
+
|
|
274
|
+
run do
|
|
275
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
276
|
+
validate_optional_part_parameter(submissions, 'metadata')
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
test do
|
|
281
|
+
id :bulk_data_v400_submit_provider_import
|
|
282
|
+
title 'Submission Provided optional `import` with type `part`'
|
|
283
|
+
|
|
284
|
+
description %(
|
|
285
|
+
This test verifies that a submission included the optional `import` parameter, and had type `part`.
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
optional
|
|
289
|
+
|
|
290
|
+
run do
|
|
291
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
292
|
+
validate_optional_part_parameter(submissions, 'import')
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
test do
|
|
297
|
+
id :bulk_data_v400_submit_provider_terminal_submission_order
|
|
298
|
+
title 'No Requests Follow a Terminal Submission Status'
|
|
299
|
+
|
|
300
|
+
description %(
|
|
301
|
+
This test verifies that no additional `$bulk-submit` request was
|
|
302
|
+
made for a submission after it was marked `completed` or `stopped`.
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
run do
|
|
306
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
307
|
+
validate_terminal_submission_order(submissions)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulkDataTestKit
|
|
4
|
+
module BulkDataV400
|
|
5
|
+
module Submit
|
|
6
|
+
module Provider
|
|
7
|
+
class SubmitStoppedGroup < Inferno::TestGroup
|
|
8
|
+
include Helpers
|
|
9
|
+
|
|
10
|
+
title 'Bulk Submit Operation - Stopped'
|
|
11
|
+
|
|
12
|
+
description %(
|
|
13
|
+
This group verifies that a provider made at least one submission with a status of `stopped`.
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
id :bulk_data_v400_submit_provider_submit_stopped
|
|
17
|
+
|
|
18
|
+
run_as_group
|
|
19
|
+
|
|
20
|
+
optional
|
|
21
|
+
|
|
22
|
+
test do
|
|
23
|
+
id :bulk_data_v400_submit_provider_stopped_submit
|
|
24
|
+
title 'Stopped Submit Request Was Made'
|
|
25
|
+
|
|
26
|
+
description %(
|
|
27
|
+
This test verifies that at least one `stopped` submit request was made.
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
run do
|
|
31
|
+
submissions = load_tagged_requests(SUBMIT_TAG)
|
|
32
|
+
found_stopped = submissions.any? do |request|
|
|
33
|
+
request_has_submission_status?(request, 'stopped')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
skip_if !found_stopped, 'A `stopped` submission was not detected.'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulkDataTestKit
|
|
4
|
+
module BulkDataV400
|
|
5
|
+
module Submit
|
|
6
|
+
module Provider
|
|
7
|
+
FILE_DOWNLOAD_TAG = 'bulk_submit_file_download'
|
|
8
|
+
MANIFEST_TAG = 'bulk_submit_manifest'
|
|
9
|
+
OAUTH_METADATA_TAG = 'bulk_submit_oauth_metadata'
|
|
10
|
+
POLL_TAG = 'bulk_submit_status_poll'
|
|
11
|
+
STATUS_TAG = 'bulk_submit_status'
|
|
12
|
+
STATUS_SUBMIT_TAG = 'bulk_submit_status_submit'
|
|
13
|
+
SUBMIT_TAG = 'bulk_submit_submit'
|
|
14
|
+
TOKEN_TAG = 'bulk_submit_token'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|