service_base_url_test_kit 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/service_base_url_test_kit/examples/SmartAccessBrand.json.erb +105 -0
- data/lib/service_base_url_test_kit/service_base_url_retrieve_group.rb +13 -13
- data/lib/service_base_url_test_kit/service_base_url_test_group.rb +46 -19
- data/lib/service_base_url_test_kit/service_base_url_validate_group.rb +194 -64
- data/lib/service_base_url_test_kit/version.rb +1 -1
- data/lib/service_base_url_test_kit.rb +36 -18
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 638bed4317d3630a7ffdfbc9cef4be2dc266ab285de017d890a1ceadec4858fc
|
4
|
+
data.tar.gz: fab6cb020b68f87db82348891f3b80eb0d5e3bc9181639c9bf1b5a9505611de4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61b58536e24b25039953dc99cc4a507202c08297a8be0f70edb0d340ec0fa77824dbaee0de8be5bb548306eaf5c0e5b47dc143405882ebb5f91537bd258ccb68
|
7
|
+
data.tar.gz: 1fccec1d67cb3642771fa89360e90b3ad9f157bed70d35ee5beb09324cc5b649f74554638df4202834ffba3ca43c1578751477df79eb7c626707371ace21d205
|
@@ -0,0 +1,105 @@
|
|
1
|
+
{
|
2
|
+
"resourceType" : "Bundle",
|
3
|
+
"id" : "example1",
|
4
|
+
"type" : "collection",
|
5
|
+
"timestamp" : "2023-09-05T20:00:43.241070-07:00",
|
6
|
+
"entry" : [{
|
7
|
+
"fullUrl" : "https://fhir.labs.example.com/Organization/examplelabs",
|
8
|
+
"resource" : {
|
9
|
+
"resourceType" : "Organization",
|
10
|
+
"id" : "examplelabs",
|
11
|
+
"extension" : [{
|
12
|
+
"extension" : [{
|
13
|
+
"url" : "brandLogo",
|
14
|
+
"valueUrl" : "https://labs.example.com/images/logo.svg"
|
15
|
+
}],
|
16
|
+
"url" : "http://hl7.org/fhir/StructureDefinition/organization-brand"
|
17
|
+
},
|
18
|
+
{
|
19
|
+
"extension" : [{
|
20
|
+
"url" : "portalName",
|
21
|
+
"valueString" : "Example Labs HealthCentral Portal"
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"url" : "portalUrl",
|
25
|
+
"valueUrl" : "https://healthcentral.labs.example.com"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"url" : "portalLogo",
|
29
|
+
"valueUrl" : "https://healthcentral.labs.example.com/logo.png"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"url" : "portalEndpoint",
|
33
|
+
"valueReference" : {
|
34
|
+
"reference" : "Endpoint/examplelabs",
|
35
|
+
"display" : "FHIR R4 Endpoint for ExampleLabs Brand"
|
36
|
+
}
|
37
|
+
}],
|
38
|
+
"url" : "http://hl7.org/fhir/StructureDefinition/organization-portal"
|
39
|
+
}],
|
40
|
+
"identifier" : [{
|
41
|
+
"system" : "urn:ietf:rfc:3986",
|
42
|
+
"value" : "https://examplelabs.org"
|
43
|
+
}],
|
44
|
+
"active" : true,
|
45
|
+
"type" : [{
|
46
|
+
"coding" : [{
|
47
|
+
"system" : "http://hl7.org/fhir/smart-app-launch/CodeSystem/patient-access-category",
|
48
|
+
"code" : "laboratory",
|
49
|
+
"display" : "Laboratory"
|
50
|
+
}]
|
51
|
+
}],
|
52
|
+
"name" : "ExampleLabs",
|
53
|
+
"alias" : ["ExampleLabs Alaska",
|
54
|
+
"...(more here)...",
|
55
|
+
"ExampleLabs Wisconsin"],
|
56
|
+
"telecom" : [{
|
57
|
+
"system" : "url",
|
58
|
+
"value" : "https://labs.example.com"
|
59
|
+
}],
|
60
|
+
"address" : [{
|
61
|
+
"line" : ["4015 Lake Otis Pkwy"],
|
62
|
+
"city" : "Anchorage",
|
63
|
+
"state" : "AK",
|
64
|
+
"postalCode" : "99508"
|
65
|
+
},
|
66
|
+
{
|
67
|
+
"state" : "...(more here)..."
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"line" : ["123 Main St"],
|
71
|
+
"city" : "Madison",
|
72
|
+
"state" : "WI",
|
73
|
+
"postalCode" : "53726"
|
74
|
+
}]
|
75
|
+
}
|
76
|
+
},
|
77
|
+
{
|
78
|
+
"fullUrl" : "https://fhir.labs.example.com/Endpoint/examplelabs",
|
79
|
+
"resource" : {
|
80
|
+
"resourceType" : "Endpoint",
|
81
|
+
"id" : "examplelabs",
|
82
|
+
"extension" : [{
|
83
|
+
"url" : "http://hl7.org/fhir/StructureDefinition/endpoint-fhir-version",
|
84
|
+
"valueCode" : "4.0.1"
|
85
|
+
}],
|
86
|
+
"status" : "active",
|
87
|
+
"connectionType" : {
|
88
|
+
"system" : "http://terminology.hl7.org/CodeSystem/endpoint-connection-type",
|
89
|
+
"code" : "hl7-fhir-rest"
|
90
|
+
},
|
91
|
+
"name" : "FHIR R4 Endpoint for ExampleLabs",
|
92
|
+
"contact" : [{
|
93
|
+
"system" : "url",
|
94
|
+
"value" : "https://dev-portal.labs.example.com"
|
95
|
+
}],
|
96
|
+
"payloadType" : [{
|
97
|
+
"coding" : [{
|
98
|
+
"system" : "http://terminology.hl7.org/CodeSystem/endpoint-payload-type",
|
99
|
+
"code" : "none"
|
100
|
+
}]
|
101
|
+
}],
|
102
|
+
"address" : "<%= ENV['INFERNO_HOST'] %>/custom/service_base_url_test_kit_suite/examples/CapabilityStatement"
|
103
|
+
}
|
104
|
+
}]
|
105
|
+
}
|
@@ -1,40 +1,40 @@
|
|
1
1
|
module ServiceBaseURLTestKit
|
2
2
|
class ServiceBaseURLEndpointQueryGroup < Inferno::TestGroup
|
3
3
|
id :service_base_url_retrieve_list
|
4
|
-
title 'Retrieve Service Base URL
|
4
|
+
title 'Retrieve Service Base URL Publication'
|
5
5
|
description %(
|
6
|
-
A developer's Service Base URL
|
6
|
+
A developer's Service Base URL publication must be publicly available. This test
|
7
7
|
issues a HTTP GET request against the supplied URL and expects to receive
|
8
|
-
the service base url
|
8
|
+
the service base url publication at this location.
|
9
9
|
)
|
10
10
|
run_as_group
|
11
11
|
|
12
|
-
input :service_base_url_list_url,
|
13
|
-
title: 'Service Base URL List URL',
|
14
|
-
description: 'The URL to the developer\'s public Service Base URL List'
|
15
|
-
|
16
12
|
http_client do
|
17
|
-
url :
|
18
|
-
headers
|
13
|
+
url :service_base_url_publication_url
|
14
|
+
headers Accept: 'application/json, application/fhir+json'
|
19
15
|
end
|
20
16
|
|
21
17
|
test do
|
22
18
|
id :service_base_url_retrieve_list_test
|
23
|
-
title 'Server returns publicly accessible Service Base URL
|
19
|
+
title 'Server returns publicly accessible Service Base URL Publication'
|
24
20
|
description %(
|
25
21
|
Verify that the developer's list of Service Base URLs can be publicly
|
26
22
|
accessed at the supplied URL location.
|
27
23
|
)
|
28
24
|
|
25
|
+
input :service_base_url_publication_url,
|
26
|
+
optional: true
|
27
|
+
|
29
28
|
output :bundle_response
|
30
29
|
|
31
30
|
makes_request :bundle_request
|
32
31
|
|
33
32
|
run do
|
34
|
-
|
33
|
+
omit_if service_base_url_publication_url.blank?, 'URL for Service Base URL Publication not Inputted.'
|
34
|
+
|
35
|
+
get(tags: ['service_base_url_bundle'])
|
35
36
|
assert_response_status(200)
|
36
|
-
|
37
|
-
end
|
37
|
+
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -4,26 +4,53 @@ require_relative 'service_base_url_retrieve_group'
|
|
4
4
|
module ServiceBaseURLTestKit
|
5
5
|
class ServiceBaseURLGroup < Inferno::TestGroup
|
6
6
|
id :service_base_url_test_group
|
7
|
-
title '
|
8
|
-
description %(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
7
|
+
title 'Validate Service Base URL Publication'
|
8
|
+
description %(
|
9
|
+
Verify that the developer makes its Service Base URL publication publicly available
|
10
|
+
in the Bundle resource format with valid Endpoint and Organization entries.
|
11
|
+
This test group will issue a HTTP GET request against the supplied URL to
|
12
|
+
retrieve the developer's Service Base URL publication and ensure the list is
|
13
|
+
publicly accessible. It will then ensure that the returned service base URL
|
14
|
+
publication is in the Bundle resource format containing its service base URLs and
|
15
|
+
related organizational details in valid Endpoint and Organization resources
|
16
|
+
that follow the specifications detailed in the HTI-1 rule and the API
|
17
|
+
Condition and Maintenance of Certification.
|
18
|
+
|
19
|
+
For systems that provide the service base URL Bundle at a URL, please run
|
20
|
+
this test with the Service Base URL Publication URL input populated and the Service Base URL Publication Bundle
|
21
|
+
input left blank. While it is the expectation of the specification for the service base URL Bundle to be served at a
|
22
|
+
public-facing endpoint, testers can validate a Service Base URL Bundle not served at a public endpoint by running
|
23
|
+
these tests with the Service Base URL Publication Bundle input populated and the Service Base URL Publication URL
|
24
|
+
input left blank.
|
25
25
|
)
|
26
|
-
|
26
|
+
|
27
|
+
input_instructions <<~INSTRUCTIONS
|
28
|
+
For systems that make their Service Base URL Bundle available at a public endpoint, please input
|
29
|
+
the Service Base URL Publication URL to retrieve the Bundle from there in order to perform validation.
|
30
|
+
|
31
|
+
For systems that do not have a Service Base URL Bundle served at a public endpoint, testers can validate by
|
32
|
+
providing the Service Base URL Publication Bundle as an input and leaving the Service Base URL Publication URL
|
33
|
+
input blank.
|
34
|
+
INSTRUCTIONS
|
35
|
+
|
36
|
+
run_as_group
|
37
|
+
|
38
|
+
input :service_base_url_publication_url,
|
39
|
+
title: 'Service Base URL Publication URL',
|
40
|
+
description: %(The URL to the developer's public Service Base URL Publication. Insert your Service Base URL
|
41
|
+
publication URL if you host your Bundle at a public-facing endpoint and want Inferno to retrieve the Bundle
|
42
|
+
from there.),
|
43
|
+
optional: true
|
44
|
+
|
45
|
+
input :service_base_url_bundle,
|
46
|
+
title: 'Service Base URL Publication Bundle',
|
47
|
+
description: %(The developer's Service Base URL Publication in the JSON string format. If this input is
|
48
|
+
populated, Inferno will use the Bundle inserted here to do validation. Insert your Service Base URL
|
49
|
+
Publication Bundle in the JSON format in this input to validate your list without Inferno needing to access
|
50
|
+
the Bundle via a public-facing endpoint.),
|
51
|
+
type: 'textarea',
|
52
|
+
optional: true
|
53
|
+
|
27
54
|
group from: :service_base_url_retrieve_list
|
28
55
|
group from: :service_base_url_validate_list
|
29
56
|
end
|
@@ -1,41 +1,87 @@
|
|
1
1
|
module ServiceBaseURLTestKit
|
2
2
|
class ServiceBaseURLBundleTestGroup < Inferno::TestGroup
|
3
3
|
id :service_base_url_validate_list
|
4
|
-
title 'Validate Service Base URL
|
4
|
+
title 'Validate Service Base URL Publication'
|
5
5
|
description %(
|
6
6
|
These tests ensure that the developer's Service Base URL publication is in
|
7
7
|
the Bundle resource format, with its service base URLs and organizational
|
8
8
|
details contained in valid Endpoint and Organization entries that follow
|
9
9
|
the specifications detailed in the HTI-1 rule and the API Condition and
|
10
10
|
Maintenance of Certification.
|
11
|
+
|
12
|
+
These tests may be run individually, bypassing the first test group, if the Service Base URL Publication Bundle
|
13
|
+
input is populated and the Service Base URL Publication URL is left blank (or if it does not successfully return
|
14
|
+
a Service Base URL Publication Bundle). You may insert your Service Base URL Publication Bundle in the JSON
|
15
|
+
format in the Service Base URL Publication Bundle input to validate your list without Inferno needing to retrieve
|
16
|
+
the Bundle via a public-facing endpoint.
|
11
17
|
)
|
12
18
|
run_as_group
|
13
19
|
|
14
|
-
input :
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
input :service_base_url_bundle,
|
21
|
+
optional: true
|
22
|
+
|
23
|
+
input :endpoint_availability_success_rate,
|
24
|
+
title: 'Endpoint Availability Success Rate',
|
25
|
+
description: %(
|
26
|
+
Select an option to choose how many Endpoints have to be available and send back a valid capability
|
27
|
+
statement for the Endpoint validation test to pass.
|
28
|
+
),
|
29
|
+
type: 'radio',
|
30
|
+
options: {
|
31
|
+
list_options: [
|
32
|
+
{
|
33
|
+
label: 'All',
|
34
|
+
value: 'all'
|
35
|
+
},
|
36
|
+
{
|
37
|
+
label: 'At Least One',
|
38
|
+
value: 'at_least_1'
|
39
|
+
},
|
40
|
+
{
|
41
|
+
label: 'None',
|
42
|
+
value: 'none'
|
43
|
+
}
|
44
|
+
]
|
45
|
+
},
|
46
|
+
default: 'all'
|
47
|
+
|
48
|
+
input :endpoint_availability_limit,
|
49
|
+
title: 'Endpoint Availability Limit',
|
50
|
+
description: %(
|
51
|
+
In the case where the Endpoint Availability Success Rate is 'All', input a number to cap the number of
|
52
|
+
Endpoints that Inferno will send requests to check for availability. This can help speed up validation when
|
53
|
+
there are large number of endpoints in the Service Base URL Bundle.
|
54
|
+
),
|
55
|
+
optional: true
|
18
56
|
|
19
57
|
# @private
|
20
58
|
def find_referenced_org(bundle_resource, endpoint_id)
|
21
59
|
bundle_resource
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
60
|
+
.entry
|
61
|
+
.map(&:resource)
|
62
|
+
.select { |resource| resource.resourceType == 'Organization' }
|
63
|
+
.map(&:endpoint)
|
64
|
+
.flatten
|
65
|
+
.map(&:reference)
|
66
|
+
.select { |reference| reference.include? endpoint_id }
|
29
67
|
end
|
30
68
|
|
31
69
|
# @private
|
32
70
|
def find_referenced_endpoint(bundle_resource, endpoint_id_ref)
|
33
71
|
bundle_resource
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
72
|
+
.entry
|
73
|
+
.map(&:resource)
|
74
|
+
.select { |resource| resource.resourceType == 'Endpoint' }
|
75
|
+
.map(&:id)
|
76
|
+
.select { |endpoint_id| endpoint_id_ref.include? endpoint_id }
|
77
|
+
end
|
78
|
+
|
79
|
+
def skip_message
|
80
|
+
%(
|
81
|
+
No Service Base URL request was made in the previous test, and no Service Base URL Publication Bundle
|
82
|
+
was provided as input instead. Either provide a Service Base URL Publication URL to retrieve the Bundle via a
|
83
|
+
HTTP GET request, or provide the Bundle as an input.
|
84
|
+
)
|
39
85
|
end
|
40
86
|
|
41
87
|
# Valid BUNDLE TESTS
|
@@ -47,8 +93,16 @@ module ServiceBaseURLTestKit
|
|
47
93
|
)
|
48
94
|
|
49
95
|
run do
|
96
|
+
bundle_response = if service_base_url_bundle.blank?
|
97
|
+
load_tagged_requests('service_base_url_bundle')
|
98
|
+
skip skip_message if requests.length != 1
|
99
|
+
requests.first.response_body
|
100
|
+
else
|
101
|
+
service_base_url_bundle
|
102
|
+
end
|
50
103
|
skip_if bundle_response.blank?, 'No Bundle response was provided'
|
51
104
|
|
105
|
+
assert_valid_json(bundle_response)
|
52
106
|
bundle_resource = FHIR.from_contents(bundle_response)
|
53
107
|
assert_valid_resource(resource: bundle_resource)
|
54
108
|
|
@@ -58,13 +112,24 @@ module ServiceBaseURLTestKit
|
|
58
112
|
The given Bundle does not contain any resources
|
59
113
|
)
|
60
114
|
end
|
115
|
+
|
116
|
+
additional_resources = bundle_resource.entry
|
117
|
+
.map { |entry| entry.resource.resourceType }
|
118
|
+
.reject { |resource_type| ['Organization', 'Endpoint'].include?(resource_type) }
|
119
|
+
.uniq
|
120
|
+
|
121
|
+
warning do
|
122
|
+
assert(additional_resources.empty?, %(
|
123
|
+
The Service Base URL List contained the following additional resources other than Endpoint and
|
124
|
+
Organization resources: #{additional_resources.join(', ')}))
|
125
|
+
end
|
61
126
|
end
|
62
127
|
end
|
63
128
|
|
64
129
|
# VALID ENDPOINT TESTS
|
65
130
|
test do
|
66
131
|
id :service_base_url_valid_endpoints
|
67
|
-
title 'Service Base URL
|
132
|
+
title 'Service Base URL Publication contains valid Endpoint resources'
|
68
133
|
description %(
|
69
134
|
Verify that Bundle of Service Base URLs contains Endpoints that are
|
70
135
|
valid Endpoint resources according to the format defined in FHIR v4.0.1.
|
@@ -79,18 +144,24 @@ module ServiceBaseURLTestKit
|
|
79
144
|
)
|
80
145
|
|
81
146
|
run do
|
82
|
-
|
147
|
+
bundle_response = if service_base_url_bundle.blank?
|
148
|
+
load_tagged_requests('service_base_url_bundle')
|
149
|
+
skip skip_message if requests.length != 1
|
150
|
+
requests.first.response_body
|
151
|
+
else
|
152
|
+
service_base_url_bundle
|
153
|
+
end
|
83
154
|
skip_if bundle_response.blank?, 'No Bundle response was provided'
|
84
155
|
|
156
|
+
assert_valid_json(bundle_response)
|
85
157
|
bundle_resource = FHIR.from_contents(bundle_response)
|
86
158
|
|
87
159
|
skip_if bundle_resource.entry.empty?, 'The given Bundle does not contain any resources'
|
88
160
|
|
89
161
|
assert_valid_bundle_entries(bundle: bundle_resource,
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
)
|
162
|
+
resource_types: {
|
163
|
+
Endpoint: nil
|
164
|
+
})
|
94
165
|
|
95
166
|
endpoint_ids =
|
96
167
|
bundle_resource
|
@@ -99,11 +170,10 @@ module ServiceBaseURLTestKit
|
|
99
170
|
.select { |resource| resource.resourceType == 'Endpoint' }
|
100
171
|
.map(&:id)
|
101
172
|
|
102
|
-
|
103
|
-
for endpoint_id in endpoint_ids
|
173
|
+
endpoint_ids.each do |endpoint_id|
|
104
174
|
endpoint_referenced_orgs = find_referenced_org(bundle_resource, endpoint_id)
|
105
|
-
assert !endpoint_referenced_orgs.empty?,
|
106
|
-
|
175
|
+
assert !endpoint_referenced_orgs.empty?,
|
176
|
+
"Endpoint with id: #{endpoint_id} does not have any associated Organizations in the Bundle."
|
107
177
|
end
|
108
178
|
end
|
109
179
|
end
|
@@ -113,45 +183,91 @@ module ServiceBaseURLTestKit
|
|
113
183
|
id :service_base_url_valid_urls
|
114
184
|
title 'All Endpoint resource referenced URLS should be valid and available'
|
115
185
|
description %(
|
116
|
-
Verify that Bundle of Service Base URLs contains Endpoints that contain service base URLs that are both valid
|
186
|
+
Verify that Bundle of Service Base URLs contains Endpoints that contain service base URLs that are both valid
|
187
|
+
and available.
|
117
188
|
)
|
118
189
|
|
119
|
-
output :testing
|
120
|
-
|
121
190
|
run do
|
191
|
+
bundle_response = if service_base_url_bundle.blank?
|
192
|
+
load_tagged_requests('service_base_url_bundle')
|
193
|
+
skip skip_message if requests.length != 1
|
194
|
+
requests.first.response_body
|
195
|
+
else
|
196
|
+
service_base_url_bundle
|
197
|
+
end
|
122
198
|
skip_if bundle_response.blank?, 'No Bundle response was provided'
|
123
199
|
|
200
|
+
assert_valid_json(bundle_response)
|
124
201
|
bundle_resource = FHIR.from_contents(bundle_response)
|
125
202
|
|
126
203
|
skip_if bundle_resource.entry.empty?, 'The given Bundle does not contain any resources'
|
127
204
|
|
205
|
+
endpoint_list = bundle_resource
|
206
|
+
.entry
|
207
|
+
.map(&:resource)
|
208
|
+
.select { |resource| resource.resourceType == 'Endpoint' }
|
209
|
+
.map(&:address)
|
210
|
+
.uniq
|
211
|
+
|
212
|
+
if endpoint_availability_limit.present? && endpoint_availability_limit.to_i < endpoint_list.count
|
213
|
+
info %(
|
214
|
+
Only the first #{endpoint_availability_limit.to_i} endpoints of #{endpoint_list.count} total will be
|
215
|
+
checked.
|
216
|
+
)
|
217
|
+
end
|
128
218
|
|
129
|
-
|
130
|
-
.
|
131
|
-
.map(&:resource)
|
132
|
-
.select { |resource| resource.resourceType == 'Endpoint' }
|
133
|
-
.map(&:address)
|
134
|
-
.uniq
|
135
|
-
.each do |address|
|
219
|
+
one_endpoint_valid = false
|
220
|
+
endpoint_list.each_with_index do |address, index|
|
136
221
|
assert_valid_http_uri(address)
|
137
222
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
223
|
+
next if endpoint_availability_success_rate == 'none' ||
|
224
|
+
(endpoint_availability_limit.present? && endpoint_availability_limit.to_i <= index)
|
225
|
+
|
226
|
+
address = address.delete_suffix('/')
|
227
|
+
|
228
|
+
response = nil
|
229
|
+
warning do
|
230
|
+
response = get("#{address}/metadata", client: nil, headers: { Accept: 'application/fhir+json' })
|
231
|
+
end
|
232
|
+
|
233
|
+
if endpoint_availability_success_rate == 'all'
|
234
|
+
assert response.present?, "Encountered issues while trying to make a request to #{address}/metadata."
|
235
|
+
assert_response_status(200)
|
236
|
+
assert resource.present?, 'The content received does not appear to be a valid FHIR resource'
|
237
|
+
assert_resource_type(:capability_statement)
|
238
|
+
else
|
239
|
+
if response.present?
|
240
|
+
warning do
|
241
|
+
assert_response_status(200)
|
242
|
+
assert resource.present?, 'The content received does not appear to be a valid FHIR resource'
|
243
|
+
assert_resource_type(:capability_statement)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
if !one_endpoint_valid && response.present? && response.status == 200 && resource.present? &&
|
248
|
+
resource.resourceType == 'CapabilityStatement'
|
249
|
+
one_endpoint_valid = true
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
if endpoint_availability_success_rate == 'at_least_1'
|
255
|
+
assert(one_endpoint_valid, %(
|
256
|
+
There were no Endpoints that were available and returned a valid Capability Statement in the Service Base
|
257
|
+
URL Bundle'
|
258
|
+
))
|
143
259
|
end
|
144
260
|
end
|
145
261
|
end
|
146
262
|
|
147
|
-
|
148
263
|
# ORGANIZATION TESTS
|
149
264
|
test do
|
150
265
|
id :service_base_url_valid_organizations
|
151
|
-
title 'Service Base URL
|
266
|
+
title 'Service Base URL Publication contains valid Organization resources'
|
152
267
|
description %(
|
153
268
|
|
154
|
-
Verify that Bundle of Service Base URLs contains Organizations that are valid Organization resources according
|
269
|
+
Verify that Bundle of Service Base URLs contains Organizations that are valid Organization resources according
|
270
|
+
to the format defined in FHIR v4.0.1.
|
155
271
|
|
156
272
|
Each Organization must:
|
157
273
|
- Contain must have elements including:
|
@@ -165,36 +281,50 @@ module ServiceBaseURLTestKit
|
|
165
281
|
)
|
166
282
|
|
167
283
|
run do
|
284
|
+
bundle_response = if service_base_url_bundle.blank?
|
285
|
+
load_tagged_requests('service_base_url_bundle')
|
286
|
+
skip skip_message if requests.length != 1
|
287
|
+
requests.first.response_body
|
288
|
+
else
|
289
|
+
service_base_url_bundle
|
290
|
+
end
|
168
291
|
skip_if bundle_response.blank?, 'No Bundle response was provided'
|
169
292
|
|
293
|
+
assert_valid_json(bundle_response)
|
170
294
|
bundle_resource = FHIR.from_contents(bundle_response)
|
171
295
|
|
172
296
|
skip_if bundle_resource.entry.empty?, 'The given Bundle does not contain any resources'
|
173
297
|
|
174
298
|
assert_valid_bundle_entries(bundle: bundle_resource,
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
299
|
+
resource_types: {
|
300
|
+
Organization: nil
|
301
|
+
})
|
302
|
+
|
303
|
+
organization_resources = bundle_resource
|
304
|
+
.entry
|
305
|
+
.map(&:resource)
|
306
|
+
.select { |resource| resource.resourceType == 'Organization' }
|
307
|
+
|
308
|
+
warning do
|
309
|
+
# This was requested to be included because a publication with only a single organization
|
310
|
+
# seems like a likely error and should be checked manually.
|
311
|
+
assert(organization_resources.length > 1,
|
312
|
+
'The provided Service Base URL List contains only 1 Organization resource')
|
313
|
+
end
|
189
314
|
|
190
|
-
|
191
|
-
assert !organization.
|
315
|
+
organization_resources.each do |organization|
|
316
|
+
assert !organization.endpoint.empty?,
|
317
|
+
"Organization with id: #{organization.id} does not have the endpoint field populated"
|
318
|
+
assert !organization.address.empty?,
|
319
|
+
"Organization with id: #{organization.id} does not have the address field populated"
|
192
320
|
|
321
|
+
endpoint_references = organization.endpoint.map(&:reference)
|
193
322
|
|
194
|
-
|
323
|
+
endpoint_references.each do |endpoint_id_ref|
|
195
324
|
organization_referenced_endpts = find_referenced_endpoint(bundle_resource, endpoint_id_ref)
|
196
|
-
assert !organization_referenced_endpts.empty?,
|
197
|
-
|
325
|
+
assert !organization_referenced_endpts.empty?,
|
326
|
+
"Organization with id: #{organization.id} references an Endpoint that is not contained in this
|
327
|
+
bundle."
|
198
328
|
end
|
199
329
|
end
|
200
330
|
end
|
@@ -9,7 +9,7 @@ module ServiceBaseURLTestKit
|
|
9
9
|
description %(
|
10
10
|
This Test Kit provides a set of tests that verify conformance of Service
|
11
11
|
Base URL publications to data format requirements as described in
|
12
|
-
[Conditions
|
12
|
+
[Conditions and Maintenance of Certification - Application programming
|
13
13
|
interfaces](https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-D/part-170/subpart-D/section-170.404#p-170.404(b)(2))
|
14
14
|
and the [ONC HTI-1 Final
|
15
15
|
Rule](https://www.healthit.gov/topic/laws-regulation-and-policy/health-data-technology-and-interoperability-certification-program).
|
@@ -17,17 +17,19 @@ module ServiceBaseURLTestKit
|
|
17
17
|
Guide](https://www.healthit.gov/condition-ccg/application-programming-interfaces)
|
18
18
|
for additional guidance.
|
19
19
|
|
20
|
-
This Test Kit is provided as a tool to help developers identify potential
|
21
|
-
or problems with the structure of their Service Base URL
|
22
|
-
failures do not necessarily indicate non-conformance to
|
23
|
-
Maintenance of Certification. Use of these tests is
|
24
|
-
|
20
|
+
This Test Kit is provided as a tool to help developers identify potential
|
21
|
+
issues or problems with the structure of their Service Base URL
|
22
|
+
publication. Test failures do not necessarily indicate non-conformance to
|
23
|
+
the Conditions and Maintenance of Certification. Use of these tests is
|
24
|
+
not required for the participants of the ONC Health IT Certification Program.
|
25
|
+
Please provide feedback on these tests by reporting an issue in
|
25
26
|
[GitHub](https://github.com/inferno-framework/service-base-url-test-kit/issues),
|
26
27
|
or by reaching out to the team on the [Inferno FHIR Zulip
|
27
28
|
channel](https://chat.fhir.org/#narrow/stream/179309-inferno).
|
28
29
|
|
29
|
-
Relevant requirements from the Conditions
|
30
|
-
Application programming
|
30
|
+
Relevant requirements from the [Conditions and Maintenance of
|
31
|
+
Certification - Application programming
|
32
|
+
interfaces](https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-D/part-170/subpart-D/section-170.404#p-170.404(b)(2)):
|
31
33
|
|
32
34
|
Service Base URL publication:
|
33
35
|
|
@@ -39,18 +41,18 @@ module ServiceBaseURLTestKit
|
|
39
41
|
170.315(g)(10) are centrally managed by the Certified API Developer or
|
40
42
|
locally deployed by an API Information Source. These service base URLs and
|
41
43
|
organization details must conform to the following:
|
42
|
-
|
44
|
+
|
43
45
|
- Service base URLs must be publicly published in Endpoint resource format
|
44
46
|
according to the standard adopted in § 170.215(a) (FHIR v4.0.1).
|
45
47
|
- Organization details for each service base URL must be publicly published in Organization
|
46
48
|
resource format according to the standard adopted in § 170.215(a) (FHIR v4.0.1). Each
|
47
|
-
Organization resource must contain:
|
49
|
+
Organization resource must contain:
|
48
50
|
- A reference, in the Organization endpoint element, to the Endpoint
|
49
51
|
resources containing service base URLs managed by this organization.
|
50
|
-
- The organization
|
52
|
+
- The organization's name, location, and facility identifier.
|
51
53
|
- Endpoint and Organization resources must be:
|
52
54
|
- Collected into a Bundle resource formatted according to the standard
|
53
|
-
adopted in § 170.215(a) (FHIR v4.0.1) for publication;
|
55
|
+
adopted in § 170.215(a) (FHIR v4.0.1) for publication;
|
54
56
|
- and Reviewed quarterly and, as
|
55
57
|
necessary, updated.
|
56
58
|
|
@@ -58,6 +60,16 @@ module ServiceBaseURLTestKit
|
|
58
60
|
)
|
59
61
|
version VERSION
|
60
62
|
|
63
|
+
input_instructions <<~INSTRUCTIONS
|
64
|
+
For systems that make their Service Base URL Bundle available at a public endpoint, please input
|
65
|
+
the Service Base URL Publication URL to retrieve the Bundle from there in order to perform validation, and leave
|
66
|
+
the Service Base URL Publication Bundle input blank.
|
67
|
+
|
68
|
+
For systems that do not have a Service Base URL Bundle served at a public endpoint, testers can validate by
|
69
|
+
providing the Service Base URL Publication Bundle as an input and leaving the Service Base URL Publication URL
|
70
|
+
input blank.
|
71
|
+
INSTRUCTIONS
|
72
|
+
|
61
73
|
links [
|
62
74
|
{
|
63
75
|
label: 'Report Issue',
|
@@ -66,6 +78,14 @@ module ServiceBaseURLTestKit
|
|
66
78
|
{
|
67
79
|
label: 'Open Source',
|
68
80
|
url: 'https://github.com/inferno-framework/service-base-url-test-kit'
|
81
|
+
},
|
82
|
+
{
|
83
|
+
label: 'Service base URL requirements',
|
84
|
+
url: 'https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-D/part-170/subpart-D/section-170.404#p-170.404(b)(2)'
|
85
|
+
},
|
86
|
+
{
|
87
|
+
label: 'Certification Companion Guide',
|
88
|
+
url: 'https://www.healthit.gov/condition-ccg/application-programming-interfaces'
|
69
89
|
}
|
70
90
|
]
|
71
91
|
|
@@ -76,11 +96,9 @@ module ServiceBaseURLTestKit
|
|
76
96
|
my_bundle = JSON.parse(erb_template.result).to_json
|
77
97
|
filename = filename.delete_suffix('.erb')
|
78
98
|
end
|
79
|
-
if filename.include?(
|
80
|
-
filename = filename.delete_suffix('.json') + "/metadata"
|
81
|
-
end
|
99
|
+
filename = "#{filename.delete_suffix('.json')}/metadata" if filename.include?('CapabilityStatement')
|
82
100
|
my_bundle_route_handler = proc { [200, { 'Content-Type' => 'application/json' }, [my_bundle]] }
|
83
|
-
|
101
|
+
|
84
102
|
# Serve a JSON file at INFERNO_PATH/custom/service_base_url/examples/filename
|
85
103
|
route :get, File.join('/examples/', filename), my_bundle_route_handler
|
86
104
|
end
|
@@ -88,7 +106,7 @@ module ServiceBaseURLTestKit
|
|
88
106
|
VALIDATION_MESSAGE_FILTERS = [
|
89
107
|
/A resource should have narrative for robust management/,
|
90
108
|
/\A\S+: \S+: URL value '.*' does not resolve/
|
91
|
-
]
|
109
|
+
].freeze
|
92
110
|
|
93
111
|
# All FHIR validation requests will use this FHIR validator
|
94
112
|
fhir_resource_validator :default do
|
@@ -99,4 +117,4 @@ module ServiceBaseURLTestKit
|
|
99
117
|
|
100
118
|
group from: :service_base_url_test_group
|
101
119
|
end
|
102
|
-
end
|
120
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: service_base_url_test_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Inferno Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inferno_core
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- LICENSE
|
91
91
|
- lib/service_base_url_test_kit.rb
|
92
92
|
- lib/service_base_url_test_kit/examples/CapabilityStatement.json
|
93
|
+
- lib/service_base_url_test_kit/examples/SmartAccessBrand.json.erb
|
93
94
|
- lib/service_base_url_test_kit/examples/testBundleValid.json.erb
|
94
95
|
- lib/service_base_url_test_kit/service_base_url_retrieve_group.rb
|
95
96
|
- lib/service_base_url_test_kit/service_base_url_test_group.rb
|
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
117
|
- !ruby/object:Gem::Version
|
117
118
|
version: '0'
|
118
119
|
requirements: []
|
119
|
-
rubygems_version: 3.
|
120
|
+
rubygems_version: 3.5.10
|
120
121
|
signing_key:
|
121
122
|
specification_version: 4
|
122
123
|
summary: Inferno Service Base URL Test Kit
|