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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7930c517e65b84c6011ba94dc5419c9d26548b931194bad1724bda2e26f632e6
4
- data.tar.gz: d73dcf49c51873fb5aad07f079bc66b72d0912fea69e52d4a4e790bb167b6af2
3
+ metadata.gz: 638bed4317d3630a7ffdfbc9cef4be2dc266ab285de017d890a1ceadec4858fc
4
+ data.tar.gz: fab6cb020b68f87db82348891f3b80eb0d5e3bc9181639c9bf1b5a9505611de4
5
5
  SHA512:
6
- metadata.gz: 3d572a5d516ad116afc9787c4816493fb48788c89a163c4365ee664dd94bbd745a19eef429ae0095a13d2e7742113f64f134f80e399469798a60f08442c33157
7
- data.tar.gz: b7b0e8b87f62e5ecedeaadb0b3693ec81d9a94dd6d916616fbef54d6c023c603e30f6eb6c12567a780686a2472c64348423b757ec40e45fb0fcb444ec4837251
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 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 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 list 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
- 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
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 :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'
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
- .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
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 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,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
- resource_types: {
91
- 'Endpoint': nil
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?, "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
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 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
- .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
- address = address.delete_suffix("/")
139
- get("#{address}/metadata", client: nil, headers: {'Accept': 'application/fhir+json'})
140
- assert_response_status(200)
141
- assert resource.present?, 'The content received does not appear to be a valid FHIR resource'
142
- assert_resource_type(:capability_statement)
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 List contains valid Organization resources'
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 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.
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
- resource_types: {
176
- 'Organization': nil
177
- }
178
- )
179
-
180
- endpoint_ids =
181
- bundle_resource
182
- .entry
183
- .map(&:resource)
184
- .select { |resource| resource.resourceType == 'Endpoint' }
185
- .map(&:id)
186
-
187
-
188
- for organization in bundle_resource.entry.map(&:resource).select { |resource| resource.resourceType == 'Organization' }
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
- assert !organization.endpoint.empty?, "Organization with id: #{organization.id} does not have the endpoint field populated"
191
- assert !organization.address.empty?, "Organization with id: #{organization.id} does not have the address field populated"
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
- for endpoint_id_ref in organization.endpoint.map(&:reference)
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?, "Organization with id: #{organization.id} references an Endpoint that is not contained in this bundle."
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ServiceBaseURLTestKit
4
- VERSION = '0.10.1'
4
+ VERSION = '0.11.0'
5
5
  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 of Maintenance of Certification - Application programming
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 issues
21
- or problems with the structure of their Service Base URL publication. Test
22
- failures do not necessarily indicate non-conformance to the Conditions of
23
- Maintenance of Certification. Use of these tests is not required. Please
24
- provide feedback on these tests by reporting an issue in
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 of [Maintenance of Certification -
30
- Application programming interfaces](https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-D/part-170/subpart-D/section-170.404#p-170.404(b)(2)):
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 organizations name, location, and facility identifier.
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?("CapabilityStatement")
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.10.1
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-08-09 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
@@ -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.3.7
120
+ rubygems_version: 3.5.10
120
121
  signing_key:
121
122
  specification_version: 4
122
123
  summary: Inferno Service Base URL Test Kit