inferno_core 0.4.19 → 0.4.21

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: 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