inferno_core 0.4.19 → 0.4.21

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: a9b06c0f0ce1702d3ba9662e4762e3174eb22527a19a3eb35a5ec0e01dbf57d3
4
- data.tar.gz: 8c019f778c84c0926ef1705e256e0d3b27fd39a2c6af4f32bd8c4d1ad731ff84
3
+ metadata.gz: 13f75c775423384dd5bf4a2b13081bc05a155155fca9a6bcea1986d2baf09b15
4
+ data.tar.gz: 7b6c586b121fad54caa57fb5ae8d8c7300467b543ece25c4222c21cc65ac83c7
5
5
  SHA512:
6
- metadata.gz: 39690b392f9e9997081cc5d58ee93c249a15be3eaeecca3927619f4d116e00cd85cdecc8a91693385420bb7b7bc07398b05b636d9be94713b23ad52c99bc9161
7
- data.tar.gz: f2970277134ae396003da04b2ba09c19cd3dc02f70e513cbdbeaf7a7e014561cbf742a95fc8ed40cec034a23723ad54ed823637989628dd0661fc467b49db11a
6
+ metadata.gz: 7f0ab91414e4554a430972dd25543339cd39245c0d154dcc42d0a623c83b4aeaccf32709d08074abd4dcae07cf3deb75144a2db3cd3af548a37ddc552b0df909
7
+ data.tar.gz: 2f328c92cb3d66853eccde4aee267be6e8e668b778f75e1d278a3b5d4ba86840e4f0e260fbc5bf941017ee8bde1cd20699a53153cd9e26ee8e9bee8fa730ab7c
@@ -60,26 +60,64 @@ module Inferno
60
60
  @fhir_clients ||= {}
61
61
  end
62
62
 
63
+ # Wrapper for checking if parameter contents are primitive
64
+ #
65
+ # @param param [FHIR::Parameters::Parameter] Parameter to be checked
66
+ # @private
67
+ def primitive_parameter?(param)
68
+ param_val = param.to_hash.except('name')
69
+ param_val.any? { |datatype, param_value| FHIR.primitive?(datatype: datatype[5..], value: param_value) }
70
+ end
71
+
72
+ # Converts a list of FHIR Parameters into a query string for GET requests
73
+ #
74
+ # @param body [FHIR::Parameters] Must all be primitive if making GET request
75
+ # @private
76
+ def body_to_path(body)
77
+ query_hashes = body.parameter.map do |param|
78
+ if primitive_parameter?(param)
79
+ { param.name => param.to_hash.except('name').values[0] }
80
+ else
81
+ Inferno::Application[:logger].error "Cannot use GET request with non-primitive datatype #{param.name}"
82
+ raise ArgumentError, "Cannot use GET request with non-primitive datatype #{param.name}"
83
+ end
84
+ end
85
+ query_hashes.map(&:to_query).join('&')
86
+ end
87
+
63
88
  # Perform a FHIR operation
64
89
  #
65
90
  # @note This is a placeholder method until the FHIR::Client supports
66
- # general operations
91
+ # general operations. Note that while both POST and GET methods are allowed,
92
+ # GET is only allowed when the operation does not affect the server's state.
93
+ # See https://build.fhir.org/operationdefinition-definitions.html#OperationDefinition.affectsState
94
+ #
95
+ # @note Currently does not allow for repeated parameters if using GET
67
96
  #
68
97
  # @param path [String]
69
- # @param body [FHIR::Parameters]
98
+ # @param body [FHIR::Parameters] Must all be primitive if making GET request
70
99
  # @param client [Symbol]
71
100
  # @param name [Symbol] Name for this request to allow it to be used by
72
101
  # other tests
73
102
  # @param headers [Hash] custom headers for this operation
103
+ # @param operation_method [Symbol] indicates which request type to use for the operation
74
104
  # @return [Inferno::Entities::Request]
75
- def fhir_operation(path, body: nil, client: :default, name: nil, headers: {})
105
+ def fhir_operation(path, body: nil, client: :default, name: nil, headers: {}, operation_method: :post)
76
106
  store_request_and_refresh_token(fhir_client(client), name) do
77
107
  tcp_exception_handler do
78
108
  operation_headers = fhir_client(client).fhir_headers
79
109
  operation_headers.merge!('Content-Type' => 'application/fhir+json') if body.present?
80
110
  operation_headers.merge!(headers) if headers.present?
81
-
82
- fhir_client(client).send(:post, path, body, operation_headers)
111
+ case operation_method
112
+ when :post
113
+ fhir_client(client).send(:post, path, body, operation_headers)
114
+ when :get
115
+ path = "#{path}?#{body_to_path(body)}" if body.present?
116
+ fhir_client(client).send(:get, path, operation_headers)
117
+ else
118
+ Inferno::Application[:logger].error "Cannot perform #{operation_method} requests, use GET or POST"
119
+ raise ArgumentError, "Cannot perform #{operation_method} requests, use GET or POST"
120
+ end
83
121
  end
84
122
  end
85
123
  end
@@ -116,14 +116,22 @@ module Inferno
116
116
  def resource_is_valid?(resource, profile_url, runnable)
117
117
  profile_url ||= FHIR::Definitions.resource_definition(resource.resourceType).url
118
118
 
119
- outcome, http_status = validate(resource, profile_url, runnable)
119
+ begin
120
+ response = call_validator(resource, profile_url)
121
+ rescue StandardError => e
122
+ # This could be a complete failure to connect (validator isn't running)
123
+ # or a timeout (validator took too long to respond).
124
+ runnable.add_message('error', e.message)
125
+ raise Inferno::Exceptions::ErrorInValidatorException, "Unable to connect to validator at #{url}."
126
+ end
127
+ outcome = operation_outcome_from_validator_response(response.body, runnable)
120
128
 
121
129
  message_hashes = message_hashes_from_outcome(outcome, resource, profile_url)
122
130
 
123
131
  message_hashes
124
132
  .each { |message_hash| runnable.add_message(message_hash[:type], message_hash[:message]) }
125
133
 
126
- unless http_status == 200
134
+ unless response.status == 200
127
135
  raise Inferno::Exceptions::ErrorInValidatorException,
128
136
  'Error occurred in the validator. Review Messages tab or validator service logs for more information.'
129
137
  end
@@ -191,21 +199,17 @@ module Inferno
191
199
  #
192
200
  # @param resource [FHIR::Model]
193
201
  # @param profile_url [String]
194
- # @param runnable [Inferno::Entities::Test]
195
- # @return [[Array(FHIR::OperationOutcome, Number)] the validation response and HTTP status code
196
- def validate(resource, profile_url, runnable)
197
- begin
198
- response = Faraday.new(
199
- url,
200
- params: { profile: profile_url }
201
- ).post('validate', resource.source_contents)
202
- rescue StandardError => e
203
- runnable.add_message('error', e.message)
204
- raise Inferno::Exceptions::ErrorInValidatorException, "Unable to connect to validator at #{url}."
205
- end
206
- outcome = operation_outcome_from_validator_response(response.body, runnable)
202
+ # @return [String] the body of the validation response
203
+ def validate(resource, profile_url)
204
+ call_validator(resource, profile_url).body
205
+ end
207
206
 
208
- [outcome, response.status]
207
+ # @private
208
+ def call_validator(resource, profile_url)
209
+ Faraday.new(
210
+ url,
211
+ params: { profile: profile_url }
212
+ ).post('validate', resource.source_contents)
209
213
  end
210
214
 
211
215
  # @private
@@ -213,7 +217,7 @@ module Inferno
213
217
  if response.start_with? '{'
214
218
  FHIR::OperationOutcome.new(JSON.parse(response))
215
219
  else
216
- runnable.add_message('error', "Validator Response: #{response}")
220
+ runnable.add_message('error', "Validator Response:\n#{response}")
217
221
  raise Inferno::Exceptions::ErrorInValidatorException,
218
222
  'Validator response was an unexpected format. '\
219
223
  'Review Messages tab or validator service logs for more information.'
@@ -39,11 +39,14 @@ module Inferno
39
39
  end
40
40
  end
41
41
 
42
+ # ErrorInValidatorException is used when an exception occurred in
43
+ # calling the validator service, for example a connection timeout
44
+ # or an unexpected response format.
45
+ # Note: This class extends TestResultException instead of RuntimeError
46
+ # to bypass printing the stack trace in the UI, since
47
+ # the stack trace of this exception is not likely be useful.
48
+ # Instead the message should point to where in the validator an error occurred.
42
49
  class ErrorInValidatorException < TestResultException
43
- # This extends TestResultException instead of RuntimeError
44
- # to bypass printing the stack trace in the UI.
45
- # (The stack trace of this exception may not be useful,
46
- # instead the message should point to where in the validator an error occurred)
47
50
  def result
48
51
  'error'
49
52
  end