Skip to content

Ross-Hunter/jsonapi_expectations

Repository files navigation

Jsonapi Expectations

CircleCI

Semantic expectation helpers for JSON API testing using Airborne and RSpec. It makes writing request specs fun, easy, and legible. It essentially just digs into the jsonapi response for you, so you don't need to worry so much about data, attributes, relationships, or includes

Usage

The gem includes the following matchers, which all aim to be self-explanatory

expect_attributes title: 'JSON API paints my bikeshed!',
                  can_find: 'attributes',     # keys are translated to
                  anywhere_under: 'data key', # underscored symbols
                  works_on_array_response: 'or just a single object' 

expect_attributes_absent cost: 'allows testing field-level permissions'

expect_relationship key: 'group',  # the name of the key under `relationships`
                    type: 'sites', # (optional) defaults to plural of key
                    id: site.id,   # find by id and/or link (at least one)
                    link: "http://www.example.com/sites/#{site.id}" 
                    included: true # look for item in `included`

expect_record model, type: 'people' # can set jsonapi type

expect_record_absent hidden_model # infer type from model class

expect_records_sorted_by :ranking, direction: :desc # defaut is :asc

find_record model # grab the record for more in-depth testing of the response

expect_item_count 4 # the number of items underneath the `data` key

Using these matchers (along with these request spec helpers) a spec might look something like this

describe 'widgets' do
  let(:org) { FactoryGirl.create :organization }
  let(:widgets) { FactoryGirl.create_list :widget, 4, organization: org }
  let(:widget) { widgets.first }
  let(:widget_attributes) { { name: 'foo' } }
  let(:widget_relations) { { organization: { data: { id: org.id } } }

  example 'creating a widget' do
    authed_post widgets_path, params: { data: { attributes: widget_attributes,
                                                relationships: widget_relations } }
    expect_status :created
    expect_attributes name: widget_attributes[:name]
    expect_relationship key: 'organization',
                        link: organization_path(org.id)
  end

  example 'getting widgets with included organization' do
    widgets
    authed_get widgets_path, params: { include: 'organization' }

    expect_status :ok
    expect_record widget
    expect_record organization, included: true
    expect_records_sorted_by :price

    found_widget = find_record widget
    found_org = find_record org, included: true
    expect(found_widget.organization).to eq(found_org)
  end
end

Installation

Add this line to your application's Gemfile in your test group:

gem 'jsonapi_expectations'

And include it in spec_helper.rb

RSpec.configure do |config|
  # ...
  config.include JsonapiExpectations, type: :request
  # ...
end

Alternatives

Check out jsonapi-rspec. It looks to be the same idea, but it uses actual rspec matchers so expectations look like this:

expect(document['data']).to have_attribute(:name).with_value('Lucas')

jsonapi_expectations is a little more "magical" and the same expectation is written like this:

expect_attributes name: 'Lucas'

Choose which one works best for you!

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Ross-Hunter/jsonapi_expectations. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

This Gem has been lovingly hand-crafted by Ross-Hunter, and built on top of the super-sweet Airborne Gem.

License

The gem is available as open source under the terms of the MIT License.