Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

New matcher that asserts presence of the given fields #35

Open
wants to merge 7 commits into from

4 participants

@AlexanderPavlenko

No description provided.

lib/json_spec/matchers.rb
@@ -25,6 +26,10 @@ def have_json_type(type)
def have_json_size(size)
JsonSpec::Matchers::HaveJsonSize.new(size)
end
+
+ def have_json_fields(size)
@laserlemon Owner

This should be fields rather than size, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@laserlemon
Owner

Please reference #25 to see what I'd like to see in order to pull this in. Thank you!

@AlexanderPavlenko

@laserlemon check out latest commit

@inossidabile

@laserlemon are there any other problems with this pr? :)

@laserlemon
Owner

@AlexanderPavlenko Thanks for all of your work! There are just a couple things I would change and I'll comment on those individually in the diff. Thank you again!

features/keys.feature
((3 lines not shown))
+ Given the JSON is:
+ """
+ {
+ "a": 1,
+ "b": 2,
+ "c": 3,
+ "z" : {
+ "d": 4,
+ "e": 5
+ }
+ }
+ """
+
+ Scenario: Base paths
+ When I get the JSON
+ Then the JSON should have keys "a, b, c"
@laserlemon Owner

Since "a, b, c" is a valid JSON key, we should separate each key out into its own quotes:

Then the JSON should have keys "a", "b", "c"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/json_spec/cucumber.rb
@@ -59,7 +59,7 @@
end
Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should have the following:$/ do |base, table|
- table.rows.each do |path, value|
+ table.raw.each do |path, value|
@laserlemon Owner

This doesn't belong in this pull request. I believe that is a valid fix, referencing #33, but it should be in its own PR with tests.

I found this hard to test nicely within current tests suite, because assertion which is true for N items is also true for any subset of those items.
Also, I faced (very accidently) this issue here — https://github.com/collectiveidea/json_spec/pull/35/files#L2R74 , so I don't see many sense in keeping that aside and reverting this line.

@laserlemon Owner

We don't need to revert it if we can add a test. If he problem is that the first element is ignored, make the first element invalid and the rest valid. Then assert a non-match.

oh, good point

Wait, not so good. Two things:
1) There is no such step "the JSON should not have the following"
2) Is that really the expected behavior for mixed valid/invalid table entries? Logically, their set is neither included, nor excluded from the tested one. They just intersect. So it should fail.

@laserlemon Owner
  1. Good point.
  2. I don't understand.

I think the expected behavior would be that if a single invalid entry is included in the table, the assertion should fail. That said, if we don't have a negative step definition, we should be testing that the positive assertion fails.

I mean this example should fail, but it pass because at least one entry is invalid.

And the JSON should not have the following keys:
  | invalid           |
  | valid             |
  | another_valid     |
@laserlemon Owner

Right. So we could write a test to assert that that fails. Make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@charlierudolph charlierudolph commented on the diff
lib/json_spec/cucumber.rb
@@ -70,6 +70,16 @@
end
end
+Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have the following keys:$/ do |base, negative, table|
+ match = have_json_keys(table.raw)
+ match = match.at_path(base) if base

Please rename base to path to be consistent.
Can then shorten to one line as its works if path is nil.

match = have_json_keys(table.raw).at_path(path)

Nice drying up. Will make use of this pattern to dry up the rest of cucumber later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@charlierudolph charlierudolph commented on the diff
README.md
@@ -11,6 +11,7 @@ json_spec defines five new RSpec matchers:
* `be_json_eql`
* `include_json`
* `have_json_path`
+* `have_json_keys`

Also need to update the count of methods this gem adds a few lines above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 21, 2013
  1. @inossidabile @AlexanderPavlenko

    HaveJsonFields matcher

    inossidabile authored AlexanderPavlenko committed
  2. @AlexanderPavlenko
  3. @AlexanderPavlenko

    rename variable

    AlexanderPavlenko authored AlexanderPavlenko committed
  4. @AlexanderPavlenko

    support cucumber have_json_keys matcher; improve tests; fix bug with …

    AlexanderPavlenko authored AlexanderPavlenko committed
    …table.rows
  5. @AlexanderPavlenko

    fix check logic

    AlexanderPavlenko authored AlexanderPavlenko committed
  6. @AlexanderPavlenko

    support arbitrary json keys

    AlexanderPavlenko authored AlexanderPavlenko committed
  7. @AlexanderPavlenko

    keys feature

    AlexanderPavlenko authored
This page is out of date. Refresh to see the latest.
View
1  README.md
@@ -11,6 +11,7 @@ json_spec defines five new RSpec matchers:
* `be_json_eql`
* `include_json`
* `have_json_path`
+* `have_json_keys`

Also need to update the count of methods this gem adds a few lines above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
* `have_json_type`
* `have_json_size`
View
39 features/keys.feature
@@ -0,0 +1,39 @@
+Feature: Paths
+ Background:
+ Given the JSON is:
+ """
+ {
+ "a": 1,
+ "b": 2,
+ "c": 3,
+ "z" : {
+ "d": 4,
+ "e": 5
+ },
+ "strange keys: '\_(\")_/', FTW!": true
+ }
+ """
+
+ Scenario: Base paths
+ When I get the JSON
+ Then the JSON should have keys "a", "b", "c"
+ And the JSON should not have keys "d", "e"
+ And the JSON at "z" should have keys "d", "e"
+ And the JSON at "z" should not have keys "m", "z"
+ And the JSON should have keys "strange keys: '\_(\")_/', FTW!", "a", "b"
+
+ Scenario: Table format
+ When I get the JSON
+ Then the JSON should have the following keys:
+ | a |
+ | b |
+ | c |
+ And the JSON should not have the following keys:
+ | d |
+ | e |
+ And the JSON at "z" should have the following keys:
+ | d |
+ | e |
+ And the JSON at "z" should not have the following keys:
+ | m |
+ | z |
View
21 lib/json_spec/cucumber.rb
@@ -70,6 +70,16 @@
end
end
+Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have the following keys:$/ do |base, negative, table|
+ match = have_json_keys(table.raw)
+ match = match.at_path(base) if base

Please rename base to path to be consistent.
Can then shorten to one line as its works if path is nil.

match = have_json_keys(table.raw).at_path(path)

Nice drying up. Will make use of this pattern to dry up the rest of cucumber later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ if negative
+ last_json.should_not match
+ else
+ last_json.should match
+ end
+end
+
Then /^the (?:JSON|json)(?: response)? should( not)? have "(.*)"$/ do |negative, path|
if negative
last_json.should_not have_json_path(path)
@@ -78,6 +88,17 @@
end
end
+Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? have keys (.*)$/ do |base, negative, keys|
+ keys = eval("[#{keys}]")
+ match = have_json_keys(keys)
+ match = match.at_path(base) if base
+ if negative
+ last_json.should_not match
+ else
+ last_json.should match
+ end
+end
+
Then /^the (?:JSON|json)(?: response)?(?: at "(.*)")? should( not)? be an? (.*)$/ do |path, negative, type|
if negative
last_json.should_not have_json_type(type).at_path(path)
View
5 lib/json_spec/matchers.rb
@@ -3,6 +3,7 @@
require "json_spec/matchers/have_json_path"
require "json_spec/matchers/have_json_type"
require "json_spec/matchers/have_json_size"
+require "json_spec/matchers/have_json_keys"
module JsonSpec
module Matchers
@@ -25,6 +26,10 @@ def have_json_type(type)
def have_json_size(size)
JsonSpec::Matchers::HaveJsonSize.new(size)
end
+
+ def have_json_keys(*keys)
+ JsonSpec::Matchers::HaveJsonKeys.new(keys.flatten)
+ end
end
end
View
35 lib/json_spec/matchers/have_json_keys.rb
@@ -0,0 +1,35 @@
+module JsonSpec
+ module Matchers
+ class HaveJsonKeys
+ include JsonSpec::Helpers
+ include JsonSpec::Messages
+
+ def initialize(keys)
+ @keys = keys
+ end
+
+ def matches?(json)
+ @data = parse_json(json, @path)
+ return false unless @data.is_a?(Hash)
+ @keys.all?{|key| @data.has_key?(key.to_s)}
+ end
+
+ def at_path(path)
+ @path = path
+ self
+ end
+
+ def failure_message_for_should
+ message_with_path("Expected JSON to contain all of the following keys #{@keys.join(", ")}")
+ end
+
+ def failure_message_for_should_not
+ message_with_path("Expected JSON to not contain any of the following keys #{@keys.join(", ")}")
+ end
+
+ def description
+ message_with_path(%(have JSON keys "#{@keys.join(", ")}"))
+ end
+ end
+ end
+end
View
43 spec/json_spec/matchers/have_json_keys_spec.rb
@@ -0,0 +1,43 @@
+require "spec_helper"
+
+describe JsonSpec::Matchers::HaveJsonKeys do
+ it "fails for non-hashes" do
+ %([1,2,3]).should_not have_json_keys
+ %(1).should_not have_json_keys
+ %("test").should_not have_json_keys
+ end
+
+ it "fails for bigger set of keys" do
+ %({"a": "1", "b": "2"}).should_not have_json_keys(:a, :b, :c)
+ end
+
+ it "matches for equal set of keys" do
+ [:a, :b, :c].permutation.each do |keys|
+ %({"a": "1", "b": "2", "c": "3"}).should have_json_keys(*keys)
+ end
+ end
+
+ it "matches for smaller set of keys" do
+ %({"a": "1", "b": "2", "c": "3"}).should have_json_keys(:a, :b)
+ end
+
+ it "matches for empty set of keys" do
+ %({"a": "1", "b": "2", "c": "3"}).should have_json_keys
+ end
+
+ it "accepts array of symbol keys" do
+ %({"a": "1", "b": "2"}).should have_json_keys([:a, :b])
+ end
+
+ it "accepts array of string keys" do
+ %({"a": "1", "b": "2"}).should have_json_keys(['a', 'b'])
+ end
+
+ it "accepts symbol keys" do
+ %({"a": "1", "b": "2"}).should have_json_keys(:a, :b)
+ end
+
+ it "accepts string keys" do
+ %({"a": "1", "b": "2"}).should have_json_keys('a', 'b')
+ end
+end
Something went wrong with that request. Please try again.