collectiveidea / json_spec

Easily handle JSON in RSpec and Cucumber
rubygems.org/gems/json_spec
MIT License
919 stars 114 forks source link

Include looking for {"key":"value} giving error #21

Closed Chuckv closed 12 years ago

Chuckv commented 12 years ago

Trying to use an 'should include' step pretty much straight out of the readme and it is giving an error

The readme lists this as an example

Then the JSON at "path" should include {"key":"value"}

the contents of last_json are:

{
    "oauthkey": "af93cd1184cdcb0942b8b5d35039eb",
    "account": {
      "resource_uri": "/api/v0001/accounts/b1943ca149fd46c1aea35e55b5ab36cb",
      "uuid": "b1943ca149fd46c1aea35e55b5ab36cb",
      "name": "qa2@adready.com"
    },
    "oauthsecret": "30b698ed4188b402c0f6940b76fac5"
}

my step reads like this

Then the JSON at "account" should include {"name":"qa2@adready.com"}  

And I'm getting the following error

 # json_spec-0.8.0/lib/json_spec/cucumber.rb:37
  Expected included JSON at path "account" (RSpec::Expectations::ExpectationNotMetError)
  features\OR\API\OR_API_Users.feature:19:in `Then the JSON at "account" should include {"name":"qa2@adready.com"}'
laserlemon commented 12 years ago

The inclusion matcher is meant to match array or hash values and not subsets of hashes. Please see issue #20.

Chuckv commented 12 years ago

I saw that response when it was made. However the above example I tried to use comes almost directly from the readme. It gives the following as the first two examples in the section where examples of using 'include' is listed

Then the JSON should include {"key":"value"} Then the JSON at "path" should include {"key":"value"}

There is also this example, also from the readme

Then the JSON should include: """ { "key": "value" } """

If this is Not how 'should include' is supposed to be used, then why oh why are these specific examples being given in the readme?

laserlemon commented 12 years ago

If the JSON were:

[
  {"key":     "value"},
  {"another": "value"}
]

or:

{
  "one": {"key":     "value"},
  "two": {"another": "value"}
}

then:

Then the JSON should include {"key":"value"}

would pass.

I hope that helps!

Chuckv commented 12 years ago

also is not this spec matching a HASH (not just a hash value) from inside a hash?

it "matches a hash included in a hash" do
  json = %({"one":{"two":3},"four":{"five":6}})
  json.should include_json(%({"two":3}))
  json.should include_json(%({"five":6}))
end

Is my problem that I used 'at path' in my then step? should it have worked if I removed that?

laserlemon commented 12 years ago

In your example, we're still talking about hash values. It just so happens that those hash values are hashes.

Chuckv commented 12 years ago

Isn't the json in the sample I gave, at the path account, basically the same as the first form you gave? or is it not the case because your first form is an array and mine is not?

also suggestion for the spec sample I gave above... change {"five": 6} to be {"five":"six"} for a more robust test (at least it seems to me like that would be good)

laserlemon commented 12 years ago

The inclusion matcher has no concept of hash subsets. In your original example, any of the following steps would pass:

Then the JSON at "account" should include "/api/v0001/accounts/b1943ca149fd46c1aea35e55b5ab36cb"
Then the JSON at "account" should include "b1943ca149fd46c1aea35e55b5ab36cb"
Then the JSON at "account" should include "qa2@adready.com"
Then the JSON at "account/name" should be "qa2@adready.com"
Then the JSON should include:
  """
  {
    "resource_uri": "/api/v0001/accounts/b1943ca149fd46c1aea35e55b5ab36cb",
    "uuid": "b1943ca149fd46c1aea35e55b5ab36cb",
    "name": "qa2@adready.com"
  }
  """
Then the JSON at "account" should be:
  """
  {
    "resource_uri": "/api/v0001/accounts/b1943ca149fd46c1aea35e55b5ab36cb",
    "uuid": "b1943ca149fd46c1aea35e55b5ab36cb",
    "name": "qa2@adready.com"
  }
  """

and I would recommend:

Then the JSON at "account/name" should be "qa2@adready.com"

Using the inclusion matcher requires that the JSON value you give exactly matches a value in the collection you specify.

I hope that makes sense.

Chuckv commented 12 years ago

Yes it helps immensely. I was pretty close to understanding after your prior comment, but this cemented it.

laserlemon commented 12 years ago

Great, I'm glad I could help!