A nice and simple approach to test you JSON APIs:
# spec/features/api/user_spec.rb
require 'rails_helper'
RSpec.feature 'User', type: :feature do
it 'lists users' do
user = create(:user, :as_admin)
visit api_user_path(user, format: :json)
expect(page).to match_yaml_fixture('api/user')
end
end
This checks if the page source matches the data given in the fixture file. To make it more readable we format the expected JSON as YAML:
# spec/fixtures/api/user.yaml
---
user:
- id: 1
first_name: Max
last_name: Power
role:
id: 1
name: Admin
Add match_yaml_fixture to RSpec
Drop this in your support directory:
require 'rspec/expectations'
module FixtureHelper
def read_fixture(*path_elements)
IO.read(Rails.root.join("spec", "fixtures", *path_elements))
end
end
RSpec::Matchers.define :match_yaml_fixture do |expected|
match do |actual|
expected = prepare_expected(expected)
actual = prepare_actual(actual)
actual.strip == read_fixture(expected).strip
end
failure_message do |actual|
expected = prepare_expected(expected)
actual = prepare_actual(actual)
"expected the following to match fixture file #{expected}:\n\n#{actual}"
end
private
def prepare_expected(expected)
expected += '.yaml' unless expected.end_with?('.yaml')
expected
end
def prepare_actual(actual)
actual = JSON.parse(actual.source) if actual.is_a?(Capybara::Session)
actual = actual.to_yaml if actual.is_a?(Hash)
actual.to_s
end
end
Then include the helper in your spec_helper.rb or rails_helper.rb file:
# spec/rails_helper.rb
require File.expand_path('../support/fixture_helper', __FILE__)
RSpec.configure do |config|
config.include FixtureHelper
end