service_base_url_test_kit 0.10.1 → 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/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
|