Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore JSON keys order when stubbing a request fixes #485 #649

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/webmock/request_pattern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def with(options = {}, &block)
def matches?(request_signature)
content_type = request_signature.headers['Content-Type'] if request_signature.headers
content_type = content_type.split(';').first if content_type

@method_pattern.matches?(request_signature.method) &&
@uri_pattern.matches?(request_signature.uri) &&
(@body_pattern.nil? || @body_pattern.matches?(request_signature.body, content_type || "")) &&
Expand Down Expand Up @@ -235,6 +236,17 @@ def matches?(body, content_type = "")
matching_hashes?(body_as_hash(body, content_type), @pattern)
elsif (@pattern).is_a?(WebMock::Matchers::HashIncludingMatcher)
@pattern == body_as_hash(body, content_type)
elsif @pattern.is_a?(String) && BODY_FORMATS[content_type] == :json
begin
# Would have used WebMock::Util::JSON.parse in the #body_as_hash method,
# but it doesn't raise on invalid JSON, e.g. "foo bar".
actual = normalize_hash(JSON.parse(body))
expected = normalize_hash(JSON.parse(@pattern))
rescue JSON::ParserError
return matches?(body)
end

matching_hashes?(actual, expected)
else
empty_string?(@pattern) && empty_string?(body) ||
@pattern == body ||
Expand Down
55 changes: 48 additions & 7 deletions spec/unit/request_pattern_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

describe WebMock::RequestPattern do

before(:all) do
WebMock::RequestPattern.send(:alias_method, :match, :matches?)
end

describe "describing itself" do
it "should report string describing itself" do
expect(WebMock::RequestPattern.new(:get, "www.example.com",
Expand Down Expand Up @@ -62,13 +66,6 @@
end
end


class WebMock::RequestPattern
def match(request_signature)
self.matches?(request_signature)
end
end

describe "when matching" do

it "should match if uri matches and method matches" do
Expand Down Expand Up @@ -506,6 +503,50 @@ def match(request_signature)
not_to match(signature)
end
end

describe "when body in pattern is declared as a JSON string" do
let(:body_json) do
JSON.generate({ :a => '1', :b => 'five', 'c' => { 'd' => ['e', 'f'] } })
end

describe "for request with json body and content type is set to json" do
it "should match if JSON body matches body" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_json)).
to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/json'},
body: '{"a":"1","b":"five","c":{"d":["e","f"]}}'))
end

it "should match when JSON body matches body in different order" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_json)).
to match(WebMock::RequestSignature.new(:post, "www.example.com", headers: {content_type: 'application/json'},
body: '{"a":"1","c":{"d":["e","f"]},"b":"five"}'))
end

it "should not match when body is not json" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: body_json)).
not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
headers: {content_type: 'application/json'}, body: "foo bar"))
end

it "should not match if request body is different" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: JSON.generate({a: 1, b: 2}))).
not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
headers: {content_type: 'application/json'}, body: '{"a":1,"c":null}'))
end

it "should not match if request body is has less params than pattern" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: JSON.generate({a: 1, b: 2}))).
not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
headers: {content_type: 'application/json'}, body: '{"a":1}'))
end

it "should not match if request body is has more params than pattern" do
expect(WebMock::RequestPattern.new(:post, 'www.example.com', body: JSON.generate({a: 1}))).
not_to match(WebMock::RequestSignature.new(:post, "www.example.com",
headers: {content_type: 'application/json'}, body: '{"a":1,"c":1}'))
end
end
end
end

it "should match if pattern and request have the same headers" do
Expand Down