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

Allow matching out-of-order arrays with .in_any_order #83

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/json_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require "json_spec/exclusion"
require "json_spec/helpers"
require "json_spec/messages"
require "json_spec/indifference"
require "json_spec/matchers"
require "json_spec/memory"

Expand Down
25 changes: 25 additions & 0 deletions lib/json_spec/indifference.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module JsonSpec
module Indifference
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see this called OrderIndifference to be clearer about its function.

extend self

def toggle_indifference( toggle )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please omit spaces around arguments in the method signature.

@indifferent = !!toggle
end

def indifferize(ruby)
return ruby unless @indifferent

case ruby
when Hash
ruby.sort.inject({}) do |hash, (key, value)|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were hashes ever failing due to order dependence issues? If not, we should not bother sorting the incoming hash.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; good catch. I'll remove that.

I'll write a test spec for that case just to be sure this module can't break hash order (in)dependence in the future.

hash[key] = indifferize(value)
hash
end
when Array
ruby.map{|v| indifferize(v) }.sort_by{|v| generate_normalized_json(v) }
else ruby
end
end

end
end
8 changes: 7 additions & 1 deletion lib/json_spec/matchers/be_json_eql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Matchers
class BeJsonEql
include JsonSpec::Helpers
include JsonSpec::Exclusion
include JsonSpec::Indifference
include JsonSpec::Messages

attr_reader :expected, :actual
Expand Down Expand Up @@ -42,6 +43,11 @@ def including(*keys)
self
end

def order_indifferent(state = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts about a more human-friendly name for this like in_any_order?

expect(foo).to be_json_eql(bar).in_any_order

Just spitballing!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that a lot better, actually. I'll include that along with the other changes.

toggle_indifference(state)
self
end

def failure_message
message_with_path("Expected equivalent JSON")
end
Expand All @@ -58,7 +64,7 @@ def description

private
def scrub(json, path = nil)
generate_normalized_json(exclude_keys(parse_json(json, path))).chomp + "\n"
generate_normalized_json(indifferize(exclude_keys(parse_json(json, path)))).chomp + "\n"
end
end
end
Expand Down
21 changes: 21 additions & 0 deletions spec/json_spec/matchers/be_json_eql_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@
%(["json","spec"]).should_not be_json_eql(%(["spec","json"]))
end

it "matches out-of-order arrays when chained with order_indifferent" do
%(["json","spec"]).should be_json_eql(%(["spec","json"])).order_indifferent
end

it "doesn't match out-of-order arrays when chained with order_indifferent if passed false" do
%(["json","spec"]).should_not be_json_eql(%(["spec","json"])).order_indifferent(false)
end

it "matches complex nested out-of-order arrays when chained with order_indifferent" do
%({"json":[{"spec":4,"laser":[{"id":2,"lemon":"a"},{"id":5,"lemon":"b"}]},{"spec":9,"laser":[{"id":3,"lemon":"c"},{"id":1,"lemon":"d"}]}]}).should be_json_eql(%({"json":[{"laser":[{"lemon":"d","id":1},{"lemon":"c","id":3}],"spec":9},{"laser":[{"lemon":"b","id":5},{"lemon":"a","id":2}],"spec":4}]})).order_indifferent
end

it "matches valid JSON values, yet invalid JSON documents" do
%("json_spec").should be_json_eql(%("json_spec"))
end
Expand All @@ -25,6 +37,10 @@
%({"json":["spec"]}).should be_json_eql(%("spec")).at_path("json/0")
end

it "matches out-of-order arrays at a path when chained with order_indifferent" do
%({"json":[{"spec":[4,2,3,1,5]}]}).should be_json_eql(%([1,2,3,4,5])).at_path("json/0/spec").order_indifferent
end

it "ignores excluded-by-default hash keys" do
JsonSpec.excluded_keys.should_not be_empty

Expand Down Expand Up @@ -66,6 +82,11 @@
%({"id":1,"json":"spec"}).should be_json_eql(%({"id":2,"json":"spec"})).excluding(:id)
end

it "excludes extra hash keys given as symbols and matches out-of-order arrays when chained with order_indifferent" do
JsonSpec.excluded_keys = []
%([{"id":1,"json":"spec"},{"id":4,"json":"laser"}]).should be_json_eql(%([{"id":3,"json":"laser"},{"id":2,"json":"spec"}])).excluding(:id).order_indifferent
end

it "excludes multiple keys" do
JsonSpec.excluded_keys = []
%({"id":1,"json":"spec"}).should be_json_eql(%({"id":2,"json":"different"})).excluding(:id, :json)
Expand Down