diff --git a/lib/pact/configuration.rb b/lib/pact/configuration.rb index efb1865..952a475 100644 --- a/lib/pact/configuration.rb +++ b/lib/pact/configuration.rb @@ -1,9 +1,11 @@ require 'pact/matchers/embedded_diff_formatter' require 'pact/matchers/unix_diff_formatter' require 'pact/matchers/list_diff_formatter' +require 'pact/matchers/multipart_form_diff_formatter' require 'pact/shared/json_differ' require 'pact/shared/text_differ' require 'pact/shared/form_differ' +require 'pact/shared/multipart_form_differ' module Pact @@ -24,6 +26,7 @@ def self.=~ other end DIFF_FORMATTER_REGISTRATIONS = [ + [/multipart\/form-data/, Pact::Matchers::MultipartFormDiffFormatter], [/.*/, Pact::Matchers::UnixDiffFormatter], [NilMatcher, Pact::Matchers::UnixDiffFormatter] ] @@ -31,6 +34,7 @@ def self.=~ other DIFFERS = [ [/json/, Pact::JsonDiffer], [/application\/x\-www\-form\-urlencoded/, Pact::FormDiffer], + [/multipart\/form-data/, Pact::MultipartFormDiffer], [NilMatcher, Pact::TextDiffer], [/.*/, Pact::TextDiffer] ] diff --git a/lib/pact/consumer_contract/request.rb b/lib/pact/consumer_contract/request.rb index ab75dab..3efe06d 100644 --- a/lib/pact/consumer_contract/request.rb +++ b/lib/pact/consumer_contract/request.rb @@ -2,9 +2,7 @@ require 'pact/shared/null_expectation' module Pact - module Request - class Expected < Pact::Request::Base DEFAULT_OPTIONS = {:allow_unexpected_keys => false}.freeze @@ -80,8 +78,6 @@ def body_diff(actual_body) def body_differ Pact.configuration.body_differ_for_content_type content_type end - end - end -end \ No newline at end of file +end diff --git a/lib/pact/matchers/multipart_form_diff_formatter.rb b/lib/pact/matchers/multipart_form_diff_formatter.rb new file mode 100644 index 0000000..720d898 --- /dev/null +++ b/lib/pact/matchers/multipart_form_diff_formatter.rb @@ -0,0 +1,41 @@ +require 'pact/matchers/unix_diff_formatter' +require 'pact/matchers/differ' + +module Pact + module Matchers + class MultipartFormDiffFormatter + + def initialize diff, options = {} + @options = options + @body_diff = diff[:body] + @non_body_diff = diff.reject{ |k, v| k == :body } + @colour = options.fetch(:colour, false) + @differ = Pact::Matchers::Differ.new(@colour) + end + + def self.call diff, options = {} + new(diff, options).call + end + + def call + Pact::Matchers::UnixDiffFormatter::MESSAGES_TITLE + "\n" + non_body_diff_string + "\n" + body_diff_string + end + + def non_body_diff_string + if @non_body_diff.any? + Pact::Matchers::ExtractDiffMessages.call(@non_body_diff).collect{ | message| "* #{message}" }.join("\n") + else + "" + end + end + + def body_diff_string + if @body_diff + @differ.diff_as_string(@body_diff.expected, @body_diff.actual) + else + "" + end + end + end + end +end diff --git a/lib/pact/shared/multipart_form_differ.rb b/lib/pact/shared/multipart_form_differ.rb new file mode 100644 index 0000000..7191f63 --- /dev/null +++ b/lib/pact/shared/multipart_form_differ.rb @@ -0,0 +1,14 @@ +require 'uri' +require 'pact/shared/text_differ' + +module Pact + class MultipartFormDiffer + def self.call expected, actual, options = {} + require 'pact/matchers' # avoid recursive loop between this file and pact/matchers + expected_boundary = expected.split.first + actual_boundary = actual.split.first + actual_with_hardcoded_boundary = actual.gsub(actual_boundary, expected_boundary) + TextDiffer.call(expected, actual_with_hardcoded_boundary, options) + end + end +end diff --git a/spec/fixtures/multipart-form-diff.txt b/spec/fixtures/multipart-form-diff.txt new file mode 100644 index 0000000..e17e8ba --- /dev/null +++ b/spec/fixtures/multipart-form-diff.txt @@ -0,0 +1,9 @@ + + +Description of differences +-------------------------------------- +* Wrong header + +@@ -1,2 +1,2 @@ +-bar ++foo diff --git a/spec/lib/pact/matchers/multipart_form_diff_formatter_spec.rb b/spec/lib/pact/matchers/multipart_form_diff_formatter_spec.rb new file mode 100644 index 0000000..5bc8ecf --- /dev/null +++ b/spec/lib/pact/matchers/multipart_form_diff_formatter_spec.rb @@ -0,0 +1,36 @@ +require 'pact/matchers/multipart_form_diff_formatter' + +module Pact + module Matchers + describe MultipartFormDiffFormatter do + describe ".call" do + subject { MultipartFormDiffFormatter.call(diff, options)} + + let(:diff) do + { + headers: header_diff, + body: body_diff + } + end + + let(:header_diff) do + { + "Content-Type" => Difference.new("foo", "bar", "Wrong header") + } + end + + let(:body_diff) do + Difference.new("foo", "bar", "A message") + end + + let(:options) { {} } + + let(:expected_output) { File.read("spec/fixtures/multipart-form-diff.txt")} + + it "formats the diff" do + expect(subject).to eq expected_output + end + end + end + end +end diff --git a/spec/lib/pact/shared/multipart_form_differ_spec.rb b/spec/lib/pact/shared/multipart_form_differ_spec.rb new file mode 100644 index 0000000..baed782 --- /dev/null +++ b/spec/lib/pact/shared/multipart_form_differ_spec.rb @@ -0,0 +1,39 @@ +require 'pact/shared/multipart_form_differ' + +module Pact + describe MultipartFormDiffer do + + describe ".call" do + + let(:expected_body) do + "-------------RubyMultipartPost-1e4912957c7bb64de3c444568326663b\r\nContent-Disposition: form-data; name=\"file\"; filename=\"text.txt\"\r\nContent-Length: 14\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nThis is a file\r\n-------------RubyMultipartPost-1e4912957c7bb64de3c444568326663b--\r\n\r\n" + end + + let(:actual_body) do + "-------------RubyMultipartPost-1e4912957c7bb64de3c4445683266XXX\r\nContent-Disposition: form-data; name=\"file\"; filename=\"text.txt\"\r\nContent-Length: 14\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nThis is a file\r\n-------------RubyMultipartPost-1e4912957c7bb64de3c4445683266XXX--\r\n\r\n" + end + + let(:options) do + {} + end + + subject { MultipartFormDiffer.call(expected_body, actual_body, options) } + + context "when the bodies are the same apart from the boundary" do + it "returns an empty diff" do + expect(subject).to eq({}) + end + end + + context "when the bodies are not the same" do + let(:actual_body) do + "-------------RubyMultipartPost-1e4912957c7bb64de3c4445683266XXX\r\nContent-Disposition: form-data; name=\"file\"; filename=\"bar.txt\"\r\nContent-Length: 14\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: binary\r\n\r\nThis is a file\r\n-------------RubyMultipartPost-1e4912957c7bb64de3c4445683266XXX--\r\n\r\n" + end + + it "returns a text diff" do + expect(subject).to_not eq({}) + end + end + end + end +end