lib/soaspec/exchange_handlers/response_extractor.rb in soaspec-0.2.24 vs lib/soaspec/exchange_handlers/response_extractor.rb in soaspec-0.2.25

- old
+ new

@@ -1,82 +1,82 @@ -module Soaspec - # Enables extracting a response according to type / path - module ResponseExtractor - # 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 - 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 'Incorrect Type produced ' + converted.class - else - raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}" - end - end - - # @param [Object] response Response object - # @return [Hash] Hash representing response body - 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}" - end - end - - private - - # @param [String] xml XML to convert - # @return [Hash] Hash representing XML - def parse_xml(xml) - parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym }) - parser.parse(xml) - end - - # 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 - 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 - - # Convert snakecase to PascalCase - # @return [String] PascalCase converted path - 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 - - # Find element with name specified or pascal case equivalent - # @return [String] String to find paths with pascal converted or given path - 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 - - # @param [String] json_path Path set from Exchange - # @return [String] JSON Path - def prefix_json_path(json_path) - return json_path if json_path[0] == '$' - - "$..#{json_path}" - end - end -end +module Soaspec + # Enables extracting a response according to type / path + module ResponseExtractor + # 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 + 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 'Incorrect Type produced ' + converted.class + else + raise "Neither XML nor JSON detected. It is #{type}. Don't know how to parse It is #{response.body}" + end + end + + # @param [Object] response Response object + # @return [Hash] Hash representing response body + 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}" + end + end + + private + + # @param [String] xml XML to convert + # @return [Hash] Hash representing XML + def parse_xml(xml) + parser = Nori.new(strip_namespaces: strip_namespaces?, convert_tags_to: ->(tag) { tag.snakecase.to_sym }) + parser.parse(xml) + end + + # 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 + 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 + + # Convert snakecase to PascalCase + # @return [String] PascalCase converted path + 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 + + # Find element with name specified or pascal case equivalent + # @return [String] String to find paths with pascal converted or given path + 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 + + # @param [String] json_path Path set from Exchange + # @return [String] JSON Path + def prefix_json_path(json_path) + return json_path if json_path[0] == '$' + + "$..#{json_path}" + end + end +end