inferno_core 1.1.0 → 1.1.1
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/inferno/apps/web/serializers/test.rb +1 -0
- data/lib/inferno/dsl/assertions.rb +55 -6
- data/lib/inferno/dsl/fhir_client.rb +3 -0
- data/lib/inferno/dsl/fhir_resource_validation.rb +110 -42
- data/lib/inferno/dsl/fhir_validation.rb +37 -2
- data/lib/inferno/dsl/http_client.rb +28 -0
- data/lib/inferno/dsl/messages.rb +10 -0
- data/lib/inferno/dsl/runnable.rb +15 -0
- data/lib/inferno/exceptions.rb +7 -0
- data/lib/inferno/public/bundle.js +11 -11
- data/lib/inferno/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc9addf71b6ea91eb5aa426eabe24df9a2cbdb3199271e3f60d8e66f1cacd8cc
|
|
4
|
+
data.tar.gz: 16fd0eaf84e1c2a391ba90efcedbeae1a24f82ad45dcc9b7a8b5e2365ed3d53d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0eed6f34c2f0cfd4a78f12d7dc4ce853480520d740e4af6da052ec4b4eb2d3551ff4208e99516990438a957dcccf8a0ad38f01aaae34224b5286086fb88d4095
|
|
7
|
+
data.tar.gz: 0fc841b4d2ad71f098061277d9041caa6633e36679276ca6db2db8553c22a383d63c950196aacb661b9175b398aa8e80da5f5e8cd9b90d377019afb8b14d04b9
|
|
@@ -21,6 +21,7 @@ module Inferno
|
|
|
21
21
|
field :input_instructions
|
|
22
22
|
field :user_runnable?, name: :user_runnable
|
|
23
23
|
field :optional?, name: :optional
|
|
24
|
+
field :simulation_verification?, name: :is_simulation_verification
|
|
24
25
|
field :verifies_requirements, if: :field_present?, extractor: RequirementsFilteringExtractor
|
|
25
26
|
end
|
|
26
27
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative '../exceptions'
|
|
2
|
+
require_relative 'messages'
|
|
2
3
|
|
|
3
4
|
module Inferno
|
|
4
5
|
module DSL
|
|
@@ -7,6 +8,7 @@ module Inferno
|
|
|
7
8
|
# immediately stop execution and receive a `fail` result. Additional
|
|
8
9
|
# assertions added to this module will be available in all tests.
|
|
9
10
|
module Assertions
|
|
11
|
+
include Messages
|
|
10
12
|
# Make an assertion
|
|
11
13
|
#
|
|
12
14
|
# @param test a value whose truthiness will determine whether the
|
|
@@ -59,6 +61,7 @@ module Inferno
|
|
|
59
61
|
# @private
|
|
60
62
|
def invalid_resource_message(resource, profile_url)
|
|
61
63
|
return "Resource does not conform to the profile: #{profile_url}" if profile_url.present?
|
|
64
|
+
return 'No resource to validate.' unless resource.present?
|
|
62
65
|
|
|
63
66
|
"Resource does not conform to the base #{resource&.resourceType} profile."
|
|
64
67
|
end
|
|
@@ -70,12 +73,31 @@ module Inferno
|
|
|
70
73
|
# may include a version separated by a vertical bar (|),
|
|
71
74
|
# and defaults to validating against the base FHIR resource type
|
|
72
75
|
# @param validator [Symbol] the name of the validator to use
|
|
76
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
73
77
|
# @return [void]
|
|
74
|
-
def assert_valid_resource(resource: self.resource, profile_url: nil, validator: :default)
|
|
75
|
-
assert resource_is_valid?(resource:, profile_url:, validator:),
|
|
78
|
+
def assert_valid_resource(resource: self.resource, profile_url: nil, validator: :default, message_prefix: '')
|
|
79
|
+
assert resource_is_valid?(resource:, profile_url:, validator:, message_prefix:),
|
|
76
80
|
invalid_resource_message(resource, profile_url)
|
|
77
81
|
end
|
|
78
82
|
|
|
83
|
+
# @private
|
|
84
|
+
def invalid_object_message(model_url)
|
|
85
|
+
"Object does not conform to the logical model: #{model_url}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Validate an object against a logical model
|
|
89
|
+
#
|
|
90
|
+
# @param object [Hash]
|
|
91
|
+
# @param model_url [String] canonical url of the model to validate against,
|
|
92
|
+
# may include a version separated by a vertical bar (|),
|
|
93
|
+
# @param validator [Symbol] the name of the validator to use
|
|
94
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
95
|
+
# @return [void]
|
|
96
|
+
def assert_conformance_to_logical_model(object, model_url, validator: :default, message_prefix: '')
|
|
97
|
+
assert conforms_to_logical_model?(object, model_url, validator:, message_prefix:),
|
|
98
|
+
invalid_object_message(model_url)
|
|
99
|
+
end
|
|
100
|
+
|
|
79
101
|
# Validate each entry of a Bundle
|
|
80
102
|
#
|
|
81
103
|
# @param bundle [FHIR::Bundle]
|
|
@@ -87,6 +109,7 @@ module Inferno
|
|
|
87
109
|
# types as keys and profile urls (or nil) as values, only those resource
|
|
88
110
|
# types will be validated against the provided profile url or the base
|
|
89
111
|
# resource if nil.
|
|
112
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
90
113
|
# @example
|
|
91
114
|
# # Only validate Patient bundle entries
|
|
92
115
|
# assert_valid_bundle_entries(resource_types: 'Patient')
|
|
@@ -104,7 +127,7 @@ module Inferno
|
|
|
104
127
|
# }
|
|
105
128
|
# )
|
|
106
129
|
# @return [void]
|
|
107
|
-
def assert_valid_bundle_entries(bundle: resource, resource_types: {})
|
|
130
|
+
def assert_valid_bundle_entries(bundle: resource, resource_types: {}, message_prefix: '')
|
|
108
131
|
assert_resource_type('Bundle', resource: bundle)
|
|
109
132
|
|
|
110
133
|
types_to_check = normalize_types_to_check(resource_types)
|
|
@@ -115,7 +138,7 @@ module Inferno
|
|
|
115
138
|
.map(&:resource)
|
|
116
139
|
.select { |resource| types_to_check.empty? || types_to_check.include?(resource.resourceType) }
|
|
117
140
|
.reject do |resource|
|
|
118
|
-
validation_params = { resource: }
|
|
141
|
+
validation_params = { resource:, message_prefix: }
|
|
119
142
|
profile = types_to_check[resource.resourceType]
|
|
120
143
|
validation_params[:profile_url] = profile if profile
|
|
121
144
|
|
|
@@ -161,9 +184,25 @@ module Inferno
|
|
|
161
184
|
# @param message [String] extra failure message
|
|
162
185
|
# @return [void]
|
|
163
186
|
def assert_valid_json(maybe_json_string, message = '')
|
|
164
|
-
|
|
187
|
+
parsed_json_if_valid(maybe_json_string, message, continue: false)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Return parsed json Hash if valid, or indicate an error with an error message or a failed assert
|
|
191
|
+
#
|
|
192
|
+
# @param maybe_json_string [String]
|
|
193
|
+
# @param message [String] extra failure message
|
|
194
|
+
# @param continue [Boolean] if true will log an error message and continue,
|
|
195
|
+
# otherwise will raise an assert exception
|
|
196
|
+
# @return [void]
|
|
197
|
+
def parsed_json_if_valid(maybe_json_string, message = '', continue: true)
|
|
198
|
+
JSON.parse(maybe_json_string)
|
|
165
199
|
rescue JSON::ParserError
|
|
166
|
-
|
|
200
|
+
if continue
|
|
201
|
+
add_message(:error, "Invalid JSON. #{message}")
|
|
202
|
+
nil
|
|
203
|
+
else
|
|
204
|
+
assert false, "Invalid JSON. #{message}"
|
|
205
|
+
end
|
|
167
206
|
end
|
|
168
207
|
|
|
169
208
|
# Check for a valid http/https uri
|
|
@@ -224,6 +263,16 @@ module Inferno
|
|
|
224
263
|
"Could not find #{missing_elements.join(', ')} in the #{resources.length} " \
|
|
225
264
|
'provided resource(s)'
|
|
226
265
|
end
|
|
266
|
+
|
|
267
|
+
# Check that there are no messages associated with the current runnable with a type of 'error'
|
|
268
|
+
#
|
|
269
|
+
# @param message [String] failure message
|
|
270
|
+
# @param message_list [Array] (optional) list of messages to check for errors,
|
|
271
|
+
# if different from the runnable's messages
|
|
272
|
+
# @return [void]
|
|
273
|
+
def assert_no_error_messages(message = '', message_list: messages)
|
|
274
|
+
assert !error_messages?(message_list:), message.present? ? message : 'Errors found - see Messages for details.'
|
|
275
|
+
end
|
|
227
276
|
end
|
|
228
277
|
end
|
|
229
278
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require_relative 'fhir_client_builder'
|
|
2
2
|
require_relative 'request_storage'
|
|
3
3
|
require_relative 'tcp_exception_handler'
|
|
4
|
+
require_relative 'messages'
|
|
4
5
|
|
|
5
6
|
module Inferno
|
|
6
7
|
module DSL
|
|
@@ -37,6 +38,8 @@ module Inferno
|
|
|
37
38
|
# @see Inferno::DSL::FHIRClientBuilder Documentation for the client
|
|
38
39
|
# configuration DSL
|
|
39
40
|
module FHIRClient
|
|
41
|
+
include Messages
|
|
42
|
+
|
|
40
43
|
# @private
|
|
41
44
|
def self.included(klass)
|
|
42
45
|
klass.extend ClassMethods
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative '../ext/fhir_models'
|
|
2
2
|
require_relative '../feature'
|
|
3
|
+
require_relative '../exceptions'
|
|
3
4
|
module Inferno
|
|
4
5
|
module DSL
|
|
5
6
|
# This module contains the methods needed to configure a validator to
|
|
@@ -159,6 +160,37 @@ module Inferno
|
|
|
159
160
|
@exclude_message
|
|
160
161
|
end
|
|
161
162
|
|
|
163
|
+
# Validate a FHIR resource and determine if it's valid.
|
|
164
|
+
# Adds validation messages to the runnable if add_messages_to_runnable is true.
|
|
165
|
+
def conforms_to_logical_model?(object, model_url, runnable, add_messages_to_runnable: true,
|
|
166
|
+
message_prefix: '', validator_response_details: nil)
|
|
167
|
+
|
|
168
|
+
unless model_url.present?
|
|
169
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
170
|
+
'Logical Model Validation',
|
|
171
|
+
'The profile of the logical model must be provided.'
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
unless object.present?
|
|
176
|
+
if add_messages_to_runnable
|
|
177
|
+
runnable.add_message(:error,
|
|
178
|
+
"#{message_prefix}No object to check for conformance.")
|
|
179
|
+
end
|
|
180
|
+
return false
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
unless object.is_a?(Hash)
|
|
184
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
185
|
+
'Logical Model Validation',
|
|
186
|
+
"Expected a Hash, got a #{object.class}."
|
|
187
|
+
)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
conformant?(object, model_url, runnable, add_messages_to_runnable:, message_prefix:,
|
|
191
|
+
validator_response_details:)
|
|
192
|
+
end
|
|
193
|
+
|
|
162
194
|
# Validate a FHIR resource and determine if it's valid.
|
|
163
195
|
# Adds validation messages to the runnable if add_messages_to_runnable is true.
|
|
164
196
|
#
|
|
@@ -167,29 +199,51 @@ module Inferno
|
|
|
167
199
|
# @param profile_url [String] the profile URL to validate against
|
|
168
200
|
# @param runnable [Object] the runnable context (test/group/suite)
|
|
169
201
|
# @param add_messages_to_runnable [Boolean] whether to add messages to the runnable
|
|
202
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
170
203
|
# @param validator_response_details [Array, nil] if not nil, the service will populate this array with
|
|
171
204
|
# the detailed response message from the validator service. Can be used by test kits to perform custom
|
|
172
205
|
# handling of error messages.
|
|
173
206
|
# @return [Boolean] true if the resource is valid
|
|
174
207
|
def resource_is_valid?(resource, profile_url, runnable, add_messages_to_runnable: true,
|
|
175
|
-
validator_response_details: nil)
|
|
208
|
+
message_prefix: '', validator_response_details: nil)
|
|
209
|
+
|
|
210
|
+
unless resource.present?
|
|
211
|
+
runnable.add_message(:error, "#{message_prefix}No resource to validate.") if add_messages_to_runnable
|
|
212
|
+
return false
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
unless resource.is_a?(FHIR::Model)
|
|
216
|
+
raise Inferno::Exceptions::TestSuiteImplementationException.new(
|
|
217
|
+
'FHIR Resource Validation',
|
|
218
|
+
"Expected a FHIR::Model, got a #{resource.class}."
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
end
|
|
176
222
|
profile_url ||= FHIR::Definitions.resource_definition(resource.resourceType).url
|
|
177
223
|
|
|
224
|
+
conformant?(resource, profile_url, runnable, add_messages_to_runnable:, message_prefix:,
|
|
225
|
+
validator_response_details:)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# @private
|
|
229
|
+
def conformant?(target, profile_url, runnable, add_messages_to_runnable: true,
|
|
230
|
+
message_prefix: '', validator_response_details: nil)
|
|
231
|
+
|
|
178
232
|
# 1. Get raw content from validator
|
|
179
|
-
response = get_raw_validator_content(
|
|
233
|
+
response = get_raw_validator_content(target, profile_url, runnable)
|
|
180
234
|
|
|
181
235
|
# 2. Convert to validation issues
|
|
182
|
-
issues = get_issues_from_validator_response(response,
|
|
236
|
+
issues = get_issues_from_validator_response(response, target)
|
|
183
237
|
|
|
184
238
|
# 3. Add additional validation messages
|
|
185
|
-
issues = join_additional_validation_messages(issues,
|
|
239
|
+
issues = join_additional_validation_messages(issues, target, profile_url)
|
|
186
240
|
|
|
187
241
|
# 4. Mark resources as filtered
|
|
188
242
|
mark_issues_for_filtering(issues)
|
|
189
243
|
|
|
190
244
|
# 5. Add error messages to runnable
|
|
191
245
|
filtered_issues = issues.reject(&:filtered)
|
|
192
|
-
add_validation_messages_to_runnable(runnable, filtered_issues) if add_messages_to_runnable
|
|
246
|
+
add_validation_messages_to_runnable(runnable, filtered_issues, message_prefix:) if add_messages_to_runnable
|
|
193
247
|
validator_response_details&.concat(issues)
|
|
194
248
|
|
|
195
249
|
# 6. Return validity
|
|
@@ -204,12 +258,12 @@ module Inferno
|
|
|
204
258
|
|
|
205
259
|
# @private
|
|
206
260
|
# Gets raw content from validator including error handling
|
|
207
|
-
# @param
|
|
261
|
+
# @param target [FHIR::Model, Hash] the object to validate
|
|
208
262
|
# @param profile_url [String] the profile URL to validate against
|
|
209
263
|
# @param runnable [Object] the runnable context
|
|
210
264
|
# @return [Faraday::Response] the HTTP response from the validator
|
|
211
|
-
def get_raw_validator_content(
|
|
212
|
-
response = call_validator(
|
|
265
|
+
def get_raw_validator_content(target, profile_url, runnable)
|
|
266
|
+
response = call_validator(target, profile_url)
|
|
213
267
|
|
|
214
268
|
unless response.status == 200
|
|
215
269
|
raise Inferno::Exceptions::ErrorInValidatorException,
|
|
@@ -225,19 +279,19 @@ module Inferno
|
|
|
225
279
|
|
|
226
280
|
# @private
|
|
227
281
|
# Adds validation messages to the runnable
|
|
228
|
-
def add_validation_messages_to_runnable(runnable, filtered_issues)
|
|
282
|
+
def add_validation_messages_to_runnable(runnable, filtered_issues, message_prefix: '')
|
|
229
283
|
filtered_issues.each do |issue|
|
|
230
|
-
runnable.add_message(issue.severity, issue.message)
|
|
284
|
+
runnable.add_message(issue.severity, "#{message_prefix}#{issue.message}")
|
|
231
285
|
end
|
|
232
286
|
end
|
|
233
287
|
|
|
234
288
|
# Warm up the validator session by sending a test validation request.
|
|
235
289
|
# This initializes the validator session and persists it for future use.
|
|
236
290
|
#
|
|
237
|
-
# @param
|
|
291
|
+
# @param target [FHIR::Model, Hash] the object to validate
|
|
238
292
|
# @param profile_url [String] the profile URL to validate against
|
|
239
|
-
def warm_up(
|
|
240
|
-
response_body = validate(
|
|
293
|
+
def warm_up(target, profile_url)
|
|
294
|
+
response_body = validate(target, profile_url)
|
|
241
295
|
res = JSON.parse(response_body)
|
|
242
296
|
session_id = res['sessionId']
|
|
243
297
|
validator_session_repo.save(test_suite_id:, validator_session_id: session_id,
|
|
@@ -253,9 +307,9 @@ module Inferno
|
|
|
253
307
|
# Recursively processes slice information.
|
|
254
308
|
#
|
|
255
309
|
# @param response [Faraday::Response] the HTTP response from the validator
|
|
256
|
-
# @param
|
|
310
|
+
# @param target [FHIR::Model, Hash] the object being validated
|
|
257
311
|
# @return [Array<ValidatorIssue>] list of validator issues
|
|
258
|
-
def get_issues_from_validator_response(response,
|
|
312
|
+
def get_issues_from_validator_response(response, target)
|
|
259
313
|
response_body = remove_invalid_characters(response.body)
|
|
260
314
|
response_hash = JSON.parse(response_body)
|
|
261
315
|
|
|
@@ -268,7 +322,7 @@ module Inferno
|
|
|
268
322
|
raw_issues = response_hash.dig('outcomes', 0, 'issues') || []
|
|
269
323
|
|
|
270
324
|
raw_issues.map do |raw_issue|
|
|
271
|
-
convert_raw_issue_to_validator_issue(raw_issue,
|
|
325
|
+
convert_raw_issue_to_validator_issue(raw_issue, target)
|
|
272
326
|
end
|
|
273
327
|
end
|
|
274
328
|
|
|
@@ -277,28 +331,28 @@ module Inferno
|
|
|
277
331
|
# Recursively processes sliceInfo if present.
|
|
278
332
|
#
|
|
279
333
|
# @param raw_issue [Hash] the raw issue from validator response
|
|
280
|
-
# @param
|
|
334
|
+
# @param target [FHIR::Model, Hash] the object being validated
|
|
281
335
|
# @return [ValidatorIssue] the converted validator issue
|
|
282
|
-
def convert_raw_issue_to_validator_issue(raw_issue,
|
|
336
|
+
def convert_raw_issue_to_validator_issue(raw_issue, target)
|
|
283
337
|
# Recursively process sliceInfo
|
|
284
338
|
slice_info = []
|
|
285
339
|
if raw_issue['sliceInfo']&.any?
|
|
286
340
|
slice_info = raw_issue['sliceInfo'].map do |slice_issue|
|
|
287
|
-
convert_raw_issue_to_validator_issue(slice_issue,
|
|
341
|
+
convert_raw_issue_to_validator_issue(slice_issue, target)
|
|
288
342
|
end
|
|
289
343
|
end
|
|
290
344
|
|
|
291
345
|
ValidatorIssue.new(
|
|
292
346
|
raw_issue: raw_issue,
|
|
293
|
-
|
|
347
|
+
target: target,
|
|
294
348
|
slice_info: slice_info,
|
|
295
349
|
filtered: false
|
|
296
350
|
)
|
|
297
351
|
end
|
|
298
352
|
|
|
299
353
|
# @private
|
|
300
|
-
def call_validator(
|
|
301
|
-
request_body =
|
|
354
|
+
def call_validator(target, profile_url)
|
|
355
|
+
request_body = wrap_target_for_hl7_wrapper(target, profile_url)
|
|
302
356
|
Faraday.new(
|
|
303
357
|
url,
|
|
304
358
|
request: { timeout: 600 }
|
|
@@ -306,14 +360,14 @@ module Inferno
|
|
|
306
360
|
end
|
|
307
361
|
|
|
308
362
|
# @private
|
|
309
|
-
# Post
|
|
363
|
+
# Post an object to the validation service for validating.
|
|
310
364
|
# Returns the raw validator response body.
|
|
311
365
|
#
|
|
312
|
-
# @param
|
|
366
|
+
# @param target [FHIR::Model, Hash]
|
|
313
367
|
# @param profile_url [String]
|
|
314
368
|
# @return [String] the body of the validation response
|
|
315
|
-
def validate(
|
|
316
|
-
call_validator(
|
|
369
|
+
def validate(target, profile_url)
|
|
370
|
+
call_validator(target, profile_url).body
|
|
317
371
|
end
|
|
318
372
|
|
|
319
373
|
# Add a specific error message for specific network problems to help the user
|
|
@@ -351,11 +405,11 @@ module Inferno
|
|
|
351
405
|
# Joins additional validation messages to the issues list
|
|
352
406
|
#
|
|
353
407
|
# @param issues [Array<ValidatorIssue>] the list of validator issues
|
|
354
|
-
# @param
|
|
408
|
+
# @param target [FHIR::Model] the object being validated
|
|
355
409
|
# @param profile_url [String] the profile URL being validated against
|
|
356
410
|
# @return [Array<ValidatorIssue>] the complete list of issues including additional messages
|
|
357
|
-
def join_additional_validation_messages(issues,
|
|
358
|
-
additional_issues = additional_validation_messages(
|
|
411
|
+
def join_additional_validation_messages(issues, target, profile_url)
|
|
412
|
+
additional_issues = additional_validation_messages(target, profile_url)
|
|
359
413
|
issues + additional_issues
|
|
360
414
|
end
|
|
361
415
|
|
|
@@ -376,12 +430,12 @@ module Inferno
|
|
|
376
430
|
# Gets additional validation messages from custom validation blocks.
|
|
377
431
|
# Converts the message hashes to ValidatorIssue objects.
|
|
378
432
|
#
|
|
379
|
-
# @param
|
|
433
|
+
# @param target [FHIR::Model, Hash] the object being validated
|
|
380
434
|
# @param profile_url [String] the profile URL being validated against
|
|
381
435
|
# @return [Array<ValidatorIssue>] list of additional validator issues
|
|
382
|
-
def additional_validation_messages(
|
|
436
|
+
def additional_validation_messages(target, profile_url)
|
|
383
437
|
additional_validations
|
|
384
|
-
.flat_map { |step| step.call(
|
|
438
|
+
.flat_map { |step| step.call(target, profile_url) }
|
|
385
439
|
.select { |message| message.is_a? Hash }
|
|
386
440
|
.map do |message_hash|
|
|
387
441
|
# Create a synthetic raw_issue for additional validation messages
|
|
@@ -392,7 +446,7 @@ module Inferno
|
|
|
392
446
|
}
|
|
393
447
|
ValidatorIssue.new(
|
|
394
448
|
raw_issue: synthetic_raw_issue,
|
|
395
|
-
|
|
449
|
+
target: target,
|
|
396
450
|
slice_info: [],
|
|
397
451
|
filtered: false
|
|
398
452
|
)
|
|
@@ -536,7 +590,7 @@ module Inferno
|
|
|
536
590
|
end
|
|
537
591
|
|
|
538
592
|
# @private
|
|
539
|
-
def
|
|
593
|
+
def wrap_target_for_hl7_wrapper(target, profile_url)
|
|
540
594
|
validator_session_id =
|
|
541
595
|
validator_session_repo.find_validator_session_id(test_suite_id,
|
|
542
596
|
name.to_s, requirements)
|
|
@@ -547,6 +601,13 @@ module Inferno
|
|
|
547
601
|
# This allows backward compatibility until the validator-wrapper is updated.
|
|
548
602
|
context_key = Feature.use_validation_context_key? ? :validationContext : :cliContext
|
|
549
603
|
|
|
604
|
+
file_contents =
|
|
605
|
+
if target.is_a?(Hash)
|
|
606
|
+
target.to_json
|
|
607
|
+
else
|
|
608
|
+
target.source_contents
|
|
609
|
+
end
|
|
610
|
+
|
|
550
611
|
wrapped_resource = {
|
|
551
612
|
context_key => {
|
|
552
613
|
**validation_context.definition,
|
|
@@ -554,8 +615,8 @@ module Inferno
|
|
|
554
615
|
},
|
|
555
616
|
filesToValidate: [
|
|
556
617
|
{
|
|
557
|
-
fileName: "#{
|
|
558
|
-
fileContent:
|
|
618
|
+
fileName: "#{profile_url.split('/').last}.json",
|
|
619
|
+
fileContent: file_contents,
|
|
559
620
|
fileType: 'json'
|
|
560
621
|
}
|
|
561
622
|
],
|
|
@@ -598,16 +659,16 @@ module Inferno
|
|
|
598
659
|
# ValidatorIssue represents a single validation issue returned from the FHIR validator
|
|
599
660
|
class ValidatorIssue
|
|
600
661
|
attr_accessor :filtered, :raw_issue, :slice_info
|
|
601
|
-
attr_reader :
|
|
662
|
+
attr_reader :target
|
|
602
663
|
|
|
603
664
|
# Creates a new ValidatorIssue
|
|
604
665
|
# @param raw_issue [Hash] the raw issue hash from the validator response
|
|
605
|
-
# @param
|
|
666
|
+
# @param target [FHIR::Model, Hash] the object being validated
|
|
606
667
|
# @param slice_info [Array<ValidatorIssue>] nested slice information as ValidatorIssue objects
|
|
607
668
|
# @param filtered [Boolean] whether this issue has been filtered out
|
|
608
|
-
def initialize(raw_issue:,
|
|
669
|
+
def initialize(raw_issue:, target:, slice_info: [], filtered: false)
|
|
609
670
|
@raw_issue = raw_issue
|
|
610
|
-
@
|
|
671
|
+
@target = target
|
|
611
672
|
@slice_info = slice_info
|
|
612
673
|
@filtered = filtered
|
|
613
674
|
end
|
|
@@ -641,8 +702,15 @@ module Inferno
|
|
|
641
702
|
# Don't add prefix for additional validation messages
|
|
642
703
|
return details_text if location_value == 'additional_validation'
|
|
643
704
|
|
|
644
|
-
|
|
645
|
-
|
|
705
|
+
"#{location_prefix}#{location_value}: #{details_text}"
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
def location_prefix
|
|
709
|
+
if target.is_a?(Hash)
|
|
710
|
+
''
|
|
711
|
+
else
|
|
712
|
+
"#{target.id ? "#{target.resourceType}/#{target.id}" : target.resourceType}: "
|
|
713
|
+
end
|
|
646
714
|
end
|
|
647
715
|
|
|
648
716
|
# Converts the validator's severity level to our standard format
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative '../ext/fhir_models'
|
|
2
|
+
require_relative '../exceptions'
|
|
2
3
|
module Inferno
|
|
3
4
|
module DSL
|
|
4
5
|
# This module contains the methods needed to configure a validator to
|
|
@@ -32,19 +33,42 @@ module Inferno
|
|
|
32
33
|
# @param profile_url [String]
|
|
33
34
|
# @param validator [Symbol] the name of the validator to use
|
|
34
35
|
# @param add_messages_to_runnable [Boolean] whether to add validation messages to runnable or not
|
|
36
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
35
37
|
# @param validator_response_details [Array, nil] if not nil, the service will populate this array with
|
|
36
38
|
# the detailed response message from the validator service
|
|
37
39
|
# @return [Boolean] whether the resource is valid
|
|
38
40
|
def resource_is_valid?(
|
|
39
41
|
resource: self.resource, profile_url: nil,
|
|
40
|
-
validator: :default, add_messages_to_runnable: true,
|
|
42
|
+
validator: :default, add_messages_to_runnable: true, message_prefix: '',
|
|
41
43
|
validator_response_details: nil
|
|
42
44
|
)
|
|
43
45
|
find_validator(validator).resource_is_valid?(resource, profile_url, self,
|
|
44
46
|
add_messages_to_runnable:,
|
|
47
|
+
message_prefix:,
|
|
45
48
|
validator_response_details:)
|
|
46
49
|
end
|
|
47
50
|
|
|
51
|
+
# Perform validation, and add validation messages to the runnable
|
|
52
|
+
#
|
|
53
|
+
# @param object [Hash] json to verify against the model, as a Hash
|
|
54
|
+
# @param model_url [String]
|
|
55
|
+
# @param validator [Symbol] the name of the validator to use
|
|
56
|
+
# @param add_messages_to_runnable [Boolean] whether to add validation messages to runnable or not
|
|
57
|
+
# @param message_prefix [String] Prefix to add to the start of logged messages
|
|
58
|
+
# @param validator_response_details [Array, nil] if not nil, the service will populate this array with
|
|
59
|
+
# the detailed response message from the validator service
|
|
60
|
+
# @return [Boolean] whether the resource is valid
|
|
61
|
+
def conforms_to_logical_model?(
|
|
62
|
+
object, model_url,
|
|
63
|
+
validator: :default, add_messages_to_runnable: true, message_prefix: '',
|
|
64
|
+
validator_response_details: nil
|
|
65
|
+
)
|
|
66
|
+
find_validator(validator).conforms_to_logical_model?(object, model_url, self,
|
|
67
|
+
add_messages_to_runnable:,
|
|
68
|
+
message_prefix:,
|
|
69
|
+
validator_response_details:)
|
|
70
|
+
end
|
|
71
|
+
|
|
48
72
|
# Find a particular validator. Looks through a runnable's parents up to
|
|
49
73
|
# the suite to find a validator with a particular name
|
|
50
74
|
def find_validator(validator_name)
|
|
@@ -122,10 +146,21 @@ module Inferno
|
|
|
122
146
|
@exclude_message
|
|
123
147
|
end
|
|
124
148
|
|
|
149
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
150
|
+
def conforms_to_logical_model?(resource, profile_url, runnable, add_messages_to_runnable: true,
|
|
151
|
+
message_prefix: '', validator_response_details: nil)
|
|
152
|
+
|
|
153
|
+
raise Exceptions::TestSuiteImplementationException.new(
|
|
154
|
+
'Logical Model Validation',
|
|
155
|
+
'Logical model validation not implemented for legacy fhir_validation.'
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
159
|
+
|
|
125
160
|
# @see Inferno::DSL::FHIRValidation#resource_is_valid?
|
|
126
161
|
# rubocop:disable Metrics/CyclomaticComplexity, Lint/UnusedMethodArgument
|
|
127
162
|
def resource_is_valid?(resource, profile_url, runnable, add_messages_to_runnable: true,
|
|
128
|
-
validator_response_details: nil)
|
|
163
|
+
message_prefix: '', validator_response_details: nil)
|
|
129
164
|
profile_url ||= FHIR::Definitions.resource_definition(resource.resourceType).url
|
|
130
165
|
|
|
131
166
|
begin
|
|
@@ -126,6 +126,34 @@ module Inferno
|
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
+
# Perform an HTTP PUT request
|
|
130
|
+
#
|
|
131
|
+
# @param url [String] if this request is using a defined client, this will
|
|
132
|
+
# be appended to the client's url. Must be an absolute url for requests
|
|
133
|
+
# made without a defined client
|
|
134
|
+
# @param body [String]
|
|
135
|
+
# @param client [Symbol]
|
|
136
|
+
# @param name [Symbol] Name for this request to allow it to be used by
|
|
137
|
+
# other tests
|
|
138
|
+
# @param headers [Hash] Input headers here
|
|
139
|
+
# @param tags [Array<String>] a list of tags to assign to the request
|
|
140
|
+
# @return [Inferno::Entities::Request]
|
|
141
|
+
def put(url = '', body: nil, client: :default, name: nil, headers: nil, tags: [])
|
|
142
|
+
store_request('outgoing', name:, tags:) do
|
|
143
|
+
tcp_exception_handler do
|
|
144
|
+
client = http_client(client)
|
|
145
|
+
|
|
146
|
+
if client
|
|
147
|
+
client.put(url, body, headers)
|
|
148
|
+
elsif url.match?(%r{\Ahttps?://})
|
|
149
|
+
connection.put(url, body, headers)
|
|
150
|
+
else
|
|
151
|
+
raise StandardError, 'Must use an absolute url or define an HTTP client with a base url'
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
129
157
|
# Perform an HTTP DELETE request
|
|
130
158
|
#
|
|
131
159
|
# @param url [String] if this request is using a defined client, this will
|
data/lib/inferno/dsl/messages.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative '../utils/markdown_formatter'
|
|
2
|
+
require_relative '../exceptions'
|
|
2
3
|
|
|
3
4
|
module Inferno
|
|
4
5
|
module DSL
|
|
@@ -10,6 +11,15 @@ module Inferno
|
|
|
10
11
|
@messages ||= []
|
|
11
12
|
end
|
|
12
13
|
|
|
14
|
+
# Returns true if an error message was logged to the runnable
|
|
15
|
+
#
|
|
16
|
+
# @param message_list [Array] (optional) list of messages to check for error,
|
|
17
|
+
# if not provided, the runnable's current list of messages will be checked
|
|
18
|
+
# @return [Boolean]
|
|
19
|
+
def error_messages?(message_list: messages)
|
|
20
|
+
message_list.any? { |msg| msg[:type] == 'error' }
|
|
21
|
+
end
|
|
22
|
+
|
|
13
23
|
# Add a message to the result.
|
|
14
24
|
#
|
|
15
25
|
# @param type [String] error, warning, or info
|
data/lib/inferno/dsl/runnable.rb
CHANGED
|
@@ -309,6 +309,21 @@ module Inferno
|
|
|
309
309
|
!optional?
|
|
310
310
|
end
|
|
311
311
|
|
|
312
|
+
# Mark as simulation verification. Tests are not simulation verification by default.
|
|
313
|
+
#
|
|
314
|
+
# @param simulation_verification [Boolean]
|
|
315
|
+
# @return [void]
|
|
316
|
+
def simulation_verification(simulation_verification = true) # rubocop:disable Style/OptionalBooleanParameter
|
|
317
|
+
@is_simulation_verification = simulation_verification
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# The test is simulation verification if true
|
|
321
|
+
#
|
|
322
|
+
# @return [Boolean]
|
|
323
|
+
def simulation_verification?
|
|
324
|
+
!!@is_simulation_verification
|
|
325
|
+
end
|
|
326
|
+
|
|
312
327
|
# @private
|
|
313
328
|
def default_id
|
|
314
329
|
to_s
|
data/lib/inferno/exceptions.rb
CHANGED
|
@@ -137,5 +137,12 @@ module Inferno
|
|
|
137
137
|
super("Could not find a child with an ID ending in '#{id}' for '#{runnable}'.")
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
|
+
|
|
141
|
+
class TestSuiteImplementationException < StandardError
|
|
142
|
+
def initialize(feature, details)
|
|
143
|
+
super("This test suite incorrectly used the #{feature}. " \
|
|
144
|
+
"Contact the developer with the following details: #{details}")
|
|
145
|
+
end
|
|
146
|
+
end
|
|
140
147
|
end
|
|
141
148
|
end
|