davinci_pdex_test_kit 0.10.6 → 0.11.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/pdex_payer_client_postman_preset.json +12 -0
- data/config/presets/pdex_payer_server_fhir_foundry_ri_preset.json +96 -0
- data/config/presets/pdex_payer_server_inferno_ri_preset.json +96 -0
- data/lib/davinci_pdex_test_kit/docs/davinci_pdex_test_kit_description_v200.md +33 -0
- data/lib/davinci_pdex_test_kit/docs/payer_client_suite_description_v200.md +107 -17
- data/lib/davinci_pdex_test_kit/fhir_resource_navigation.rb +5 -1
- data/lib/davinci_pdex_test_kit/group_metadata.rb +5 -1
- data/lib/davinci_pdex_test_kit/igs/davinci-pdex-2.0.0.tgz +0 -0
- data/lib/davinci_pdex_test_kit/igs/us-core-3.1.1.tgz +0 -0
- data/lib/davinci_pdex_test_kit/metadata.rb +16 -0
- data/lib/davinci_pdex_test_kit/must_support_test.rb +3 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_member_match_tests/client_member_match_validation_test.rb +20 -18
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_validation_test.rb +96 -43
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_workflow_interaction_test.rb +49 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/allergyintolerance_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/careplan_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/careteam_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/clinical_data_request_check_test.rb +24 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/condition_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/device_clinical_data_request_test.rb +19 -17
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/diagnosticreport_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/documentreference_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/encounter_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/explanationofbenefit_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/goal_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/immunization_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/location_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/medicationdispense_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/medicationrequest_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/observation_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/organization_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/patient_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/patient_id_search_request_check_test.rb +21 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/practitioner_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/practitionerrole_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/procedure_clinical_data_request_test.rb +18 -16
- data/lib/davinci_pdex_test_kit/pdex_payer_client/collection.rb +46 -44
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/binary_endpoint.rb +26 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/export_endpoint.rb +29 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/export_status_endpoint.rb +38 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/member_match_endpoint.rb +51 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/next_page_endpoint.rb +23 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/patient_endpoint.rb +25 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/patient_everything_endpoint.rb +34 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/proxy_endpoint.rb +178 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/resource_read_endpoint.rb +21 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/resource_search_endpoint.rb +22 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server/token_endpoint.rb +27 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/mock_server.rb +53 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/tags.rb +15 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client/urls.rb +51 -0
- data/lib/davinci_pdex_test_kit/pdex_payer_client_suite.rb +101 -144
- data/lib/davinci_pdex_test_kit/pdex_payer_server/coverage_to_link_minimal_data_validation.rb +1 -1
- data/lib/davinci_pdex_test_kit/pdex_payer_server/coverage_to_link_must_support_validation.rb +1 -1
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_id_search_test.rb +5 -4
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_identifier_search_test.rb +5 -4
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_must_support_test.rb +3 -2
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_patient_last_updated_search_test.rb +7 -6
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_patient_service_date_search_test.rb +7 -6
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_patient_type_search_test.rb +7 -6
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_patient_use_search_test.rb +6 -5
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_provenance_revinclude_search_test.rb +10 -7
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_read_test.rb +1 -1
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_reference_resolution_test.rb +3 -2
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/explanation_of_benefit_validation_test.rb +1 -1
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit/metadata.yml +12 -12
- data/lib/davinci_pdex_test_kit/pdex_payer_server/explanation_of_benefit_group.rb +12 -14
- data/lib/davinci_pdex_test_kit/pdex_payer_server/export_patient_group.rb +3 -4
- data/lib/davinci_pdex_test_kit/pdex_payer_server/export_validation_group.rb +2 -6
- data/lib/davinci_pdex_test_kit/pdex_payer_server/member_match_request_local_references_validation.rb +1 -1
- data/lib/davinci_pdex_test_kit/pdex_payer_server/member_match_request_profile_validation.rb +1 -3
- data/lib/davinci_pdex_test_kit/pdex_payer_server/multiple_member_matches_group.rb +7 -8
- data/lib/davinci_pdex_test_kit/pdex_payer_server/no_member_matches_group.rb +7 -8
- data/lib/davinci_pdex_test_kit/pdex_payer_server/patient_operation_in_capability_statement_validation.rb +1 -3
- data/lib/davinci_pdex_test_kit/pdex_payer_server/workflow_clinical_data_group.rb +3 -5
- data/lib/davinci_pdex_test_kit/pdex_payer_server/workflow_everything_group.rb +2 -4
- data/lib/davinci_pdex_test_kit/pdex_payer_server/workflow_export_group.rb +2 -4
- data/lib/davinci_pdex_test_kit/pdex_payer_server/workflow_member_match_group.rb +12 -13
- data/lib/davinci_pdex_test_kit/pdex_payer_server_suite.rb +13 -14
- data/lib/davinci_pdex_test_kit/version.rb +2 -3
- data/lib/davinci_pdex_test_kit.rb +1 -2
- metadata +65 -24
- data/lib/davinci_pdex_test_kit/ext/inferno_core/record_response_route.rb +0 -98
- data/lib/davinci_pdex_test_kit/ext/inferno_core/request.rb +0 -19
- data/lib/davinci_pdex_test_kit/ext/inferno_core/runnable.rb +0 -18
- data/lib/davinci_pdex_test_kit/mock_server.rb +0 -281
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_member_match_tests/client_member_match_submit_test.rb +0 -24
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_must_support_tests/client_member_match_must_support_submit_test.rb +0 -26
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_must_support_tests/client_member_match_must_support_validation_test.rb +0 -32
- data/lib/davinci_pdex_test_kit/pdex_payer_client/client_must_support_tests/metadata.yml +0 -61
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/initial_scratch_storing.rb +0 -32
- data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/initial_wait_test.rb +0 -31
- data/lib/davinci_pdex_test_kit/tags.rb +0 -11
- data/lib/davinci_pdex_test_kit/urls.rb +0 -77
- /data/lib/davinci_pdex_test_kit/{metadata → pdex_payer_client/mock_server/resources}/mock_capability_statement.json +0 -0
- /data/lib/davinci_pdex_test_kit/{metadata → pdex_payer_client/mock_server/resources}/mock_operation_outcome_resource.json +0 -0
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'hanami/controller'
|
2
|
-
|
3
|
-
module Inferno
|
4
|
-
module DSL
|
5
|
-
# A base class for creating routes with custom response logic. Requests and responses are tagged and saved.
|
6
|
-
# @private
|
7
|
-
# @see Inferno::DSL::Runnable#resume_test_route
|
8
|
-
class RecordResponseRoute < Hanami::Action
|
9
|
-
include Import[
|
10
|
-
requests_repo: 'inferno.repositories.requests',
|
11
|
-
results_repo: 'inferno.repositories.results',
|
12
|
-
test_runs_repo: 'inferno.repositories.test_runs',
|
13
|
-
tests_repo: 'inferno.repositories.tests'
|
14
|
-
]
|
15
|
-
|
16
|
-
def self.call(...)
|
17
|
-
new.call(...)
|
18
|
-
end
|
19
|
-
|
20
|
-
# @private
|
21
|
-
def test_run_identifier_block
|
22
|
-
self.class.singleton_class.instance_variable_get(:@test_run_identifier_block)
|
23
|
-
end
|
24
|
-
|
25
|
-
# @private
|
26
|
-
def build_response_block
|
27
|
-
self.class.singleton_class.instance_variable_get(:@build_response_block)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @private
|
31
|
-
def tags
|
32
|
-
self.class.singleton_class.instance_variable_get(:@tags)
|
33
|
-
end
|
34
|
-
|
35
|
-
# @private
|
36
|
-
def resumes?(test)
|
37
|
-
instance_exec(test, &self.class.singleton_class.instance_variable_get(:@resumes))
|
38
|
-
end
|
39
|
-
|
40
|
-
# @private
|
41
|
-
def find_test_run(test_run_identifier)
|
42
|
-
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
43
|
-
end
|
44
|
-
|
45
|
-
# @private
|
46
|
-
def find_waiting_result(test_run)
|
47
|
-
results_repo.find_waiting_result(test_run_id: test_run.id)
|
48
|
-
end
|
49
|
-
|
50
|
-
# @private
|
51
|
-
def update_result(waiting_result)
|
52
|
-
results_repo.update_result(waiting_result.id, 'pass')
|
53
|
-
end
|
54
|
-
|
55
|
-
# @private
|
56
|
-
def persist_request(request, test_run, waiting_result, test)
|
57
|
-
requests_repo.create(
|
58
|
-
request.to_hash.merge(
|
59
|
-
test_session_id: test_run.test_session_id,
|
60
|
-
result_id: waiting_result.id,
|
61
|
-
name: test.config.request_name(test.incoming_request_name),
|
62
|
-
tags:
|
63
|
-
)
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
|
-
# @private
|
68
|
-
def find_test(waiting_result)
|
69
|
-
tests_repo.find(waiting_result.test_id)
|
70
|
-
end
|
71
|
-
|
72
|
-
# @private
|
73
|
-
def handle(req, res)
|
74
|
-
request = Inferno::Entities::Request.from_hanami_request(req)
|
75
|
-
|
76
|
-
test_run_identifier = instance_exec(request, &test_run_identifier_block)
|
77
|
-
|
78
|
-
test_run = find_test_run(test_run_identifier)
|
79
|
-
|
80
|
-
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
81
|
-
|
82
|
-
waiting_result = find_waiting_result(test_run)
|
83
|
-
test = find_test(waiting_result)
|
84
|
-
|
85
|
-
test_runs_repo.mark_as_no_longer_waiting(test_run.id) if resumes? test
|
86
|
-
|
87
|
-
update_result(waiting_result) if resumes? test
|
88
|
-
|
89
|
-
instance_exec(request, test, waiting_result, &build_response_block)
|
90
|
-
|
91
|
-
Inferno::Entities::Request.to_hanami_response(request, res)
|
92
|
-
persist_request(request, test_run, waiting_result, test)
|
93
|
-
|
94
|
-
Jobs.perform(Jobs::ResumeTestRun, test_run.id) if resumes? test
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Inferno
|
2
|
-
module Entities
|
3
|
-
class Request
|
4
|
-
def self.to_hanami_response(request, response)
|
5
|
-
response.status = request.status
|
6
|
-
response.body = request.response_body
|
7
|
-
request.response_headers.each do |header|
|
8
|
-
response.headers[header.name] = header.value
|
9
|
-
end
|
10
|
-
|
11
|
-
response
|
12
|
-
end
|
13
|
-
|
14
|
-
def response_headers=(headers_hash)
|
15
|
-
headers.concat(headers_hash.map { |key, value| Header.new(name: key.to_s, value:, type: 'response') })
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require_relative 'record_response_route'
|
2
|
-
|
3
|
-
module Inferno
|
4
|
-
module DSL
|
5
|
-
module Runnable
|
6
|
-
def record_response_route(method, path, tags, build_response, resumes: ->(_) { true }, &block)
|
7
|
-
route_class = Class.new(Inferno::DSL::RecordResponseRoute) do |klass|
|
8
|
-
klass.singleton_class.instance_variable_set(:@build_response_block, build_response)
|
9
|
-
klass.singleton_class.instance_variable_set(:@test_run_identifier_block, block)
|
10
|
-
klass.singleton_class.instance_variable_set(:@tags, Array.wrap(tags))
|
11
|
-
klass.singleton_class.instance_variable_set(:@resumes, resumes)
|
12
|
-
end
|
13
|
-
|
14
|
-
route(method, path, route_class)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,281 +0,0 @@
|
|
1
|
-
require_relative 'user_input_response'
|
2
|
-
require_relative 'urls'
|
3
|
-
require_relative 'pdex_payer_client/collection'
|
4
|
-
require_relative 'pdex_payer_client/client_validation_test'
|
5
|
-
#require_relative 'metadata/mock_capability_statement'
|
6
|
-
|
7
|
-
|
8
|
-
module DaVinciPDexTestKit
|
9
|
-
# Serve responses to PAS requests
|
10
|
-
#
|
11
|
-
# Note that there are numerous expected validation issues that can safely be ignored.
|
12
|
-
# See here for full list: https://hl7.org/fhir/us/davinci-pas/STU2/qa.html#suppressed
|
13
|
-
module MockServer
|
14
|
-
include URLs
|
15
|
-
|
16
|
-
def server_proxy
|
17
|
-
@server_proxy ||= Faraday.new(
|
18
|
-
url: ENV.fetch('FHIR_REFERENCE_SERVER'),
|
19
|
-
params: {},
|
20
|
-
headers: {'Content-Type' => 'application/json', 'Authorization' => 'Bearer SAMPLE_TOKEN', 'Host' => ENV.fetch('HOST_HEADER')},
|
21
|
-
) do |proxy|
|
22
|
-
proxy.use FaradayMiddleware::Gzip
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def token_response(request, _test = nil, _test_result = nil)
|
27
|
-
# Placeholder for a more complete mock token endpoint
|
28
|
-
request.response_body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json
|
29
|
-
request.status = 200
|
30
|
-
end
|
31
|
-
|
32
|
-
def claim_response(request, test = nil, test_result = nil)
|
33
|
-
endpoint = resource_endpoint(request.url)
|
34
|
-
params = match_request_to_expectation(endpoint, request.query_parameters)
|
35
|
-
if params
|
36
|
-
response = server_proxy.get(endpoint, params)
|
37
|
-
request.status = response.status
|
38
|
-
response_resource = replace_bundle_urls(FHIR.from_contents(response.body))
|
39
|
-
request.response_headers = remove_transfer_encoding_header(response.headers)
|
40
|
-
request.response_body = response_resource.to_json
|
41
|
-
request.response_header("content-length").value = request.response_body.length
|
42
|
-
else
|
43
|
-
response = server_proxy.get('Patient', {_id: 999})
|
44
|
-
response_resource = FHIR.from_contents(response.body)
|
45
|
-
response_resource.entry = [{fullUrl: 'urn:uuid:2866af9c-137d-4458-a8a9-eeeec0ce5583', resource: mock_operation_outcome_resource, search: {mode: 'outcome'}}]
|
46
|
-
response_resource.link.first.url = request.url #specific case for Operation Outcome handling
|
47
|
-
request.status = 400
|
48
|
-
request.response_body = response_resource.to_json
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def read_next_page(request, test = nil, test_result = nil)
|
53
|
-
response = server_proxy.get('', request.query_parameters)
|
54
|
-
request.status = response.status
|
55
|
-
request.response_headers = remove_transfer_encoding_header(response.headers)
|
56
|
-
request.response_body = replace_bundle_urls(FHIR.from_contents(response.body)).to_json
|
57
|
-
end
|
58
|
-
|
59
|
-
def everything_response(request, test = nil, test_result = nil)
|
60
|
-
response = server_proxy.get('Patient/999/$everything') #TODO: Change from static response
|
61
|
-
request.status = response.status
|
62
|
-
request.response_headers = remove_transfer_encoding_header(response.headers)
|
63
|
-
request.response_body = replace_bundle_urls(FHIR.from_contents(response.body)).to_json
|
64
|
-
end
|
65
|
-
|
66
|
-
def export_response(request, test = nil, test_result = nil)
|
67
|
-
headers_as_hash = request.request_headers.map { |header| {"#{header.name}": header.value}}.reduce({}) { |reduced, curr| reduced.merge(curr)}
|
68
|
-
response = server_proxy.get do |req|
|
69
|
-
req.url 'Group/pdex-Group/$export' #TODO: change from static response
|
70
|
-
req.headers = headers_as_hash.merge(server_proxy.headers)
|
71
|
-
end
|
72
|
-
request.status = response.status
|
73
|
-
request.response_headers = response.env.response_headers
|
74
|
-
request.response_header("content-location").value.gsub!(/(.*)\?/, "#{new_link}/$export-poll-status?")
|
75
|
-
request.response_body = response.body
|
76
|
-
end
|
77
|
-
|
78
|
-
def export_status_response(request, test = nil, test_result = nil)
|
79
|
-
headers_as_hash = request.request_headers.map { |header| {"#{header.name}": header.value}}.reduce({}) { |reduced, curr| reduced.merge(curr)}
|
80
|
-
response = server_proxy.get do |req|
|
81
|
-
req.url '$export-poll-status'
|
82
|
-
req.params = request.query_parameters
|
83
|
-
req.headers = headers_as_hash.merge(server_proxy.headers)
|
84
|
-
end
|
85
|
-
request.status = response.status
|
86
|
-
request.response_headers = remove_transfer_encoding_header(response.env.response_headers)
|
87
|
-
request.response_body = response.status.to_i == 200 ? replace_export_urls(JSON.parse(response.body)).to_json : response.body
|
88
|
-
request.response_header("content-length").value = request.response_body.length
|
89
|
-
end
|
90
|
-
|
91
|
-
def binary_read_response(request, test = nil, test_result = nil)
|
92
|
-
binary_id = request.url.split('/').last
|
93
|
-
response = server_proxy.get('Binary/'+binary_id)
|
94
|
-
request.status = response.status
|
95
|
-
request.response_headers = response.headers
|
96
|
-
request.response_body = response.body
|
97
|
-
end
|
98
|
-
|
99
|
-
def member_match_response(request, test = nil, test_result = nil)
|
100
|
-
#remove token from request as well
|
101
|
-
original_request_as_hash = JSON.parse(request.request_body).to_h
|
102
|
-
request.request_body = original_request_as_hash.to_json
|
103
|
-
#TODO: Change from static response
|
104
|
-
request.response_body = {
|
105
|
-
resourceType: "Parameters",
|
106
|
-
parameter: [
|
107
|
-
{
|
108
|
-
name: "MemberIdentifier",
|
109
|
-
valueIdentifier: {
|
110
|
-
type: {
|
111
|
-
coding: [
|
112
|
-
{
|
113
|
-
system: "http://terminology.hl7.org/CodeSystem/v2-0203",
|
114
|
-
code: "MB"
|
115
|
-
}
|
116
|
-
]
|
117
|
-
},
|
118
|
-
system: "https://github.com/inferno-framework/target-payer/identifiers/member",
|
119
|
-
value: "99999",
|
120
|
-
assigner: {
|
121
|
-
display: "Old Payer"
|
122
|
-
}
|
123
|
-
}
|
124
|
-
}
|
125
|
-
]
|
126
|
-
}.to_json
|
127
|
-
request.status = 200
|
128
|
-
end
|
129
|
-
|
130
|
-
def get_metadata
|
131
|
-
proc { [200, {'Content-Type' => 'application/fhir+json;charset=utf-8'}, [File.read("lib/davinci_pdex_test_kit/metadata/mock_capability_statement.json")]] }
|
132
|
-
end
|
133
|
-
|
134
|
-
def remove_transfer_encoding_header(headers)
|
135
|
-
if !headers["transfer-encoding"].nil?
|
136
|
-
headers.reject!{|key, value| key == "transfer-encoding"}
|
137
|
-
else
|
138
|
-
headers
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def match_request_to_expectation(endpoint, params)
|
143
|
-
matched_search = SEARCHES_BY_PRIORITY[endpoint.to_sym].find {|expectation| (params.keys.map{|key| key.to_s} & expectation).sort == expectation}
|
144
|
-
# matched_search_without_patient = SEARCHES_BY_PRIORITY[endpoint.to_sym].find {|expectation| (params.keys.map{|key| key.to_s} << "patient" & expectation) == expectation}
|
145
|
-
|
146
|
-
if matched_search
|
147
|
-
params.select {|key, value| matched_search.include?(key.to_s) || key == "_revInclude" || key == "_include"}
|
148
|
-
else
|
149
|
-
nil
|
150
|
-
end
|
151
|
-
# else
|
152
|
-
# new_params = params.select {|key, value| matched_search_without_patient.include?(key.to_s) || key == "_revInclude" || key == "_include"}
|
153
|
-
# new_params["patient"] = patient_id_from_match_request
|
154
|
-
# new_params
|
155
|
-
# end
|
156
|
-
end
|
157
|
-
|
158
|
-
def extract_client_id(request)
|
159
|
-
URI.decode_www_form(request.request_body).to_h['client_id']
|
160
|
-
end
|
161
|
-
|
162
|
-
# Header expected to be a bearer token of the form "Bearer: <token>"
|
163
|
-
def extract_bearer_token(request)
|
164
|
-
request.request_header('Authorization')&.value&.split&.last
|
165
|
-
end
|
166
|
-
|
167
|
-
def extract_token_from_query_params(request)
|
168
|
-
request.query_parameters['token']
|
169
|
-
end
|
170
|
-
|
171
|
-
# Pull resource type from url
|
172
|
-
# e.g. http://example.org/fhir/Patient/123 -> Patient
|
173
|
-
# @private
|
174
|
-
def resource_endpoint(url)
|
175
|
-
return unless url.start_with?('http://', 'https://')
|
176
|
-
|
177
|
-
/custom\/pdex_payer_client\/fhir\/(.*)\?/.match(url)[1]
|
178
|
-
end
|
179
|
-
|
180
|
-
# @private
|
181
|
-
def referenced_entities(resource, entries, root_url)
|
182
|
-
matches = []
|
183
|
-
attributes = resource&.source_hash&.keys
|
184
|
-
attributes.each do |attr|
|
185
|
-
value = resource.send(attr.to_sym)
|
186
|
-
if value.is_a?(FHIR::Reference) && value.reference.present?
|
187
|
-
match = find_matching_entry(value.reference, entries, root_url)
|
188
|
-
if match.present? && matches.none?(match)
|
189
|
-
value.reference = match.fullUrl
|
190
|
-
matches.concat([match], referenced_entities(match.resource, entries, root_url))
|
191
|
-
end
|
192
|
-
elsif value.is_a?(Array) && value.all? { |elmt| elmt.is_a?(FHIR::Model) }
|
193
|
-
value.each { |val| matches.concat(referenced_entities(val, entries, root_url)) }
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
matches
|
198
|
-
end
|
199
|
-
|
200
|
-
def mock_operation_outcome_resource
|
201
|
-
FHIR.from_contents(File.read("lib/davinci_pdex_test_kit/metadata/mock_operation_outcome_resource.json"))
|
202
|
-
end
|
203
|
-
|
204
|
-
def replace_bundle_urls(bundle)
|
205
|
-
reference_server_base = ENV.fetch('FHIR_REFERENCE_SERVER')
|
206
|
-
bundle&.link.map! {|link| {relation: link.relation, url: link.url.gsub(reference_server_base, new_link)}}
|
207
|
-
bundle&.entry&.map! do |bundled_resource|
|
208
|
-
{fullUrl: bundled_resource.fullUrl.gsub(reference_server_base, new_link),
|
209
|
-
resource: bundled_resource.resource,
|
210
|
-
search: bundled_resource.search
|
211
|
-
}
|
212
|
-
end
|
213
|
-
bundle
|
214
|
-
end
|
215
|
-
|
216
|
-
def replace_export_urls(export_status_output)
|
217
|
-
reference_server_base = ENV.fetch('FHIR_REFERENCE_SERVER')
|
218
|
-
export_status_output['output'].map! { |binary| {type: binary["type"], url: binary["url"].gsub(reference_server_base, new_link)} }
|
219
|
-
export_status_output['request'] = new_link + '/Patient/$export'
|
220
|
-
export_status_output
|
221
|
-
end
|
222
|
-
|
223
|
-
def new_link
|
224
|
-
"#{Inferno::Application['base_url']}\/custom\/pdex_payer_client\/fhir"
|
225
|
-
end
|
226
|
-
|
227
|
-
# @private
|
228
|
-
def absolute_reference(ref, entries, root_url)
|
229
|
-
url = find_matching_entry(ref&.reference, entries, root_url)&.fullUrl
|
230
|
-
ref.reference = url if url
|
231
|
-
ref
|
232
|
-
end
|
233
|
-
|
234
|
-
def fetch_all_bundled_resources(
|
235
|
-
reply_handler: nil,
|
236
|
-
max_pages: 0,
|
237
|
-
additional_resource_types: [],
|
238
|
-
resource_type: self.resource_type
|
239
|
-
)
|
240
|
-
page_count = 1
|
241
|
-
resources = []
|
242
|
-
bundle = resource
|
243
|
-
resources += bundle&.entry&.map { |entry| entry&.resource }
|
244
|
-
|
245
|
-
until bundle.nil? || (page_count == max_pages && max_pages != 0)
|
246
|
-
|
247
|
-
next_bundle_link = bundle&.link&.find { |link| link.relation == 'next' }&.url
|
248
|
-
reply_handler&.call(response)
|
249
|
-
|
250
|
-
break if next_bundle_link.blank?
|
251
|
-
|
252
|
-
reply = fhir_client.raw_read_url(next_bundle_link)
|
253
|
-
|
254
|
-
store_request('outgoing') { reply }
|
255
|
-
error_message = cant_resolve_next_bundle_message(next_bundle_link)
|
256
|
-
|
257
|
-
assert_response_status(200)
|
258
|
-
assert_valid_json(reply.body, error_message)
|
259
|
-
|
260
|
-
bundle = fhir_client.parse_reply(FHIR::Bundle, fhir_client.default_format, reply)
|
261
|
-
resources += bundle&.entry&.map { |entry| entry&.resource }
|
262
|
-
|
263
|
-
page_count += 1
|
264
|
-
end
|
265
|
-
valid_resource_types = [resource_type, 'OperationOutcome'].concat(additional_resource_types)
|
266
|
-
resources
|
267
|
-
end
|
268
|
-
|
269
|
-
# @private
|
270
|
-
def find_matching_entry(ref, entries, root_url = '')
|
271
|
-
ref = "#{root_url}/#{ref}" if relative_reference?(ref) && root_url&.present?
|
272
|
-
|
273
|
-
entries&.find { |entry| entry&.fullUrl == ref }
|
274
|
-
end
|
275
|
-
|
276
|
-
# @private
|
277
|
-
def relative_reference?(ref)
|
278
|
-
ref&.count('/') == 1
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require_relative '../../urls'
|
2
|
-
|
3
|
-
module DaVinciPDexTestKit
|
4
|
-
class PDexClientMemberMatchSubmitTest < Inferno::Test
|
5
|
-
include URLs
|
6
|
-
|
7
|
-
id :initial_member_match_submit_test
|
8
|
-
title 'Client makes a $member-match request'
|
9
|
-
description %(
|
10
|
-
This test will await a $member-match request and proceed once a request is received.
|
11
|
-
)
|
12
|
-
input :access_token
|
13
|
-
|
14
|
-
run do
|
15
|
-
wait(
|
16
|
-
identifier: access_token,
|
17
|
-
message: %(
|
18
|
-
Access Token: #{access_token} \n
|
19
|
-
Submit a PDex $member-match request to `#{member_match_url}`.
|
20
|
-
)
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative '../../urls'
|
2
|
-
|
3
|
-
module DaVinciPDexTestKit
|
4
|
-
class PDexClientMemberMatchMustSupportSubmitTest < Inferno::Test
|
5
|
-
include URLs
|
6
|
-
|
7
|
-
id :initial_member_match_must_support_submit_test
|
8
|
-
title '$member-match requests span all Must Supports'
|
9
|
-
description %(
|
10
|
-
This test will receive $member-match requests until the user specifies they are done. It then checks all received $member-match requests for Must Support coverage.
|
11
|
-
)
|
12
|
-
input :access_token
|
13
|
-
config options: { accepts_multiple_requests: true }
|
14
|
-
|
15
|
-
run do
|
16
|
-
wait(
|
17
|
-
identifier: access_token,
|
18
|
-
message: %(
|
19
|
-
Access Token: #{access_token} \n
|
20
|
-
Submit PDex $member-match request(s) to `#{member_match_url}`, and [click here](#{resume_pass_url}?token=#{access_token}) when all Must Support
|
21
|
-
elements have been covered.
|
22
|
-
)
|
23
|
-
)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require_relative '../client_validation_test.rb'
|
2
|
-
require_relative '../../group_metadata.rb'
|
3
|
-
|
4
|
-
module DaVinciPDexTestKit
|
5
|
-
class PDexInitialMemberMatchMustSupportValidationTest < Inferno::Test
|
6
|
-
include DaVinciPDexTestKit::MustSupportTest
|
7
|
-
include DaVinciPDexTestKit::ClientValidationTest
|
8
|
-
include URLs
|
9
|
-
|
10
|
-
id :initial_member_match_must_support_validation_test
|
11
|
-
title 'All must support elements are provided in the received $member-match requests'
|
12
|
-
description %(
|
13
|
-
This test verifies that the client is capable of making $member-match requests
|
14
|
-
)
|
15
|
-
input :access_token
|
16
|
-
|
17
|
-
def resource_type
|
18
|
-
'Parameters'
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.metadata
|
22
|
-
@metadata ||= DaVinciPDexTestKit::GroupMetadata.new(YAML.load_file(File.join(__dir__, 'metadata.yml'), aliases: true))
|
23
|
-
end
|
24
|
-
|
25
|
-
run do
|
26
|
-
|
27
|
-
assert all_member_match_requests, "No previous $member-match requests received"
|
28
|
-
|
29
|
-
perform_must_support_test(all_member_match_requests.map {|match_request| FHIR::Parameters.new(JSON.parse(match_request.request_body).to_h)})
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
---
|
2
|
-
:name: hrex_member_match_request_parameters
|
3
|
-
:class_name: HRexMemberMatchRequestParameters
|
4
|
-
:version: 1.0.0
|
5
|
-
:reformatted_version: v1.0.0
|
6
|
-
:resource: Parameters
|
7
|
-
:profile_url: http://hl7.org/fhir/us/davinci-hrex/StructureDefinition/hrex-parameters-member-match-in
|
8
|
-
:profile_name: HRex Member Match Request Parameters
|
9
|
-
:profile_version: 1.0.0
|
10
|
-
:title: Member Match Request Parameters
|
11
|
-
:short_description: "The Parameters profile for Da Vinci Find Member using Patient and Coverage Resources Request. The resource must contain: \n * MemberPatient - US Core Patient containing member demographics \n * CoverageToMatch - details of prior health plan coverage provided by the member, typically from their health plan coverage card \n * CoverageToLink - details of new or prospective health plan coverage, provided by the health plan based upon the member's enrolment"
|
12
|
-
:is_delayed: false
|
13
|
-
:interactions: []
|
14
|
-
:operations: []
|
15
|
-
:include_params: []
|
16
|
-
:revincludes: []
|
17
|
-
:required_concepts: []
|
18
|
-
:must_supports:
|
19
|
-
:extensions: []
|
20
|
-
:slices:
|
21
|
-
- :slice_id: Parameters.parameter:MemberPatient
|
22
|
-
:slice_name: MemberPatient
|
23
|
-
:path: parameter
|
24
|
-
:discriminator:
|
25
|
-
:type: value
|
26
|
-
:values:
|
27
|
-
- :path: name
|
28
|
-
:value: MemberPatient
|
29
|
-
- :slice_id: Parameters.parameter:CoverageToMatch
|
30
|
-
:slice_name: CoverageToMatch
|
31
|
-
:path: parameter
|
32
|
-
:discriminator:
|
33
|
-
:type: value
|
34
|
-
:values:
|
35
|
-
- :path: name
|
36
|
-
:value: CoverageToMatch
|
37
|
-
- :slice_id: Parameters.parameter:CoverageToLink
|
38
|
-
:slice_name: CoverageToLink
|
39
|
-
:path: parameter
|
40
|
-
:discriminator:
|
41
|
-
:type: value
|
42
|
-
:values:
|
43
|
-
- :path: name
|
44
|
-
:value: CoverageToLink
|
45
|
-
- :slice_id: Parameters.parameter:Consent
|
46
|
-
:slice_name: Consent
|
47
|
-
:path: parameter
|
48
|
-
:discriminator:
|
49
|
-
:type: value
|
50
|
-
:values:
|
51
|
-
- :path: name
|
52
|
-
:value: Consent
|
53
|
-
:elements:
|
54
|
-
- :path: parameter:MemberPatient.resource
|
55
|
-
- :path: parameter:CoverageToMatch.resource
|
56
|
-
- :path: parameter:CoverageToLink.resource
|
57
|
-
- :path: parameter:Consent.resource
|
58
|
-
:mandatory_elements:
|
59
|
-
|
60
|
-
|
61
|
-
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require_relative '../client_validation_test.rb'
|
2
|
-
module DaVinciPDexTestKit
|
3
|
-
class PDexClientScratchStorage < Inferno::Test
|
4
|
-
include DaVinciPDexTestKit::ClientValidationTest
|
5
|
-
|
6
|
-
id :initial_scratch_storing
|
7
|
-
title 'Client makes clinical data requests that capture an entire patient'
|
8
|
-
description %(
|
9
|
-
This test organizes the received requests in order to validate all expected specific resources were returned
|
10
|
-
)
|
11
|
-
input :access_token
|
12
|
-
|
13
|
-
run do
|
14
|
-
previous_clinical_data_request_resources.each do |request, resources|
|
15
|
-
resources.each do |resource|
|
16
|
-
scratch[resource.resourceType.to_sym] ||= []
|
17
|
-
scratch[resource.resourceType.to_sym] |= [resource]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
if !export_resources.empty?
|
21
|
-
info "Attempted an $export request"
|
22
|
-
export_resources.each do |resource|
|
23
|
-
scratch[resource.resourceType.to_sym] ||= []
|
24
|
-
scratch[resource.resourceType.to_sym] |= [resource]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
if everything_request
|
28
|
-
info "Attempted an $everything request"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/lib/davinci_pdex_test_kit/pdex_payer_client/clinical_data_request_tests/initial_wait_test.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require_relative '../../urls'
|
2
|
-
module DaVinciPDexTestKit
|
3
|
-
class PDexClientSubmitMustSupportTest < Inferno::Test
|
4
|
-
include URLs
|
5
|
-
|
6
|
-
id :initial_wait_test
|
7
|
-
title 'Client makes clinical data requests'
|
8
|
-
description %(
|
9
|
-
This test will receive clinical data requests until the user confirms they are done.
|
10
|
-
)
|
11
|
-
input :access_token
|
12
|
-
config options: { accepts_multiple_requests: true }
|
13
|
-
|
14
|
-
run do
|
15
|
-
wait(
|
16
|
-
identifier: access_token,
|
17
|
-
message: %(
|
18
|
-
Access Token: #{access_token} \n
|
19
|
-
Submit PDex requests via at least one of the following methods:
|
20
|
-
* Single Resource API: `#{submit_url}`, with `:endpoint` replaced with the endpoint you want to reach
|
21
|
-
* $everything method: `#{everything_url}`, with `:patient` replaced with the patient you are matching
|
22
|
-
* $export method: `#{export_url}`, see workflow process at the [Bulk Data IG](https://hl7.org/fhir/uv/bulkdata/STU2/)
|
23
|
-
* $export-poll-status: `#{export_status_url}`, then continue to make reads from the binaries if a payload is delivered
|
24
|
-
|
25
|
-
and [click here](#{resume_clinical_data_url}?token=#{access_token}) when done.
|
26
|
-
),
|
27
|
-
timeout: 900
|
28
|
-
)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DaVinciPDexTestKit
|
4
|
-
AUTH_TAG = 'pdex_auth'
|
5
|
-
SUBMIT_TAG = 'pdex_submit'
|
6
|
-
BINARY_TAG = 'pdex_binary'
|
7
|
-
EXPORT_TAG = 'pdex_export'
|
8
|
-
EXPORT_STATUS_TAG = 'pdex_export_status'
|
9
|
-
EVERYTHING_TAG = 'pdex_everything'
|
10
|
-
MEMBER_MATCH_TAG = 'pdex_member_match'
|
11
|
-
end
|