davinci_pas_test_kit 0.11.0 → 0.12.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/pas_client_example.json +30 -0
- data/config/presets/pas_ri.json +69 -0
- data/lib/davinci_pas_test_kit/client_suite.rb +11 -27
- data/lib/davinci_pas_test_kit/docs/PAS Requirements Interpretation.xlsx +0 -0
- data/lib/davinci_pas_test_kit/{mock_server.rb → endpoints/claim_endpoint.rb} +32 -45
- data/lib/davinci_pas_test_kit/endpoints/token_endpoint.rb +22 -0
- data/lib/davinci_pas_test_kit/fhir_resource_navigation.rb +3 -3
- data/lib/davinci_pas_test_kit/generated/v2.0.1/server_suite.rb +4 -2
- data/lib/davinci_pas_test_kit/generator/templates/group.rb.erb +129 -0
- data/lib/davinci_pas_test_kit/generator/templates/must_support.rb.erb +73 -0
- data/lib/davinci_pas_test_kit/generator/templates/operation.rb.erb +62 -0
- data/lib/davinci_pas_test_kit/generator/templates/resource_list.rb.erb +13 -0
- data/lib/davinci_pas_test_kit/generator/templates/suite.rb.erb +91 -0
- data/lib/davinci_pas_test_kit/generator/templates/validation.rb.erb +98 -0
- data/lib/davinci_pas_test_kit/generator/templates/validation_client.rb.erb +50 -0
- data/lib/davinci_pas_test_kit/igs/davinci_pas_2.0.1.tgz +0 -0
- data/lib/davinci_pas_test_kit/metadata.rb +87 -0
- data/lib/davinci_pas_test_kit/version.rb +2 -1
- data/lib/davinci_pas_test_kit.rb +1 -0
- metadata +21 -10
- data/lib/davinci_pas_test_kit/ext/inferno_core/record_response_route.rb +0 -98
- data/lib/davinci_pas_test_kit/ext/inferno_core/request.rb +0 -19
- data/lib/davinci_pas_test_kit/ext/inferno_core/runnable.rb +0 -18
@@ -1,25 +1,19 @@
|
|
1
|
-
require_relative 'ext/inferno_core/record_response_route'
|
2
|
-
require_relative 'ext/inferno_core/runnable'
|
3
|
-
require_relative 'ext/inferno_core/request'
|
4
1
|
require_relative 'validator_suppressions'
|
5
2
|
require_relative 'tags'
|
6
3
|
require_relative 'urls'
|
7
|
-
require_relative '
|
4
|
+
require_relative 'endpoints/claim_endpoint'
|
5
|
+
require_relative 'endpoints/token_endpoint'
|
8
6
|
require_relative 'custom_groups/v2.0.1/pas_client_authentication_group'
|
9
7
|
require_relative 'custom_groups/v2.0.1/pas_client_approval_group'
|
10
8
|
require_relative 'custom_groups/v2.0.1/pas_client_denial_group'
|
11
9
|
require_relative 'custom_groups/v2.0.1/pas_client_pended_group'
|
12
10
|
require_relative 'generated/v2.0.1/pas_client_submit_must_support_use_case_group'
|
13
11
|
require_relative 'generated/v2.0.1/pas_client_inquiry_must_support_use_case_group'
|
14
|
-
require_relative 'version'
|
15
12
|
|
16
13
|
module DaVinciPASTestKit
|
17
14
|
class ClientSuite < Inferno::TestSuite
|
18
|
-
extend MockServer
|
19
|
-
|
20
15
|
id :davinci_pas_client_suite_v201
|
21
16
|
title 'Da Vinci PAS Client Suite v2.0.1'
|
22
|
-
version VERSION
|
23
17
|
description File.read(File.join(__dir__, 'docs', 'client_suite_description_v201.md'))
|
24
18
|
|
25
19
|
links [
|
@@ -31,16 +25,16 @@ module DaVinciPASTestKit
|
|
31
25
|
label: 'Open Source',
|
32
26
|
url: 'https://github.com/inferno-framework/davinci-pas-test-kit/'
|
33
27
|
},
|
28
|
+
{
|
29
|
+
label: 'Download',
|
30
|
+
url: 'https://github.com/inferno-framework/davinci-pas-test-kit/releases'
|
31
|
+
},
|
34
32
|
{
|
35
33
|
label: 'Implementation Guide',
|
36
34
|
url: 'https://hl7.org/fhir/us/davinci-pas/STU2/'
|
37
35
|
}
|
38
36
|
]
|
39
37
|
|
40
|
-
def self.test_resumes?(test)
|
41
|
-
!test.config.options[:accepts_multiple_requests]
|
42
|
-
end
|
43
|
-
|
44
38
|
fhir_resource_validator do
|
45
39
|
igs 'hl7.fhir.us.davinci-pas#2.0.1'
|
46
40
|
|
@@ -51,26 +45,16 @@ module DaVinciPASTestKit
|
|
51
45
|
end
|
52
46
|
end
|
53
47
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
record_response_route :post, SUBMIT_PATH, SUBMIT_TAG, method(:claim_response),
|
59
|
-
resumes: method(:test_resumes?) do |request|
|
60
|
-
ClientSuite.extract_bearer_token(request)
|
61
|
-
end
|
62
|
-
|
63
|
-
record_response_route :post, INQUIRE_PATH, INQUIRE_TAG, method(:claim_response),
|
64
|
-
resumes: method(:test_resumes?) do |request|
|
65
|
-
ClientSuite.extract_bearer_token(request)
|
66
|
-
end
|
48
|
+
suite_endpoint :post, TOKEN_PATH, TokenEndpoint
|
49
|
+
suite_endpoint :post, SUBMIT_PATH, ClaimEndpoint
|
50
|
+
suite_endpoint :post, INQUIRE_PATH, ClaimEndpoint
|
67
51
|
|
68
52
|
resume_test_route :get, RESUME_PASS_PATH do |request|
|
69
|
-
|
53
|
+
request.query_parameters['token']
|
70
54
|
end
|
71
55
|
|
72
56
|
resume_test_route :get, RESUME_FAIL_PATH, result: 'fail' do |request|
|
73
|
-
|
57
|
+
request.query_parameters['token']
|
74
58
|
end
|
75
59
|
|
76
60
|
group from: :pas_client_v201_authentication_group
|
Binary file
|
@@ -1,38 +1,35 @@
|
|
1
|
-
require_relative 'user_input_response'
|
1
|
+
require_relative '../user_input_response'
|
2
2
|
|
3
3
|
module DaVinciPASTestKit
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# See here for full list: https://hl7.org/fhir/us/davinci-pas/STU2/qa.html#suppressed
|
8
|
-
module MockServer
|
9
|
-
def token_response(request, _test = nil, _test_result = nil)
|
10
|
-
# Placeholder for a more complete mock token endpoint
|
11
|
-
request.response_body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json
|
12
|
-
request.status = 200
|
4
|
+
class ClaimEndpoint < Inferno::DSL::SuiteEndpoint
|
5
|
+
def test_run_identifier
|
6
|
+
request.headers['authorization']&.delete_prefix('Bearer ')
|
13
7
|
end
|
14
8
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
9
|
+
def tags
|
10
|
+
[operation == 'submit' ? SUBMIT_TAG : INQUIRE_TAG]
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_response
|
14
|
+
response.status = 200
|
15
|
+
response.format = :json
|
18
16
|
|
19
|
-
user_inputted_response = UserInputResponse.user_inputted_response(test,
|
20
|
-
if
|
21
|
-
|
17
|
+
user_inputted_response = UserInputResponse.user_inputted_response(test, result)
|
18
|
+
if user_inputted_response.present?
|
19
|
+
response.body = user_inputted_response
|
22
20
|
return
|
23
21
|
end
|
24
22
|
|
25
|
-
|
26
|
-
req_bundle = FHIR.from_contents(request&.request_body)
|
23
|
+
req_bundle = FHIR.from_contents(request.body.string)
|
27
24
|
claim_entry = req_bundle&.entry&.find { |e| e&.resource&.resourceType == 'Claim' }
|
28
25
|
claim_full_url = claim_entry&.fullUrl
|
29
26
|
if claim_entry.blank? || claim_full_url.blank?
|
30
|
-
handle_missing_required_elements(claim_entry,
|
27
|
+
handle_missing_required_elements(claim_entry, response)
|
31
28
|
return
|
32
29
|
end
|
33
30
|
|
34
31
|
root_url = base_url(claim_full_url)
|
35
|
-
claim_response = mock_claim_response(claim_entry.resource, req_bundle,
|
32
|
+
claim_response = mock_claim_response(claim_entry.resource, req_bundle, root_url)
|
36
33
|
|
37
34
|
res_bundle = FHIR::Bundle.new(
|
38
35
|
id: SecureRandom.uuid,
|
@@ -51,16 +48,20 @@ module DaVinciPASTestKit
|
|
51
48
|
|
52
49
|
res_bundle.entry.concat(referenced_entities(claim_response, req_bundle.entry, root_url))
|
53
50
|
|
54
|
-
|
55
|
-
request.status = 200
|
56
|
-
request.response_headers = { 'Content-Type': 'application/json' }
|
51
|
+
response.body = res_bundle.to_json
|
57
52
|
end
|
58
53
|
|
54
|
+
def update_result
|
55
|
+
results_repo.update_result(result.id, 'pass') unless test.config.options[:accepts_multiple_requests]
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
59
60
|
# Note that references from the claim to other resources in the bundle need to be changed to absolute URLs
|
60
61
|
# if they are relative, because the ClaimResponse's fullUrl is a urn:uuid
|
61
62
|
#
|
62
63
|
# @private
|
63
|
-
def mock_claim_response(claim, bundle,
|
64
|
+
def mock_claim_response(claim, bundle, root_url)
|
64
65
|
return FHIR::ClaimResponse.new(id: SecureRandom.uuid) if claim.blank?
|
65
66
|
|
66
67
|
now = Time.now.utc
|
@@ -128,33 +129,23 @@ module DaVinciPASTestKit
|
|
128
129
|
)
|
129
130
|
end
|
130
131
|
|
131
|
-
def
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
# Header expected to be a bearer token of the form "Bearer: <token>"
|
136
|
-
def extract_bearer_token(request)
|
137
|
-
request.request_header('Authorization')&.value&.split&.last
|
138
|
-
end
|
139
|
-
|
140
|
-
def extract_token_from_query_params(request)
|
141
|
-
request.query_parameters['token']
|
142
|
-
end
|
143
|
-
|
144
|
-
def handle_missing_required_elements(claim_entry, request)
|
145
|
-
request.status = 400
|
146
|
-
request.response_headers = { 'Content-Type': 'application/json' }
|
132
|
+
def handle_missing_required_elements(claim_entry, response)
|
133
|
+
response.status = 400
|
147
134
|
details = if claim_entry.blank?
|
148
135
|
'Required Claim entry missing from bundle'
|
149
136
|
else
|
150
137
|
'Required element fullUrl missing from Claim entry'
|
151
138
|
end
|
152
|
-
|
139
|
+
response.body = FHIR::OperationOutcome.new(
|
153
140
|
issue: FHIR::OperationOutcome::Issue.new(severity: 'fatal', code: 'required',
|
154
141
|
details: FHIR::CodeableConcept.new(text: details))
|
155
142
|
).to_json
|
156
143
|
end
|
157
144
|
|
145
|
+
def operation
|
146
|
+
request.url&.split('$')&.last
|
147
|
+
end
|
148
|
+
|
158
149
|
# Drop the last two segments of a URL, i.e. the resource type and ID of a FHIR resource
|
159
150
|
# e.g. http://example.org/fhir/Patient/123 -> http://example.org/fhir
|
160
151
|
# @private
|
@@ -165,7 +156,6 @@ module DaVinciPASTestKit
|
|
165
156
|
url.sub(%r{/[^/]*/[^/]*(/)?\z}, '')
|
166
157
|
end
|
167
158
|
|
168
|
-
# @private
|
169
159
|
def referenced_entities(resource, entries, root_url)
|
170
160
|
matches = []
|
171
161
|
attributes = resource&.source_hash&.keys
|
@@ -185,21 +175,18 @@ module DaVinciPASTestKit
|
|
185
175
|
matches
|
186
176
|
end
|
187
177
|
|
188
|
-
# @private
|
189
178
|
def absolute_reference(ref, entries, root_url)
|
190
179
|
url = find_matching_entry(ref&.reference, entries, root_url)&.fullUrl
|
191
180
|
ref.reference = url if url
|
192
181
|
ref
|
193
182
|
end
|
194
183
|
|
195
|
-
# @private
|
196
184
|
def find_matching_entry(ref, entries, root_url = '')
|
197
185
|
ref = "#{root_url}/#{ref}" if relative_reference?(ref) && root_url&.present?
|
198
186
|
|
199
187
|
entries&.find { |entry| entry&.fullUrl == ref }
|
200
188
|
end
|
201
189
|
|
202
|
-
# @private
|
203
190
|
def relative_reference?(ref)
|
204
191
|
ref&.count('/') == 1
|
205
192
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DaVinciPASTestKit
|
2
|
+
class TokenEndpoint < Inferno::DSL::SuiteEndpoint
|
3
|
+
def test_run_identifier
|
4
|
+
URI.decode_www_form(request.body.string).to_h['client_id']
|
5
|
+
end
|
6
|
+
|
7
|
+
def tags
|
8
|
+
[AUTH_TAG]
|
9
|
+
end
|
10
|
+
|
11
|
+
def make_response
|
12
|
+
# Placeholder for a more complete mock token endpoint
|
13
|
+
response.status = 200
|
14
|
+
response.format = :json
|
15
|
+
response.body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_result
|
19
|
+
results_repo.update_result(result.id, 'pass')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -20,7 +20,7 @@ module DaVinciPASTestKit
|
|
20
20
|
end.compact
|
21
21
|
end
|
22
22
|
|
23
|
-
def find_a_value_at(element, path, include_dar: false, &
|
23
|
+
def find_a_value_at(element, path, include_dar: false, &)
|
24
24
|
return nil if element.nil?
|
25
25
|
|
26
26
|
elements = Array.wrap(element)
|
@@ -32,7 +32,7 @@ module DaVinciPASTestKit
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
return elements.find(&
|
35
|
+
return elements.find(&) if block_given?
|
36
36
|
|
37
37
|
return elements.first
|
38
38
|
end
|
@@ -52,7 +52,7 @@ module DaVinciPASTestKit
|
|
52
52
|
elements.each do |elmt|
|
53
53
|
child = get_next_value(elmt, segment)
|
54
54
|
element_found = if block_given?
|
55
|
-
find_a_value_at(child, remaining_path, include_dar:, &
|
55
|
+
find_a_value_at(child, remaining_path, include_dar:, &)
|
56
56
|
else
|
57
57
|
find_a_value_at(child, remaining_path, include_dar:)
|
58
58
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require_relative '../../validator_suppressions'
|
2
2
|
require_relative '../../custom_groups/v2.0.1/pas_error_group'
|
3
|
-
require_relative '../../version'
|
4
3
|
require_relative 'pas_server_approval_use_case_group'
|
5
4
|
require_relative 'pas_server_denial_use_case_group'
|
6
5
|
require_relative 'pas_server_pended_use_case_group'
|
@@ -11,7 +10,6 @@ module DaVinciPASTestKit
|
|
11
10
|
class ServerSuite < Inferno::TestSuite
|
12
11
|
id :davinci_pas_server_suite_v201
|
13
12
|
title 'Da Vinci PAS Server Suite v2.0.1'
|
14
|
-
version DaVinciPASTestKit::VERSION
|
15
13
|
description File.read(File.join(__dir__, '..', '..', 'docs', 'server_suite_description_v201.md'))
|
16
14
|
|
17
15
|
links [
|
@@ -23,6 +21,10 @@ module DaVinciPASTestKit
|
|
23
21
|
label: 'Open Source',
|
24
22
|
url: 'https://github.com/inferno-framework/davinci-pas-test-kit/'
|
25
23
|
},
|
24
|
+
{
|
25
|
+
label: 'Download',
|
26
|
+
url: 'https://github.com/inferno-framework/davinci-pas-test-kit/releases'
|
27
|
+
},
|
26
28
|
{
|
27
29
|
label: 'Implementation Guide',
|
28
30
|
url: 'https://hl7.org/fhir/us/davinci-pas/STU2/'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
<% test_file_list.each do |file_name| %>require_relative '<%= file_name %>'
|
2
|
+
<% end %>
|
3
|
+
module DaVinciPASTestKit
|
4
|
+
module <%= module_name %>
|
5
|
+
class <%= class_name %> < Inferno::TestGroup
|
6
|
+
title '<%= title %>'
|
7
|
+
description %(
|
8
|
+
<%=description.gsub("\n", "\n" + " "*8) %>
|
9
|
+
)
|
10
|
+
|
11
|
+
id :<%= group_id %>
|
12
|
+
<% if run_as_group %>run_as_group<% end %>
|
13
|
+
<% if system == 'client'%>
|
14
|
+
<% test_id_list.each do |id| %>
|
15
|
+
test from: :<%= id %><% end %>
|
16
|
+
<% else %>
|
17
|
+
def use_case
|
18
|
+
'<%= use_case %>'
|
19
|
+
end
|
20
|
+
<% if use_case != 'must_support'%>
|
21
|
+
<% test_id_list.each do |category, id_list| %>
|
22
|
+
group do
|
23
|
+
title '<%= category %>'
|
24
|
+
<% id_list.each do |id| %>
|
25
|
+
test from: :<%= id %><% if rename_input?(id) %> do
|
26
|
+
id :<%= alt_test_id(id, use_case) %>
|
27
|
+
config(
|
28
|
+
inputs: {
|
29
|
+
pa_submit_request_payload: {
|
30
|
+
name: :<%= alt_request_input_name(use_case, 'submit')%> ,
|
31
|
+
title: '<%= alt_request_input_title(use_case, 'submit')%>'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end<% end %><% end %>
|
36
|
+
end<% end %>
|
37
|
+
<% else %>
|
38
|
+
<% test_id_list.each do |group, subgroup|%>
|
39
|
+
group do
|
40
|
+
title '<%= group%>'
|
41
|
+
<% if group == '$submit Element Support' %>description %(
|
42
|
+
Check that the provided `$submit` requests both themselves contain
|
43
|
+
and elicit server responses that contain all PAS-defined profiles
|
44
|
+
and their must support elements.
|
45
|
+
|
46
|
+
For `$submit` requests, this includes the following profiles:
|
47
|
+
|
48
|
+
- [PAS Request Bundle](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-pas-request-bundle.html)
|
49
|
+
- [PAS Claim Update](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-claim-update.html)
|
50
|
+
- [PAS Coverage](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-coverage.html)
|
51
|
+
- [PAS Beneficiary Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-beneficiary.html)
|
52
|
+
- [PAS Subscriber Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-subscriber.html)
|
53
|
+
- [PAS Insurer Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-insurer.html)
|
54
|
+
- [PAS Requestor Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-requestor.html)
|
55
|
+
- [PAS Practitioner](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitioner.html)
|
56
|
+
- [PAS PractitionerRole](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitionerrole.html)
|
57
|
+
- [PAS Encounter](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-encounter.html)
|
58
|
+
- At least one of the following request profiles
|
59
|
+
- [PAS Device Request](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-devicerequest.html)
|
60
|
+
- [PAS Medication Request](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-medicationrequest.html)
|
61
|
+
- [PAS Nutrition Order](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-nutritionorder.html)
|
62
|
+
- [PAS Service Request](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-servicerequest.html)
|
63
|
+
|
64
|
+
For `$submit` responses, this includes the following profiles (NOTE: request-specific
|
65
|
+
profiles that may be echoed from `$submit` requests, such as the Claim instance or request instances,
|
66
|
+
are not currently checked):
|
67
|
+
|
68
|
+
- [PAS Response Bundle](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-pas-response-bundle.html)
|
69
|
+
- [PAS Claim Response](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-claimresponse.html)
|
70
|
+
- [PAS CommunicationRequest](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-communicationrequest.html)
|
71
|
+
- [PAS Task](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-task.html)
|
72
|
+
- [PAS Beneficiary Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-beneficiary.html)
|
73
|
+
- [PAS Insurer Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-insurer.html)
|
74
|
+
- [PAS Requestor Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-requestor.html)
|
75
|
+
- [PAS Practitioner](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitioner.html)
|
76
|
+
- [PAS PractitionerRole](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitionerrole.html)
|
77
|
+
)<% elsif group == '$inquire Element Support' %>description %(
|
78
|
+
Check that the provided `$inquire` requests both themselves contain
|
79
|
+
and elicit server responses that contain all PAS-defined profiles
|
80
|
+
and their must support elements.
|
81
|
+
|
82
|
+
For `$inquire` requests, this includes the following profiles:
|
83
|
+
|
84
|
+
- [PAS Inquiry Request Bundle](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-pas-inquiry-request-bundle.html)
|
85
|
+
- [PAS Claim Inquiry](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-claim-inquiry.html)
|
86
|
+
- [PAS Coverage](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-coverage.html)
|
87
|
+
- [PAS Beneficiary Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-beneficiary.html)
|
88
|
+
- [PAS Subscriber Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-subscriber.html)
|
89
|
+
- [PAS Insurer Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-insurer.html)
|
90
|
+
- [PAS Requestor Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-requestor.html)
|
91
|
+
- [PAS Practitioner](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitioner.html)
|
92
|
+
- [PAS PractitionerRole](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitionerrole.html)
|
93
|
+
|
94
|
+
For `$inquire` responses, this includes the following profiles (NOTE: request-specific
|
95
|
+
profiles that may be echoed from `$submit` requests, such as the Claim instance or request instances,
|
96
|
+
are not currently checked):
|
97
|
+
|
98
|
+
- [PAS Inquiry Response Bundle](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-pas-inquiry-request-bundle.html)
|
99
|
+
- [PAS Claim Inquiry Response](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-claiminquiryresponse.html)
|
100
|
+
- [PAS Task](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-task.html)
|
101
|
+
- [PAS Beneficiary Patient](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-beneficiary.html)
|
102
|
+
- [PAS Insurer Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-insurer.html)
|
103
|
+
- [PAS Requestor Organization](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-requestor.html)
|
104
|
+
- [PAS Practitioner](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitioner.html)
|
105
|
+
- [PAS PractitionerRole](https://hl7.org/fhir/us/davinci-pas/STU2/StructureDefinition-profile-practitionerrole.html)
|
106
|
+
)<% end %>
|
107
|
+
run_as_group
|
108
|
+
<% subgroup.each do |category, id_list| %>
|
109
|
+
group do
|
110
|
+
title '<%= category%>'
|
111
|
+
<% id_list.each do |id|%>
|
112
|
+
test from: :<%= id%><% if must_support_rename_input?(id) %> do
|
113
|
+
id :<%= alt_test_id(id, use_case) %>
|
114
|
+
config(
|
115
|
+
inputs: {<% request_type = id.include?('inquiry') ? 'inquire' : 'submit' %>
|
116
|
+
pa_<%= request_type%>_request_payload: {
|
117
|
+
name: :<%= alt_request_input_name(use_case, request_type)%>,
|
118
|
+
title: '<%= alt_request_input_title(use_case, request_type)%>',
|
119
|
+
description: 'Insert an additional request bundle or a list of bundles (e.g. [bundle_1, bundle_2])'
|
120
|
+
}
|
121
|
+
}
|
122
|
+
)
|
123
|
+
end<%end%><% end %>
|
124
|
+
end<% end %>
|
125
|
+
end<%end%>
|
126
|
+
<% end %><% end %>
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative '../../../must_support_test'
|
2
|
+
require_relative '../../../generator/group_metadata'
|
3
|
+
require_relative '../../../tags'
|
4
|
+
|
5
|
+
module DaVinciPASTestKit
|
6
|
+
module <%= module_name %>
|
7
|
+
class <%= class_name %> < Inferno::Test
|
8
|
+
include DaVinciPASTestKit::MustSupportTest
|
9
|
+
|
10
|
+
title 'All must support elements for Profile <%= profile_name %> are observed across all instances <%= request_type.include?('request') ? 'submitted' : 'returned' %>'
|
11
|
+
description %(
|
12
|
+
<% if system == 'client' && request_type.include?('request') %>
|
13
|
+
PAS client systems are required to be able to populate all
|
14
|
+
must support elements on instances of all profiles included in <% request_type.include?('submit') ? 'Submit' : 'Inquiry' %>
|
15
|
+
requests, including instances of the <%= profile_name %> Profile.
|
16
|
+
This test checks all identified instances of the <%= profile_name %>
|
17
|
+
Profile on requests sent by the client to ensure that the following
|
18
|
+
must support elements are observed: <% end %><% if system == 'client' && request_type.include?('response') %>
|
19
|
+
PAS client systems are required to be able to receive all
|
20
|
+
must support elements on instances of all profiles included in <% request_type.include?('submit') ? 'Submit' : 'Inquiry' %>
|
21
|
+
responses, including instances of the <%= profile_name %> Profile.
|
22
|
+
This test checks all identified instances of the <%= profile_name %>
|
23
|
+
Profile on responses sent to the client to ensure that the following
|
24
|
+
must support elements are observed:<% end %><% if system == 'server' && request_type.include?('request') %>
|
25
|
+
**USER INPUT VALIDATION**: This test validates input provided by the user instead of the system under test. Errors encountered will be treated as a skip instead of a failure.
|
26
|
+
|
27
|
+
PAS server systems are required to be able to receive all
|
28
|
+
must support elements on instances of all profiles included in <% request_type.include?('submit') ? 'Submit' : 'Inquiry' %>
|
29
|
+
requests, including instances of the <%= profile_name %> Profile.
|
30
|
+
This test checks all identified instances of the <%= profile_name %>
|
31
|
+
Profile on requests sent to the server to ensure that the following
|
32
|
+
must support elements are observed:<% end %><% if system == 'server' && request_type.include?('response') %>
|
33
|
+
PAS server systems are required to be able to populate all
|
34
|
+
must support elements on instances of all profiles included in <% request_type.include?('submit') ? 'Submit' : 'Inquiry' %>
|
35
|
+
responses, including instances of the <%= profile_name %> Profile.
|
36
|
+
This test checks all identified instances of the <%= profile_name %>
|
37
|
+
Profile on responses returned by the server to ensure that the following
|
38
|
+
must support elements are observed:<% end %>
|
39
|
+
|
40
|
+
<%= must_support_list_string %>
|
41
|
+
)
|
42
|
+
|
43
|
+
id :<%= test_id %>
|
44
|
+
|
45
|
+
def resource_type
|
46
|
+
'<%= resource_type %>'
|
47
|
+
end
|
48
|
+
|
49
|
+
def user_input_validation
|
50
|
+
<% if system == 'server' && request_type.include?('request') %>true<% else %>false<% end %>
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.metadata
|
54
|
+
@metadata ||= Generator::GroupMetadata.new(YAML.load_file(File.join(__dir__, 'metadata.yml'), aliases: true))
|
55
|
+
end
|
56
|
+
|
57
|
+
def scratch_resources
|
58
|
+
# The scratch key in MS test should be the same as the scratch key in the validation test for a given profile.
|
59
|
+
scratch[:<%= request_type %>_resources] ||= {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def resources_of_interest
|
63
|
+
collection = tagged_resources(<%= request_type.include?('submit') ? 'SUBMIT_TAG' : 'INQUIRE_TAG' %>).presence || <%= resource_collection_string %>
|
64
|
+
collection.select { |res| res.resourceType == resource_type }
|
65
|
+
end
|
66
|
+
|
67
|
+
run do
|
68
|
+
perform_must_support_test(resources_of_interest)
|
69
|
+
validate_must_support(user_input_validation)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module DaVinciPASTestKit
|
2
|
+
module <%= module_name %>
|
3
|
+
class <%= class_name %> < Inferno::Test
|
4
|
+
|
5
|
+
id :<%= test_id %>
|
6
|
+
title '<%= title %>'
|
7
|
+
description %(
|
8
|
+
<%=description.gsub("\n", "\n" + " "*8) %>
|
9
|
+
)
|
10
|
+
|
11
|
+
input :pa_<%= request_type %>_payload,
|
12
|
+
title: 'PAS <%= request_type.humanize.titleize%> Payload',
|
13
|
+
description: 'Insert Bundle to be sent for PAS <%= request_type.humanize.titleize%>',
|
14
|
+
type: 'textarea',
|
15
|
+
optional: true
|
16
|
+
input_order :server_endpoint, :smart_credentials
|
17
|
+
<% if operation == 'submit'%>output :response_time<% end %>
|
18
|
+
makes_request :pa_<%= operation %>
|
19
|
+
|
20
|
+
def scratch_resources
|
21
|
+
scratch[:<%= operation %>_request_response_pair] ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def request_bundles
|
25
|
+
parsed_payload = JSON.parse(pa_<%= request_type %>_payload)
|
26
|
+
[parsed_payload].flatten.compact.uniq
|
27
|
+
end
|
28
|
+
|
29
|
+
def perform_operation(request_payload)
|
30
|
+
<% if operation == 'submit'%>start_time = Time.now<% end %>
|
31
|
+
fhir_operation('/Claim/$<%= operation %>', body: request_payload, name: :pa_<%= operation %>)
|
32
|
+
<% if operation == 'submit'%>response_time = Time.now - start_time
|
33
|
+
|
34
|
+
if response_time > 15
|
35
|
+
warning %(
|
36
|
+
The server took more that 15 seconds to respond to the Prior Authorization
|
37
|
+
request.
|
38
|
+
|
39
|
+
Response Time: #{response_time}
|
40
|
+
)
|
41
|
+
end
|
42
|
+
<% end %>
|
43
|
+
assert_response_status([200, 201])
|
44
|
+
assert_valid_json(request.response_body)
|
45
|
+
|
46
|
+
# Save request/response pair
|
47
|
+
scratch_resources[:all] ||= []
|
48
|
+
scratch_resources[:all] << {request_bundle: request.request_body, response_bundle: resource}
|
49
|
+
<% if operation == 'submit'%>output response_time:<% end %>
|
50
|
+
end
|
51
|
+
|
52
|
+
run do
|
53
|
+
skip_if pa_<%= request_type %>_payload.blank?, 'No bundle request provided to perform the <%= operation %> operation'
|
54
|
+
assert_valid_json(pa_<%= request_type %>_payload)
|
55
|
+
|
56
|
+
request_bundles.each do |bundle|
|
57
|
+
perform_operation(bundle)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module DaVinciPASTestKit
|
2
|
+
module <%= module_name %>
|
3
|
+
module ResourceList
|
4
|
+
RESOURCE_LIST = [
|
5
|
+
<%= resource_list_string.gsub("\n", "\n" + " "*4) %>
|
6
|
+
].freeze
|
7
|
+
|
8
|
+
RESOURCE_SUPPORTED_PROFILES = {<% resource_supported_profiles.each do |resource, profile_list| %>
|
9
|
+
<%= resource %>: <%= profile_list %>,<% end %>
|
10
|
+
}.freeze
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|