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