Permalink
Browse files

Fixed problem with matching requests with json body, when json string…

…s had date format.
  • Loading branch information...
bblimke committed Aug 8, 2011
1 parent af4c054 commit 772585e7025803e786234e4957c89e1244eb7ee1
Showing with 95 additions and 1 deletion.
  1. +1 −0 lib/webmock.rb
  2. +1 −1 lib/webmock/request_pattern.rb
  3. +54 −0 lib/webmock/util/json.rb
  4. +7 −0 spec/util/json_spec.rb
  5. +32 −0 spec/webmock_shared.rb
View
@@ -18,6 +18,7 @@
require 'webmock/util/headers'
require 'webmock/util/hash_counter'
require 'webmock/util/hash_keys_stringifier'
+require 'webmock/util/json'
require 'webmock/request_pattern'
require 'webmock/request_signature'
@@ -143,7 +143,7 @@ def matches?(body, content_type = "")
case BODY_FORMATS[content_type]
when :json then
- matching_hashes?(Crack::JSON.parse(body), @pattern)
+ matching_hashes?(WebMock::Util::JSON.parse(body), @pattern)
when :xml then
matching_hashes?(Crack::XML.parse(body), @pattern)
else
View
@@ -0,0 +1,54 @@
+# This is a copy of https://github.com/jnunemaker/crack/blob/master/lib/crack/json.rb
+# with date parsing removed
+module WebMock
+ module Util
+ class JSON
+ def self.parse(json)
+ YAML.load(unescape(convert_json_to_yaml(json)))
+ rescue ArgumentError => e
+ raise ParseError, "Invalid JSON string"
+ end
+
+ protected
+ def self.unescape(str)
+ str.gsub(/\\u([0-9a-f]{4})/) { [$1.hex].pack("U") }
+ end
+
+ # Ensure that ":" and "," are always followed by a space
+ def self.convert_json_to_yaml(json) #:nodoc:
+ scanner, quoting, marks, pos, times = StringScanner.new(json), false, [], nil, []
+ while scanner.scan_until(/(\\['"]|['":,\\]|\\.)/)
+ case char = scanner[1]
+ when '"', "'"
+ if !quoting
+ quoting = char
+ pos = scanner.pos
+ elsif quoting == char
+ quoting = false
+ end
+ when ":",","
+ marks << scanner.pos - 1 unless quoting
+ when "\\"
+ scanner.skip(/\\/)
+ end
+ end
+
+ if marks.empty?
+ json.gsub(/\\\//, '/')
+ else
+ left_pos = [-1].push(*marks)
+ right_pos = marks << json.length
+ output = []
+ left_pos.each_with_index do |left, i|
+ output << json[left.succ..right_pos[i]]
+ end
+ output = output * " "
+
+ times.each { |i| output[i-1] = ' ' }
+ output.gsub!(/\\\//, '/')
+ output
+ end
+ end
+ end
+ end
+end
View
@@ -0,0 +1,7 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe WebMock::Util::JSON do
+ it "should parse json without parsing dates" do
+ WebMock::Util::JSON.parse("\"a\":\"2011-01-01\"").should == {"a" => "2011-01-01"}
+ end
+end
View
@@ -300,6 +300,14 @@ class MyException < StandardError; end;
:body => "{\"a\":\"1\",\"b\":\"five\",\"c\":{\"d\":[\"e\",\"f\"]}}").status.should == "200"
end
+ it "should match if hash contains date string" do #Crack creates date object
+ WebMock.reset!
+ stub_http_request(:post, "www.example.com").
+ with(:body => {"foo" => "2010-01-01"})
+ http_request(
+ :post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
+ :body => "{\"foo\":\"2010-01-01\"}").status.should == "200"
+ end
end
describe "for request with xml body and content type is set to xml" do
@@ -321,6 +329,15 @@ class MyException < StandardError; end;
:body => "<opt b=\"five\" a=\"1\">\n <c>\n <d>e</d>\n <d>f</d>\n </c>\n</opt>\n").status.should == "200"
end
+ it "should match if hash contains date string" do #Crack creates date object
+ WebMock.reset!
+ stub_http_request(:post, "www.example.com").
+ with(:body => {"opt" => {"foo" => "2010-01-01"}})
+ http_request(
+ :post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
+ :body => "<opt foo=\"2010-01-01\">\n</opt>\n").status.should == "200"
+ end
+
end
end
@@ -1141,6 +1158,13 @@ def call(request)
}.should_not raise_error
end
+ it "should succeed if json body contains date string" do
+ lambda {
+ http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/json'},
+ :body => "{\"foo\":\"2010-01-01\"}")
+ a_request(:post, "www.example.com").with(:body => {"foo" => "2010-01-01"}).should have_been_made
+ }.should_not raise_error
+ end
end
@@ -1163,6 +1187,14 @@ def call(request)
}.should_not raise_error
end
+ it "should succeed if xml body contains date string" do
+ lambda {
+ http_request(:post, "http://www.example.com/", :headers => {'Content-Type' => 'application/xml'},
+ :body => "<opt foo=\"2010-01-01\">\n</opt>\n")
+ a_request(:post, "www.example.com").with(:body => {"opt" => {"foo" => "2010-01-01"}}).should have_been_made
+ }.should_not raise_error
+ end
+
end
end

0 comments on commit 772585e

Please sign in to comment.