module Soaspec::ResponseExtractor

Enables extracting a response according to type / path

Public Instance Methods

extract_hash(response) click to toggle source

Convert XML or JSON response into a Hash. Doesn't accept empty body @param [String] response Response as a String (either in XML or JSON) @return [Hash] Extracted Hash from response

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 9
def extract_hash(response)
  raise NoElementAtPath, "Empty Body. Can't assert on it" if response.body.empty?

  case Interpreter.response_type_for response
  when :xml then parse_xml(response.body.to_s)
  when :json
    converted = JSON.parse(response.body)
    return converted.transform_keys_to_symbols if converted.is_a? Hash
    return converted.map!(&:transform_keys_to_symbols) if converted.is_a? Array

    raise Soaspec::ResponseError, 'Incorrect Type produced ' + converted.class
  else
    raise Soaspec::ResponseError, "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}"
  end
end
to_hash(response) click to toggle source

@param [Object] response Response object @return [Hash] Hash representing response body

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 27
def to_hash(response)
  case Interpreter.response_type_for(response)
  when :xml then IndifferentHash.new(parse_xml(response.body.to_s))
  when :json
    IndifferentHash.new(JSON.parse(response.body.to_s))
  else
    raise "Unable to interpret type of '#{response.body}'. Could be because of: #{Interpreter.diagnose_error}"
  end
end

Private Instance Methods

add_pascal_path(json_path) click to toggle source

Find element with name specified or pascal case equivalent @return [String] String to find paths with pascal converted or given path

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 68
def add_pascal_path(json_path)
  return json_path unless pascal_keys?

  json_path.split(',').collect do |sub_path|
    "#{sub_path},#{convert_to_pascal_case(sub_path)}"
  end.join(',')
end
convert_to_pascal_case(key) click to toggle source

Convert snakecase to PascalCase @return [String] PascalCase converted path

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 60
def convert_to_pascal_case(key)
  return key if /[[:upper:]]/ =~ key[0] # If first character already capital, don't do conversion

  key.split('_').map(&:capitalize).join
end
parse_xml(xml) click to toggle source

@param [String] xml XML to convert @return [Hash] Hash representing XML

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 41
def parse_xml(xml)
  parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym })
  parser.parse(xml)
end
prefix_json_path(json_path) click to toggle source

@param [String] json_path Path set from Exchange @return [String] JSON Path

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 78
def prefix_json_path(json_path)
  return json_path if json_path[0] == '$'

  "$..#{json_path}"
end
prefix_xpath(xpath, attribute) click to toggle source

This enables shortcut xpaths to be used. If no '/' is given, one is appended to the start of the path If attribute value is set then this is also adjusted @return [String] New Xpath adjusted according to any add ons

# File lib/soaspec/exchange_handlers/response_extractor.rb, line 49
def prefix_xpath(xpath, attribute)
  xpath = "//*[@#{attribute}]" unless attribute.nil?
  if xpath[0] != '/'
    xpath = convert_to_pascal_case(xpath) if pascal_keys?
    xpath = '//' + xpath
  end
  xpath
end