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 +4 -4
- data/lib/inferno/dsl/fhir_client.rb +43 -5
- data/lib/inferno/dsl/fhir_validation.rb +21 -17
- data/lib/inferno/exceptions.rb +7 -4
- data/lib/inferno/public/bundle.js +12 -12
- data/lib/inferno/version.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: 13f75c775423384dd5bf4a2b13081bc05a155155fca9a6bcea1986d2baf09b15
         | 
| 4 | 
            +
              data.tar.gz: 7b6c586b121fad54caa57fb5ae8d8c7300467b543ece25c4222c21cc65ac83c7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 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 | 
            -
                         | 
| 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 | 
            -
                       | 
| 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  | 
| 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 | 
            -
                    # @ | 
| 195 | 
            -
                     | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
| 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.'
         | 
    
        data/lib/inferno/exceptions.rb
    CHANGED
    
    | @@ -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
         |