Coder Social home page Coder Social logo

json_spec's Introduction

json_spec

Easily handle JSON in RSpec and Cucumber

Gem Version Build Status Code Climate Dependency Status

RSpec

json_spec defines five new RSpec matchers:

  • be_json_eql
  • include_json
  • have_json_path
  • have_json_type
  • have_json_size

The new matchers could be used in RSpec as follows:

describe User do
  let(:user){ User.create!(first_name: "Steve", last_name: "Richert") }

  context "#to_json" do
    it "includes names" do
      names = %({"first_name":"Steve","last_name":"Richert"})
      user.to_json.should be_json_eql(names).excluding("friends")
    end

    it "includes the ID" do
      user.to_json.should have_json_path("id")
      user.to_json.should have_json_type(Integer).at_path("id")
    end

    it "includes friends" do
      user.to_json.should have_json_size(0).at_path("friends")

      friend = User.create!(first_name: "Catie", last_name: "Richert")
      user.friends << friend

      user.to_json.should have_json_size(1).at_path("friends")
      user.to_json.should include_json(friend.to_json)
    end
  end
end

json_spec also provides some useful helpers for RSpec tests:

  • parse_json
  • normalize_json
  • generate_normalized_json
  • load_json

To start using them add an include them in your RSpec configuration:

RSpec.configure do |config|
  config.include JsonSpec::Helpers
end

You can find usage examples for the helpers in spec/json_spec/helpers_spec.rb

Exclusions

json_spec ignores certain hash keys by default when comparing JSON:

  • id
  • created_at
  • updated_at

It's oftentimes helpful when evaluating JSON representations of newly-created ActiveRecord records so that the new ID and timestamps don't have to be known. These exclusions are globally customizeable:

JsonSpec.configure do
  exclude_keys "created_at", "updated_at"
end

Now, the id key will be included in json_spec's comparisons. Keys can also be excluded/included per matcher by chaining the excluding or including methods (as shown above) which will add or subtract from the globally excluded keys, respectively.

Paths

Each of json_spec's matchers deal with JSON "paths." These are simple strings of "/" separated hash keys and array indexes. For instance, with the following JSON:

{
  "first_name": "Steve",
  "last_name": "Richert",
  "friends": [
    {
      "first_name": "Catie",
      "last_name": "Richert"
    }
  ]
}

We could access the first friend's first name with the path "friends/0/first_name".

Cucumber

json_spec provides Cucumber steps that utilize its RSpec matchers and that's where json_spec really shines. This is perfect for testing your app's JSON API.

In order to use the Cucumber steps, in your env.rb you must:

require "json_spec/cucumber"

You also need to define a last_json method. If you're using Capybara, it could be as simple as:

def last_json
  page.source
end

Now, you can use the json_spec steps in your features:

Feature: User API
  Background:
    Given the following users exist:
      | id | first_name | last_name |
      | 1  | Steve      | Richert   |
      | 2  | Catie      | Richert   |
    And "Steve Richert" is friends with "Catie Richert"

  Scenario: Index action
    When I visit "/users.json"
    Then the JSON response should have 2 users
    And the JSON response at "0/id" should be 1
    And the JSON response at "1/id" should be 2

  Scenario: Show action
    When I visit "/users/1.json"
    Then the JSON response at "first_name" should be "Steve"
    And the JSON response at "last_name" should be "Richert"
    And the JSON response should have "created_at"
    And the JSON response at "created_at" should be a string
    And the JSON response at "friends" should be:
      """
      [
        {
          "id": 2,
          "first_name": "Catie",
          "last_name": "Richert"
        }
      ]
      """

The background steps above aren't provided by json_spec and the "visit" steps are provided by Capybara. The remaining steps, json_spec provides. They're versatile and can be used in plenty of different formats:

Then the JSON should be:
  """
  {
    "key": "value"
  }
  """
Then the JSON at "path" should be:
  """
  [
    "entry",
    "entry"
  ]
  """

Then the JSON should be {"key":"value"}
Then the JSON at "path" should be {"key":"value"}
Then the JSON should be ["entry","entry"]
Then the JSON at "path" should be ["entry","entry"]
Then the JSON at "path" should be "string"
Then the JSON at "path" should be 10
Then the JSON at "path" should be 10.0
Then the JSON at "path" should be 1e+1
Then the JSON at "path" should be true
Then the JSON at "path" should be false
Then the JSON at "path" should be null

Then the JSON should include:
  """
  {
    "key": "value"
  }
  """
Then the JSON at "path" should include:
  """
  [
    "entry",
    "entry"
  ]
  """

Then the JSON should include {"key":"value"}
Then the JSON at "path" should include {"key":"value"}
Then the JSON should include ["entry","entry"]
Then the JSON at "path" should include ["entry","entry"]
Then the JSON should include "string"
Then the JSON at "path" should include "string"
Then the JSON should include 10
Then the JSON at "path" should include 10
Then the JSON should include 10.0
Then the JSON at "path" should include 10.0
Then the JSON should include 1e+1
Then the JSON at "path" should include 1e+1
Then the JSON should include true
Then the JSON at "path" should include true
Then the JSON should include false
Then the JSON at "path" should include false
Then the JSON should include null
Then the JSON at "path" should include null

Then the JSON should have "path"

Then the JSON should be a hash
Then the JSON at "path" should be an array
Then the JSON at "path" should be a float

Then the JSON should have 1 entry
Then the JSON at "path" should have 2 entries
Then the JSON should have 3 keys
Then the JSON should have 4 whatevers

All instances of "should" above could be followed by "not" and all instances of "JSON" could be downcased and/or followed by "response."

Table Format

Another step exists that uses Cucumber's table formatting and wraps two of the above steps:

Then the JSON should have the following:
  | path/0 | {"key":"value"}   |
  | path/1 | ["entry","entry"] |

Any number of rows can be given. The step above is equivalent to:

Then the JSON at "path/0" should be {"key":"value"}
And the JSON at "path/1" should be ["entry","entry"]

If only one column is given:

Then the JSON should have the following:
  | path/0 |
  | path/1 |

This is equivalent to:

Then the JSON should have "path/0"
And the JSON should have "path/1"

JSON Memory

There's one more Cucumber step that json_spec provides which hasn't been used above. It's used to memorize JSON for reuse in later steps. You can "keep" all or a portion of the JSON by giving a name by which to remember it.

Feature: User API
  Scenario: Index action includes full user JSON
    Given the following user exists:
      | id | first_name | last_name |
      | 1  | Steve      | Richert   |
    And I visit "/users/1.json"
    And I keep the JSON response as "USER_1"
    When I visit "/users.json"
    Then the JSON response should be:
      """
      [
        %{USER_1}
      ]
      """

You can memorize JSON at a path:

Given I keep the JSON response at "first_name" as "FIRST_NAME"

You can remember JSON at a path:

Then the JSON response at "0/first_name" should be:
  """
  %{FIRST_NAME}
  """

You can also remember JSON inline:

Then the JSON response at "0/first_name" should be %{FIRST_NAME}

More

Check out the specs and features to see all the various ways you can use json_spec.

Contributing

If you come across any issues, please tell us. Pull requests (with tests) are appreciated. No pull request is too small. Please help with:

  • Reporting bugs
  • Suggesting features
  • Writing or improving documentation
  • Fixing typos
  • Cleaning whitespace
  • Refactoring code
  • Adding tests
  • Closing issues

If you report a bug and don't include a fix, please include a failing test.

Copyright

Copyright © 2011 Steve Richert

See LICENSE for details.

json_spec's People

Contributors

alindeman avatar bleonard avatar bryckbost avatar cbusbey avatar clabrunda avatar col-lambda avatar danolson avatar jeroenvandijk avatar joshk avatar kiela avatar laserlemon avatar levinalex avatar michaelklishin avatar olleolleolle avatar shekibobo avatar skalee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json_spec's Issues

NameError: uninitialized constant RSpec::Matchers

I dont know why, but when I install the gem within :development, :test group
and run bundle install and then rake I get the following error.
(I does not happen when I put gem 'json_spec' in the top level / root)

Maybe someone has an idea how to put the gem into :development, :test group without having this rake issue.

Error:[rake --tasks] rake aborted!
NameError: uninitialized constant RSpec::Matchers
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:74:in `block in load_missing_constant'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:8:in `without_bootsnap_cache'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:74:in `rescue in load_missing_constant'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:56:in `load_missing_constant'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:4:in `<module:Id>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:3:in `<module:RSpec>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:2:in `<module:JSONAPI>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:1:in `<main>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec.rb:1:in `<main>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:95:in `rescue in block in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:72:in `block in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `each'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler.rb:114:in `require'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/config/application.rb:18:in `<top (required)>'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `require_relative'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:703:in `raw_load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:104:in `block in load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:103:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:82:in `block in run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `kernel_load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:463:in `exec'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:18:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:30:in `block in <top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:22:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
Caused by:
NameError: uninitialized constant RSpec::Matchers
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:58:in `block in load_missing_constant'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:16:in `allow_bootsnap_retry'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:57:in `load_missing_constant'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:4:in `<module:Id>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:3:in `<module:RSpec>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:2:in `<module:JSONAPI>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec/id.rb:1:in `<main>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/jsonapi-rspec-0.0.2/lib/jsonapi/rspec.rb:1:in `<main>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:95:in `rescue in block in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:72:in `block in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `each'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler.rb:114:in `require'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/config/application.rb:18:in `<top (required)>'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `require_relative'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:703:in `raw_load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:104:in `block in load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:103:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:82:in `block in run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `kernel_load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:463:in `exec'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:18:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:30:in `block in <top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:22:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
Caused by:
LoadError: cannot load such file -- jsonapi-rspec
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:81:in `block (2 levels) in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:76:in `each'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:76:in `block in require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `each'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/runtime.rb:65:in `require'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler.rb:114:in `require'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/config/application.rb:18:in `<top (required)>'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `require_relative'
/Users/janjezek/Coding/RubymineProjects/PiForCloudApi/Rakefile:4:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/rake_module.rb:29:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:703:in `raw_load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:104:in `block in load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:103:in `load_rakefile'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:82:in `block in run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/rake:23:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:74:in `kernel_load'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:463:in `exec'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/cli.rb:18:in `start'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:30:in `block in <top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/lib/bundler/friendly_errors.rb:124:in `with_friendly_errors'
/Users/janjezek/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.17.1/exe/bundle:22:in `<top (required)>'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/janjezek/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'

include_json can't test parsed array response

Correct me if I am wrong, but currently json_spec can't test the following scenario:

Given actual (json object) and expected(hash):

JSON.parse(actual)
[{"name" => "Mike"}, {"name" => "Abby"}]
expected
{"name" => "Abby"}

actual.should include(expected.to_json) => fail because the following is false:
[{"name" => "Mike"}, {"name" => "Abby"}].include?({"name" => "Abby"})

Maybe we should create include_partial_json ? If so, I will try to submit a patch.

MultiJson Load errors on be_json_eql matchers

in my tests:

this passes

it {should be_json_eql(@league.id).at_path('id')}

this throws MultiJson load error

it {should be_json_eql(@league.href).at_path('href')}

Failure/Error: it {should be_json_eql(@league.href).at_path('href')}
 MultiJson::LoadError:
   795: unexpected token at 'http://0.0.0.0/api/leagues/259?post=3000'

MissingPathError causing spec failures when no #at_path specified

Environment:

  • Rails 3.0.10
  • RSpec-Rails 2.8.1
  • json_spec 0.7.0

Given a controller spec with an example like so, where user and file exist via factories:

get :authorization_path,
  :user_email => user.email,
  :type       => file.type,
  :id         => file.id,
  :format     => :json

  response.body.should be_json_eql(true)

We began receiving MissingPathErrors for "2/discussions_post/id".

The only way to fix this, was to add an #at_path("") call to the end of every spec that didn't already specify an exact #at_path.

There is only one place this path is ever used, which is in an entirely different controller spec that contains an example like so:

get :some_posts, :format => :json

...

response.body.should be_json_eql(post.id).at_path("2/discussions_post/id")

Seems like some state is being kept around or being polluted unintentionally. This did not occur in RSpec 2.7.0 and only occurs with RSpec 2.8.x.

JSON should include_json does not work

With json_spec 1.1.5 and the following test:

  it "matches json content with path" do
    json = %({"item": {"id": "1"}})
    json.should include_json(%({"id": "1"})).at_path("item")
  end
Failures:

  1) JsonSpec::Matchers::IncludeJson matches json content
     Failure/Error: json.should include_json(%({"id": "1"})).at_path("item")
       Expected {"item": {"id":"1" }} to include {"id": "1"} at path "item"
     # ./spec/json_spec/matchers/include_json_spec.rb:44:in `block (2 levels) in <top (required)>'

Finished in 0.07838 seconds (files took 0.16929 seconds to load)
116 examples, 1 failure

Failed examples:

rspec ./spec/json_spec/matchers/include_json_spec.rb:42 # JsonSpec::Matchers::IncludeJson matches json content

undefined method parse_json

When I try to use the be_json_eql matcher, I get the following error:
Failure/Error: api_response.should be_json_eql(replay)
NoMethodError:
undefined method `parse_json' for #RSpec::Matchers::Matcher:0x7fe6041f2600

I have the latest version from github. If I change
lines 5,6 for matchers.rb to use extend instead of include, everything seems to wokring fine.

I am using rspec v 2.5

In Ruby < 1.9.2 the % operator doesn't take %{} format strings

I added this to my helper file to work around it.

if RUBY_VERSION < '1.9.2'
  class String
    old_format = instance_method(:%)

    define_method(:%) do |arg|
      if arg.is_a?(Hash)
        self.gsub(/%\{(.*?)\}/) { arg[$1.to_sym] }
      else
        old_format.bind(self).call(arg)
      end
    end
  end
end

inline vs row for have_json_type

I have some static keys with dynamic values:

    And the JSON at "data/pgdb_ms" should be a fixnum # json_spec-1.0.3/lib/json_spec/cucumber.rb:81
    And the JSON should have the following:           # json_spec-1.0.3/lib/json_spec/cucumber.rb:61
      | data/pgdb_ms | a fixnum                  |
      756: unexpected token at 'a fixnum' (MultiJson::DecodeError)

I should probably submit a patch… thought I should mention it first and see if I'm not reading the manual correctly.

JsonSpec.remember does not properly verify input

The code in JsonSpec.remember assumes that the incoming argument will be a string and uses the % operator to interpolate from the memory hash into the string. However, it is perfectly possible to pass in a Numeric type (e.g. Fixnum) for which the % operator means something totally different which causes the code to try to convert the hash to fixnum, which it can't. This is especially problematic from the cucumber matchers, where your input is always run through remember.

I ran into the problem when trying to do a cucumber step like "And the JSON at "count" should be 10" but I am completely unable to reproduce it in this repo's cucumber tests (the 10 always comes in as a string some way I don't understand).

It appears possible to fix this either by doing .to_s on the income argument or changing the exclusion criteria to also include .is_a?(Numeric) (i.e. in addition to checking if the memory hash is empty). I think the is numeric check is more precise, so I'll submit a pull request with that change, but both solve my particular problem.

ArgumentError: bad value for range

I'm trying to use the have_json_size matcher but no luck. When I used as shown below, I get an error like ArgumentError: bad value for range.

    context "listing cases" do
      specify do
        get "#{API_BASE_PATH}/cases/"
        expect(last_response).to be_ok
        expect { JSON.parse(last_response.body) }.not_to raise_exception
        expect (last_response.body).to    have_json_size(1)
      end
    end

Attending to the examples it seems this syntax is ok.
Any clue if I'm doing something wrong?
Thanks a lot in advance.

installs files into my project, not as library

Very useful addition to the rspec tool suite, thanks!

I'm still learning the subtleties of bundler, but when I added:

gem 'json_spec'

to my Gemfile and run bundle, it created a new subdir in my project: json_spec/ruby/1.9.1/ with bin, cache, gems, bundler, doc and specifications subdirs

Usually this is all quietly installed in the library somewhere.

Is this a config issue for json_spec or user error on my part?

thx! michael

Adding loose comparison -- code, and pull request if interested.

I wanted a loose comparison type of thing so I threw one together. I'm wondering if this is a feature worth implementing, and if so, I'll submit a pull request with proper specs and an adjusted matcher name -- if not someone else might find this useful.

gist: https://gist.github.com/jejacks0n/6384919

This allows specifying attributes that you want to ensure are there, but that you don't really care about the value of by using a wildcard (*).

eg.

expect(response_body).to look_like <<-JSON
  {
    "access_token": "*",
    "token_type": "bearer",
  }
JSON

Thoughts / feelings? If it's something worth adding, what would you like me to change?

be_json_eql with nested hashes succeeds when it should not

In order to get better error messages and possibly improve my test cases I incorporated this gem into a complex test where we compare JSON returned from an API.

I am finding that tests with JSON containing nested hashes pass even when values in the internal hash are not the same. Here is a snippet of code I added to the be_json_eql_spec.rb file that demonstrates the problem. The first test passes, the second fails because the test is seeing a match where there is not one.

Am I missing something?

Thanks,
Greg

  context "multi-level JSON" do
    let(:source_hash) do
      {
        data: { id: 401101 }
      }
    end

    it "matches multi-level JSON" do
      target_hash = JSON.parse(source_hash.to_json)
      expect(target_hash.to_json).to be_json_eql(source_hash.to_json)
    end

    it "does not match different multi-level JSON" do
      target_hash = JSON.parse(source_hash.to_json)
      target_hash['data']['id'] = 'not-the-same'
      expect(target_hash.to_json).not_to be_json_eql(source_hash.to_json)
    end
  end

The results look like this:

rspec
...................................................F.................................................................

Failures:

  1) JsonSpec::Matchers::BeJsonEql multi-level JSON does not match different multi-level JSON
     Failure/Error: expect(target_hash.to_json).not_to be_json_eql(source_hash.to_json)
     
       Expected inequivalent JSON
       Diff:
       
     # ./spec/json_spec/matchers/be_json_eql_spec.rb:28:in `block (3 levels) in <top (required)>'

Finished in 0.04953 seconds (files took 0.10741 seconds to load)
117 examples, 1 failure

Failed examples:

rspec ./spec/json_spec/matchers/be_json_eql_spec.rb:25 # JsonSpec::Matchers::BeJsonEql multi-level JSON does not match different multi-level JSON

"Expected Included JSON" RSpec Exception doesn't have any more info

$ step 'the JSON response should include:', JSON.pretty_generate(data)
*** RSpec::Expectations::ExpectationNotMetError Exception: Expected included JSON

Whereas:

$ step 'the JSON response should be:', JSON.pretty_generate(data)
*** RSpec::Expectations::ExpectationNotMetError Exception: Expected equivalent JSON
Diff:
@@ -2,19 +2,7 @@
(diff)

Ruby 2 / Rails 4 / JSON Spec 1.1.1

Add Support for Posting JSON Bodies

Description says it all! I'm loving this library, and it would be great to be able to submit JSON payloads. In the app I'm working on, we often submit large forms as payloads, submitting only authentication details as normal parameters.

Something like:

Then I post to "/someurl" with params:
"""
apikey
"""
and data:
"""
formdata
"""

Suppress legacy warnings when using rspec 3

Hi There,

obviously json_spec isn't fully compatible with rspec 3 at the moment. So using it is really painfull because there are a lot of legacy warnings like this one:

JsonSpec::Matchers::HaveJsonSize implements a legacy RSpec matcher
protocol. For the current protocol you should expose the failure messages
via the `failure_message` and `failure_message_when_negated` methods.

Is there any chance to suppress these while waiting for a fully compatible version of json_spec?

be_valid_json matcher?

Would a matcher simply to check if a response is valid JSON make sense to include in the gem? I don't believe it would be more complicated than asserting that parse_json does not throw an error, which is what I'm doing in my project, but the syntactical sugar would be nice to have IMO.

Or is this somehow covered by one of the other matchers?

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

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": "[email protected]"
    },
    "oauthsecret": "30b698ed4188b402c0f6940b76fac5"
}

my step reads like this

Then the JSON at "account" should include {"name":"[email protected]"}  

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":"[email protected]"}'

Can't call it without description

Doing it { should matcher } with a json_spec matcher results in rspec 2.6.0 failing to test the spec with a message of RSpec expects the matcher to have a #description method.

JSON Path integration

I'd really like the see a JSON Path integration. https://github.com/joshbuddy/jsonpath It seems awkward to me that a user would have to explicitly set their path to find data in the JSON string. Specifically, I'd like the run a test that that looks like something like this in cucumber

  Scenario: List events in JSON
    Given I oauth as the user "[email protected]" with the password "password"
    When I GET to "v1/foos"
    Then the response status should be "200"
    And the JSON at "$..bar_type" should include ["baz", "biz"]

While I could explicitly write the code to test this for every property, it get's a little tedious after writing out every property and JSONPath provides a pretty slick powerful way to navigate the JSON to retrieve the data.

Version 1.1.0 not appears on RubyGems

$ bundle update json_spec  
Fetching gem metadata from http://rubygems.org/.........
Fetching gem metadata from http://rubygems.org/..
Could not find gem 'json_spec (~> 1.1) ruby' in the gems available on this machine.

RubyGems suggestion:

gem "json_spec", "~> 1.0.3"

A temporary workaround:

gem 'json_spec', git: 'https://github.com/collectiveidea/json_spec', tag: 'v1.1.0'

Can't use path accessor methods to access string representation of integer keys

If you got a JSON object with string representation of integers (e.g. {"1":"foo","2":"bar"}, you can't use json_spec path accessor methods, since it will try to convert such keys to integer during path access even if the object being accessed is not an array.

Note JSON does not allow you to define integer keys in an object.

The problem lies in the path is parsed all at once at the start of path walking, which means the code does not have a change to determine whether the key is being used to access a hash or an array, and to only perform the int conversion when it is an array.

JSON null value is counted as 1 entry

An entry can be null such as [null], which is 1 entry. If a null is a value of an Array, then the array has 0 entry. However a null value returns a size of 1

def matches?(json)
ruby = parse_json(json, @path)
#when ruby = nil
#NoMethodError: undefined method `size' for nil:NilClass
# so @Actual = 1 when ruby is nil
# seems false return 0 rather then 1?
@Actual = Enumerable === ruby ? ruby.size : 1
@Actual == @expected
end

I created a fork and then did a pull request
#80

be_json_eql(:null) is not intuitive

It seems very counter intuitive to me that to check if the json is null I need to pass the string null and can't pass the nil object. I'm pretty sure I was able to do this in previous versions. I'd love to see either an example in the readme if that is the desired behavior.

Rspec4?

Any chance someone has had some luck running this with rspec >= 4.0?

gem.add_dependency "rspec", ">= 2.0", "< 4.0"

at "path" should include: step not acting as I would expect

(apologies in advance for the steps, they need to be cleaned up a fair bit)

My scenario looks like this

Scenario Outline:  GET to OR Packages for specific package uuid returns proper data
  Given I create a request body from the following JSON data
  """
  {
    "package":
    {
      "name": "anothertestpackage", 
      "description": "This is a test, testing 4 5 6", 
      "package_type" : <package_type>, 
      "duration": 30, 
      "start_date": "2012-03-01T08:00:00Z"
    }
  }
  """
  And I have the URI for a new: package made in: OR from the request body
  When I make a: GET request to the URI for: my new package with no query string
 Then the JSON at "package" should include:
  """
  {
    "name": "anothertestpackage", 
    "description": "This is a test, testing 4 5 6", 
    "package_type" : <package_type>, 
    "duration": 30, 
    "start_date": "2012-03-01T08:00:00Z"
  }
  """

  Examples:
    | package_type |
    | "IMPRESSIONS" |
    | "CLICKS" |
    | "LEADS" |

And the contents of last_json are like this at the point the Then step is executed

{
  "package": {
    "status": "NEW",
    "account": {
      "resource_uri": "/api/v0001/accounts/fecdbb85a3584ca59820a321c3c2767d"
    },
    "name": "anothertestpackage",
    "package_type": "IMPRESSIONS",
    "margin_goal": "0.5000",
    "duration": 30,
    "resource_uri": "/api/v0001/packages/fecdbb85a3584ca59820a321c3c2767d/feea333776c9454c92edab8e73628cbd",
    "start_date": "2012-03-01T08:00:00Z",
    "description": "This is a test, testing 4 5 6"
  }
}

I should think the step would pass, but I'm getting this error instead

  Expected included JSON at path "package" (RSpec::Expectations::ExpectationNotMetError)
  features\OR\API\OR_API_Packages.feature:70:in `Then the JSON at "package" should include:'

Is this user error? should I be using a different means to determine if the expected key:value pairs are present in the JSON returned by the API? I don't really see any examples of doing this kind of comparison in your feature files for the gem, so it is difficult to know if this is not what include was intended for.

include_json doesn't work for simple caser

using it with RSpec expect({:make => "Acura"}.to_json).to include_json({:make => "Acura"}.to_json)

I get error:
C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/rspec-support-3.3.0/lib/rspec/support.rb:
86:in `block in module:Support': Expected {"make":"Acura"} to include {"make":
"Acura"} (RSpec::Expectations::ExpectationNotMetError)

am I doing something wrong?

Path doesn't seem to be reset

After calling at_path in one spec it is still set to a particular value when running another spec.
This breaks the other Test of course.

It started after updating rspec-rails to 2.8.1.
2.7.0 works fine. Not sure if it is an rspec-rails or json_spec issue though.

rspec-rails 2.8.1
json_spec 0.7.0
ruby 1.9.2

I went back to 2.7.0 for now, but hopefully this can be resolved.

thx

Request: "in yaml" option, so you can write features in YAML but compare it to JSON

JSON is for computers; YAML is for people; so are features!

I rigged this:

Then /^the JSON response should be \(in yaml\):$/  do |yaml|
  step 'the JSON response should be:', YAML.parse(yaml).to_json
end

so I could:

Then the JSON response should be (in yaml):
"""
  chunky:
  - bacon
"""

but just for that one step. It'd be nice if I could do that to any of them, without having to write a translation step, and as part of json_spec itself. (I am testing a JSON api, but I still don't want to write JSON if I can help it)

LoadError: cannot load such file -- [{ 'key':'value' }]

I'm trying to use json_spec with cucumber, but using the step:

  Then the JSON should be:
  """
  {
    'key':'value'
  }
  """

The error is in the helpers.rb file, in the method:

  def multi_json_load(json)
    MultiJson.respond_to?(:load) ? MultiJson.load(json) : MultiJson.decode(json)
  end

Using just MultiJson.decode(json) works fine.

Sorry for my bad english x;

"the JSON should be ..." failing in JRuby

I'm using JRuby 1.6.5 with Rails 3.1.3 and Cucumber 1.1.4.

When I try to use the step 'the JSON should be ...' I get this error

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.length (NoMethodError)
/home/declan/.rvm/gems/jruby-1.6.5@neo/gems/cucumber-1.1.4/bin/../lib/cucumber/step_match.rb:73:in `replace_arguments'
...

Current workaround is to use 'the JSON at "" should be ...' instead, i.e. use the JSON at PATH step, and just give it the root path.

Is this project still maintained?

Hello everyone!

Awesome project but is it still maintained? I plan to add it to a couple projects but the github shows low or no movement for a long time now.

include_json does not working

Hi,

Thanks for awesome gem.

I am testing with RSpec with json_spec 0.7.0.

    it 'should create new temp image' do
      post :create, :temp_image => {:file => fixture_file_upload(File.join(Rails.root, 'spec', 'fixtures', 'test_image.jpg'), 'image/jpeg')}, :format => 'json'
      puts response.body
      response.body.should include_json(%({"status":"success"}))
    end

Output is

{"temp_image":{"current_filter":"original","url":"http://picyou.dev/storage/test/filtered/7/original_original_preview.jpg?1314790553","id":7},"status":"success"}

But test fails for some reason with message: Expected included JSON.

Any help would be appreciated.

Thanks,
Andrey.

Support some sort of Regex matcher

I would like to have some sort of matcher like

response_body.should have_json_path('users/href').that_matches(/^http:\/\//)

thoughts on doing a PR to add support for this?

Quotes within JSON body should not be memorised with escaped double quotes

When I get "/files.json"
# my last_json returns something like:
# "{\"files\":[{\"uuid\":\"7cd19c4d-83c2-4acb-9ed8-44800eee6442\"},{\"uuid\":\"05a8bee9-c7b0-43d8-9aa2-743f5786deb8\"]}"

And I keep the JSON response at "files/0/uuid" as "FILE_UUID"
# this is was memorized as: {:IMAGE_UUID=>"\"7cd19c4d-83c2-4acb-9ed8-44800eee6442\""}
# would expect just "7cd19c4d-83c2-4acb-9ed8-44800eee6442", which is without the escaped strings

When I get "/files/%{FILE_UUID}.json"
# because the above actual memorisation results in a get to url "/files/\"7cd19c4d-83c2-4acb-9ed8-44800eee6442\".json", which is not right

undefined method `exclude_keys'

I'm using json_spec with cucumber. I added

    require "json_spec/cucumber"

to env.rb. And when I run cucumber features I get such error:

undefined method `exclude_keys' for #<RSpec::Matchers::Matcher:0x00000005d53a18> (NoMethodError)
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/matchers/method_missing.rb:9:in `method_missing'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/matchers/matcher.rb:114:in `method_missing'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/json_spec-0.7.0/lib/json_spec/matchers.rb:40:in `scrub'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/json_spec-0.7.0/lib/json_spec/matchers.rb:11:in `block (2 levels) in <top (required)>'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/matchers/matcher.rb:39:in `instance_exec'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/matchers/matcher.rb:39:in `matches?'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/expectations/handler.rb:11:in `handle_matcher'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/rspec-expectations-2.5.0/lib/rspec/expectations/extensions/kernel.rb:27:in `should'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/json_spec-0.7.0/lib/json_spec/cucumber.rb:17:in `block in <top (required)>'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/core_ext/instance_exec.rb:48:in `instance_exec'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/core_ext/instance_exec.rb:48:in `block in cucumber_instance_exec'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/core_ext/instance_exec.rb:69:in `cucumber_run_with_backtrace_filtering'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/core_ext/instance_exec.rb:36:in `cucumber_instance_exec'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/rb_support/rb_step_definition.rb:62:in `invoke'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/step_match.rb:26:in `invoke'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/step_invocation.rb:63:in `invoke'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/step_invocation.rb:42:in `accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:99:in `block in visit_step'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:164:in `broadcast'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:98:in `visit_step'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/step_collection.rb:15:in `block in accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/step_collection.rb:14:in `each'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/step_collection.rb:14:in `accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:93:in `block in visit_steps'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:164:in `broadcast'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:92:in `visit_steps'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/scenario.rb:53:in `block (2 levels) in accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:79:in `block (2 levels) in with_hooks'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:95:in `before_and_after'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:78:in `block in with_hooks'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime/support_code.rb:115:in `call'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime/support_code.rb:115:in `block (3 levels) in around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/language_support/language_methods.rb:13:in `block in around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/language_support/language_methods.rb:95:in `call'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/language_support/language_methods.rb:95:in `execute_around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/language_support/language_methods.rb:12:in `around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime/support_code.rb:114:in `block (2 levels) in around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime/support_code.rb:112:in `call'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime/support_code.rb:112:in `around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:90:in `around'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:77:in `with_hooks'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/scenario.rb:51:in `block in accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/scenario.rb:106:in `with_visitor'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/scenario.rb:45:in `accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:51:in `block in visit_feature_element'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:164:in `broadcast'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:50:in `visit_feature_element'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/feature.rb:40:in `block in accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/feature.rb:39:in `each'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/feature.rb:39:in `accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:20:in `block in visit_feature'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:164:in `broadcast'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:19:in `visit_feature'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/features.rb:29:in `block in accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/features.rb:17:in `each'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/features.rb:17:in `each'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/features.rb:28:in `accept'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:14:in `block in visit_features'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:164:in `broadcast'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/ast/tree_walker.rb:13:in `visit_features'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/runtime.rb:45:in `run!'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/cli/main.rb:43:in `execute!'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/lib/cucumber/cli/main.rb:20:in `execute'
/home/user/.rvm/gems/ruby-1.9.2-p290/gems/cucumber-0.10.2/bin/cucumber:14:in `<top (required)>'
/home/user/.rvm/gems/ruby-1.9.2-p290/bin/cucumber:19:in `load'
/home/user/.rvm/gems/ruby-1.9.2-p290/bin/cucumber:19:in `<main>'
features/manage_api.feature:15:in `Then the JSON response at "user" should be:'

I'm iusing Ruby 1.9.2 and Rails 3. Same error on Ruby 1.8.7

Second level of nesting issue

I have this kind of structure:

"attribute" : {
  "data": {
    "object": {
      "data": "bacon"
    }
}

and my the JSON should be step is failing with this kind of error:

"attribute" : {
  "data": "{:object=>\"bacon\"}"
}

Ruby2 / Rails 4 / json_spec 1.1.1

Impossible to test have_json_type with boolean type

the have_json_type matcher relies on the ruby type system to mach types. However it's not possible to match booleans, as there isn't a Boolean type.

I think a good extension might provide a :boolean shorcut:

json.should have_json_type(:boolean).at_path("your_path")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.