Skip to content

Commit

Permalink
feat: parse String response and request bodies to StringWithMatchingR…
Browse files Browse the repository at this point in the history
…ules to support pact-xml
  • Loading branch information
bethesque committed Jul 14, 2018
1 parent babc319 commit a9fbb58
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 11 deletions.
68 changes: 57 additions & 11 deletions lib/pact/consumer_contract/interaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'pact/matching_rules'
require 'pact/errors'
require 'pact/specification_version'
require 'pact/consumer_contract/string_with_matching_rules'

module Pact
class Interaction
Expand All @@ -29,26 +30,67 @@ def self.from_hash hash, options = {}
end

def self.parse_v2_interaction hash, options
request_hash = Pact::MatchingRules.merge(hash['request'], hash['request']['matchingRules'], options)
request = Pact::Request::Expected.from_hash(request_hash)
response_hash = Pact::MatchingRules.merge(hash['response'], hash['response']['matchingRules'], options)
response = Pact::Response.from_hash(response_hash)
request = parse_v2_request(hash['request'], options)
response = parse_v2_response(hash['response'], options)
new(symbolize_keys(hash).merge(request: request, response: response))
end

def self.parse_v3_interaction hash, options
request = parse_v3_request(hash['request'], options)
response = parse_v3_response(hash['response'], options)
new(symbolize_keys(hash).merge(request: request, response: response))
end

def self.parse_v2_request request_hash, options
request_hash = Pact::MatchingRules.merge(request_hash, request_hash['matchingRules'], options)
Pact::Request::Expected.from_hash(request_hash)
end

def self.parse_v2_response response_hash, options
response_hash = Pact::MatchingRules.merge(response_hash, response_hash['matchingRules'], options)
Pact::Response.from_hash(response_hash)
end

request_hash = hash['request'].keys.each_with_object({}) do | key, new_hash |
new_hash[key] = Pact::MatchingRules.merge(hash['request'][key], hash['request'].fetch('matchingRules', {})[key], options)
def self.parse_v3_request request_hash, options
request_matching_rules = request_hash['matchingRules'] || {}
if request_hash['body'].is_a?(String)
parse_request_with_string_body(request_hash, request_matching_rules, options)
else
parse_v3_request_with_non_string_body(request_hash, request_matching_rules, options)
end
request = Pact::Request::Expected.from_hash(request_hash)
end

response_hash = hash['response'].keys.each_with_object({}) do | key, new_hash |
new_hash[key] = Pact::MatchingRules.merge(hash['response'][key], hash['response'].fetch('matchingRules', {})[key], options)
def self.parse_request_with_string_body request_hash, request_matching_rules, options
string_with_matching_rules = StringWithMatchingRules.new(request_hash['body'], options[:pact_specification_version], request_matching_rules)
Pact::Request::Expected.from_hash(request_hash.merge('body' => string_with_matching_rules))
end

def self.parse_v3_response response_hash, options
response_matching_rules = response_hash['matchingRules'] || {}
if response_hash['body'].is_a?(String)
parse_response_with_string_body(response_hash, response_matching_rules, options)
else
parse_v3_response_with_non_string_body(response_hash, response_matching_rules, options)
end
end

response = Pact::Response.from_hash(response_hash)
new(symbolize_keys(hash).merge(request: request, response: response))
def self.parse_response_with_string_body response_hash, response_matching_rules, options
string_with_matching_rules = StringWithMatchingRules.new(response_hash['body'], options[:pact_specification_version], response_matching_rules)
Pact::Response.from_hash(response_hash.merge('body' => string_with_matching_rules))
end

def self.parse_v3_request_with_non_string_body request_hash, request_matching_rules, options
request_hash = request_hash.keys.each_with_object({}) do | key, new_hash |
new_hash[key] = Pact::MatchingRules.merge(request_hash[key], request_matching_rules[key], options)
end
Pact::Request::Expected.from_hash(request_hash)
end

def self.parse_v3_response_with_non_string_body response_hash, response_matching_rules, options
response_hash = response_hash.keys.each_with_object({}) do | key, new_hash |
new_hash[key] = Pact::MatchingRules.merge(response_hash[key], response_matching_rules[key], options)
end
Pact::Response.from_hash(response_hash)
end

def to_hash
Expand Down Expand Up @@ -100,5 +142,9 @@ def request_modifies_resource_without_checking_response_body?
def to_s
to_hash.to_s
end

def self.is_xml? body
body.is_a?(String) && body.start_with?("<")
end
end
end
17 changes: 17 additions & 0 deletions lib/pact/consumer_contract/string_with_matching_rules.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Pact
class StringWithMatchingRules < String
attr_reader :matching_rules
attr_reader :pact_specification_version

def initialize string, pact_specification_version, matching_rules = {}
super(string)
@matching_rules = matching_rules
@pact_specification_version = pact_specification_version
end

# How can we show the matching rules too?
def to_s
super
end
end
end
28 changes: 28 additions & 0 deletions spec/lib/pact/consumer_contract/interaction_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@ module Consumer
expect(subject.response.body['_links']['self']['href']).to be_instance_of(Pact::Term)
end
end

context "when the request body is XML" do
let(:hash) { { 'request' => request, 'response' => response } }
subject { Interaction.from_hash hash, pact_specification_version: Pact::SpecificationVersion.new("3") }

let(:request) { { 'method' => 'get', 'path' => 'path' , 'body' => "<xml></xml>", 'matchingRules' => {"foo" => "bar" } } }

it "returns an interaction with an StringWithMatchingRules in the request" do
expect(subject.request.body).to be_a(Pact::StringWithMatchingRules)
expect(subject.request.body).to eq "<xml></xml>"
expect(subject.request.body.matching_rules).to eq "foo" => "bar"
expect(subject.request.body.pact_specification_version).to eq Pact::SpecificationVersion.new("3")
end
end

context "when the response body is XML" do
let(:hash) { { 'request' => request, 'response' => response } }
subject { Interaction.from_hash hash, pact_specification_version: Pact::SpecificationVersion.new("3") }

let(:response) { { 'status' => '200', 'body' => "<xml></xml>", 'matchingRules' => {"foo" => "bar" } } }

it "returns an interaction with an StringWithMatchingRules in the response" do
expect(subject.response.body).to be_a(Pact::StringWithMatchingRules)
expect(subject.response.body).to eq "<xml></xml>"
expect(subject.response.body.matching_rules).to eq "foo" => "bar"
expect(subject.response.body.pact_specification_version).to eq Pact::SpecificationVersion.new("3")
end
end
end

describe "request_modifies_resource_without_checking_response_body?" do
Expand Down

0 comments on commit a9fbb58

Please sign in to comment.