service_base_url_test_kit 0.10.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a699526f6d06f8063e2d7036a51aba54fe68d2c2c9f160440517ecb34aea65e
4
- data.tar.gz: 509c6f78c00322be2603803f3d138c3ec39b34fd0e18888a9df5b201293c7a72
3
+ metadata.gz: 638bed4317d3630a7ffdfbc9cef4be2dc266ab285de017d890a1ceadec4858fc
4
+ data.tar.gz: fab6cb020b68f87db82348891f3b80eb0d5e3bc9181639c9bf1b5a9505611de4
5
5
  SHA512:
6
- metadata.gz: 9cd8a0ee15f013e8da8a531b0f8c95a8f838927615096456a32f96f0032a2e31ce7f7722988c51e5779bc85b33b45f2d8491fbd1ce64cf0a06496068e85418fc
7
- data.tar.gz: fd5cf2fd1794d0204f9b15da318560a61225a8017871dc301117117aec6500fe31ab5ec4c577de3bc257f5967df326203708798fcff9a5068c038277432401c1
6
+ metadata.gz: 61b58536e24b25039953dc99cc4a507202c08297a8be0f70edb0d340ec0fa77824dbaee0de8be5bb548306eaf5c0e5b47dc143405882ebb5f91537bd258ccb68
7
+ data.tar.gz: 1fccec1d67cb3642771fa89360e90b3ad9f157bed70d35ee5beb09324cc5b649f74554638df4202834ffba3ca43c1578751477df79eb7c626707371ace21d205
@@ -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 List'
4
+ title 'Retrieve Service Base URL Publication'
5
5
  description %(
6
- A developer's Service Base URL list must be publicly available. This test
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 list at this location.
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 :service_base_url_list_url
18
- headers 'Accept': 'application/json, application/fhir+json'
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 List'
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
- get
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
- output bundle_response: resource.to_json
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 'Retrieve and Validate Service Base URL List'
8
- description %(
9
- Verify that the developer makes its Service Base URL list 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 list and ensure the list is
13
- publicly accessible. It will then ensure that the returned service base URL
14
- list 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 in 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
- all tests within this group. While it is the expectation of the
21
- 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
23
- served at a public endpoint by running Test 1.2: Validate Service Base URL
24
- List validation individually.
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 List'
4
+ title 'Validate Service Base URL Publication'
5
5
  description %(
6
- These tests ensure that the developer's Service Base URL list is in the
7
- Bundle resource format, with its service base URLs and organizational
6
+ These tests ensure that the developer's Service Base URL publication is in
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
- the specifications detailed in the HTI-1 rule in the API Condition and
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 :bundle_response,
15
- title: 'Service Base URL List Bundle',
16
- description: 'The developer\'s Service Base URL List in the JSON string format',
17
- type: 'textarea'
18
-
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
56
+
19
57
  # @private
20
58
  def find_referenced_org(bundle_resource, endpoint_id)
21
59
  bundle_resource
22
- .entry
23
- .map(&:resource)
24
- .select { |resource| resource.resourceType == 'Organization' }
25
- .map { |resource| resource.endpoint }
26
- .flatten
27
- .map(&:reference)
28
- .select { |reference| reference.include? endpoint_id }
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
- .entry
35
- .map(&:resource)
36
- .select { |resource| resource.resourceType == 'Endpoint' }
37
- .map(&:id)
38
- .select { |endpoint_id| endpoint_id_ref.include? endpoint_id }
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
61
- 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
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 List contains valid Endpoint resources'
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,19 +144,25 @@ 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
- resource_types: {
91
- 'Endpoint': nil
92
- }
93
- )
94
-
162
+ resource_types: {
163
+ Endpoint: nil
164
+ })
165
+
95
166
  endpoint_ids =
96
167
  bundle_resource
97
168
  .entry
@@ -99,13 +170,12 @@ 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?, "Endpoint with id: #{endpoint_id} does not have any associated Organizations in the Bundle."
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
- end
178
+ end
109
179
  end
110
180
 
111
181
  # ENDPOINT VALID URL TESTS
@@ -113,49 +183,97 @@ 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 and available.
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
- bundle_resource
130
- .entry
131
- .map(&:resource)
132
- .select { |resource| resource.resourceType == 'Endpoint' }
133
- .map(&:address)
134
- .each do |address|
135
- assert_valid_http_uri(address)
136
-
137
- address = address.delete_suffix("/")
138
- get("#{address}/metadata", client: nil, headers: {'Accept': 'application/json, application/fhir+json'})
139
- assert_response_status(200)
140
- assert_resource_type(:capability_statement)
219
+ one_endpoint_valid = false
220
+ endpoint_list.each_with_index do |address, index|
221
+ assert_valid_http_uri(address)
222
+
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
141
252
  end
142
- end
143
- end
144
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
+ ))
259
+ end
260
+ end
261
+ end
145
262
 
146
263
  # ORGANIZATION TESTS
147
264
  test do
148
265
  id :service_base_url_valid_organizations
149
- title 'Service Base URL List contains valid Organization resources'
266
+ title 'Service Base URL Publication contains valid Organization resources'
150
267
  description %(
151
268
 
152
- Verify that Bundle of Service Base URLs contains Organizations that are valid Organization resources according to the format defined in FHIR v4.0.1.
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.
153
271
 
154
272
  Each Organization must:
155
273
  - Contain must have elements including:
156
274
  - active
157
275
  - name
158
- - Include the organization's name, location, and provider identifier
276
+ - Include the organization's name, location, and facility identifier
159
277
  - Use the endpoint field to reference Endpoints associated with the Organization:
160
278
  - Must reference only Endpoint resources in the endpoint field
161
279
  - Must reference at least one Endpoint resource in the endpoint field
@@ -163,39 +281,53 @@ module ServiceBaseURLTestKit
163
281
  )
164
282
 
165
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
166
291
  skip_if bundle_response.blank?, 'No Bundle response was provided'
167
292
 
293
+ assert_valid_json(bundle_response)
168
294
  bundle_resource = FHIR.from_contents(bundle_response)
169
295
 
170
296
  skip_if bundle_resource.entry.empty?, 'The given Bundle does not contain any resources'
171
297
 
172
298
  assert_valid_bundle_entries(bundle: bundle_resource,
173
- resource_types: {
174
- 'Organization': nil
175
- }
176
- )
177
-
178
- endpoint_ids =
179
- bundle_resource
180
- .entry
181
- .map(&:resource)
182
- .select { |resource| resource.resourceType == 'Endpoint' }
183
- .map(&:id)
184
-
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
185
314
 
186
- for organization in bundle_resource.entry.map(&:resource).select { |resource| resource.resourceType == '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"
187
320
 
188
- assert !organization.endpoint.empty?, "Organization with id: #{organization.id} does not have the endpoint field populated"
189
- assert !organization.address.empty?, "Organization with id: #{organization.id} does not have the address field populated"
321
+ endpoint_references = organization.endpoint.map(&:reference)
190
322
 
191
-
192
- for endpoint_id_ref in organization.endpoint.map(&:reference)
323
+ endpoint_references.each do |endpoint_id_ref|
193
324
  organization_referenced_endpts = find_referenced_endpoint(bundle_resource, endpoint_id_ref)
194
- assert !organization_referenced_endpts.empty?, "Organization with id: #{organization.id} references an Endpoint that is not contained in this bundle."
195
-
325
+ assert !organization_referenced_endpts.empty?,
326
+ "Organization with id: #{organization.id} references an Endpoint that is not contained in this
327
+ bundle."
196
328
  end
197
- end
198
- end
329
+ end
330
+ end
199
331
  end
200
332
  end
201
- end
333
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ServiceBaseURLTestKit
4
- VERSION = '0.10.0'
4
+ VERSION = '0.11.0'
5
5
  end
@@ -7,52 +7,69 @@ module ServiceBaseURLTestKit
7
7
  id :service_base_url
8
8
  title 'Service Base URL Test Suite'
9
9
  description %(
10
- This test kit provides a draft set of tests to validate conformance to
11
- [HTI-1](https://www.healthit.gov/topic/laws-regulation-and-policy/health-data-technology-and-interoperability-certification-program)
12
- [rule](https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-D/part-170/subpart-D/section-170.404#p-170.404(b)(2))
13
- from the API Condition and Maintenance of Certification to include the
14
- requirement for Certified API Developers with patient-facing apps to
15
- publish their service base URLs in [a specified
16
- format](https://www.federalregister.gov/d/2023-07229/p-2342).
17
-
18
- A Certified API developer must publish, at no charge, the service base
19
- URLs and related organizational details that can be used by patients to
20
- access their electronic health information. This test kit will test that a
21
- server's service base URL list conforms to the following:
22
- - Service base URL list is publicly accessible
23
- - Service based URLs are published in the Endpoint resource format
24
- according to the standard adopted in § 170.215\(a\) - FHIR 4.0.1 release
25
- - Organization details for each service base URL are published in the
26
- Organization resource format according to the standard adopted in §
27
- 170.215\(a\) - FHIR 4.0.1 release
28
- - Each Endpoint resource must:
29
- - Have at least one Organization resource that references it in the Bundle
30
- - Each Organization resource must:
31
- - Have a populated Organization.endpoint field that contains
32
- references to the Endpoint resources containing service base URLs
33
- managed by this organization
34
- - Contain the organization's name, location, and provider identifier
35
- - Endpoint and Organization resources must be:
36
- - Collected into a Bundle resource formatted according to the standard
37
- adopted in FHIR v4.0.1: § 170.215\(a\) for publication
38
-
39
- While these tests do not specifically verify conformance to
40
- [Patient-Access
41
- Brands](https://build.fhir.org/ig/HL7/smart-app-launch/brands.html) within
42
- the draft SMART App Launch v2.2.0 standard, systems that implement that
43
- standard should pass these tests. Please report an issue if there are any
44
- problems.
45
-
46
- The tests within this test kit are available for developers that would
47
- like to evaluate their service list against the specified format. This is
48
- a draft set of tests and may contain errors or issues. Please provide
49
- feedback on these tests by reporting an issue in
10
+ This Test Kit provides a set of tests that verify conformance of Service
11
+ Base URL publications to data format requirements as described in
12
+ [Conditions and Maintenance of Certification - Application programming
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
+ and the [ONC HTI-1 Final
15
+ Rule](https://www.healthit.gov/topic/laws-regulation-and-policy/health-data-technology-and-interoperability-certification-program).
16
+ Please review the [Application Programming Interfaces Certification Companion
17
+ Guide](https://www.healthit.gov/condition-ccg/application-programming-interfaces)
18
+ for additional guidance.
19
+
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
50
26
  [GitHub](https://github.com/inferno-framework/service-base-url-test-kit/issues),
51
27
  or by reaching out to the team on the [Inferno FHIR Zulip
52
28
  channel](https://chat.fhir.org/#narrow/stream/179309-inferno).
29
+
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)):
33
+
34
+ Service Base URL publication:
35
+
36
+ For all Health IT Modules certified to § 170.315(g)(10), a Certified API
37
+ Developer must publish, at no charge, the service base URLs and related
38
+ organization details that can be used by patients to access their
39
+ electronic health information, by December 31, 2024. This includes all
40
+ customers regardless of whether the Health IT Modules certified to §
41
+ 170.315(g)(10) are centrally managed by the Certified API Developer or
42
+ locally deployed by an API Information Source. These service base URLs and
43
+ organization details must conform to the following:
44
+
45
+ - Service base URLs must be publicly published in Endpoint resource format
46
+ according to the standard adopted in § 170.215(a) (FHIR v4.0.1).
47
+ - Organization details for each service base URL must be publicly published in Organization
48
+ resource format according to the standard adopted in § 170.215(a) (FHIR v4.0.1). Each
49
+ Organization resource must contain:
50
+ - A reference, in the Organization endpoint element, to the Endpoint
51
+ resources containing service base URLs managed by this organization.
52
+ - The organization's name, location, and facility identifier.
53
+ - Endpoint and Organization resources must be:
54
+ - Collected into a Bundle resource formatted according to the standard
55
+ adopted in § 170.215(a) (FHIR v4.0.1) for publication;
56
+ - and Reviewed quarterly and, as
57
+ necessary, updated.
58
+
59
+
53
60
  )
54
61
  version VERSION
55
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
+
56
73
  links [
57
74
  {
58
75
  label: 'Report Issue',
@@ -61,6 +78,14 @@ module ServiceBaseURLTestKit
61
78
  {
62
79
  label: 'Open Source',
63
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'
64
89
  }
65
90
  ]
66
91
 
@@ -71,11 +96,9 @@ module ServiceBaseURLTestKit
71
96
  my_bundle = JSON.parse(erb_template.result).to_json
72
97
  filename = filename.delete_suffix('.erb')
73
98
  end
74
- if filename.include?("CapabilityStatement")
75
- filename = filename.delete_suffix('.json') + "/metadata"
76
- end
99
+ filename = "#{filename.delete_suffix('.json')}/metadata" if filename.include?('CapabilityStatement')
77
100
  my_bundle_route_handler = proc { [200, { 'Content-Type' => 'application/json' }, [my_bundle]] }
78
-
101
+
79
102
  # Serve a JSON file at INFERNO_PATH/custom/service_base_url/examples/filename
80
103
  route :get, File.join('/examples/', filename), my_bundle_route_handler
81
104
  end
@@ -83,7 +106,7 @@ module ServiceBaseURLTestKit
83
106
  VALIDATION_MESSAGE_FILTERS = [
84
107
  /A resource should have narrative for robust management/,
85
108
  /\A\S+: \S+: URL value '.*' does not resolve/
86
- ]
109
+ ].freeze
87
110
 
88
111
  # All FHIR validation requests will use this FHIR validator
89
112
  fhir_resource_validator :default do
@@ -94,4 +117,4 @@ module ServiceBaseURLTestKit
94
117
 
95
118
  group from: :service_base_url_test_group
96
119
  end
97
- 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.10.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-06-06 00:00:00.000000000 Z
11
+ date: 2024-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core