Last active
August 29, 2015 14:02
-
-
Save morhekil/dafdbba006b4bcf6e485 to your computer and use it in GitHub Desktop.
Shared examples spec'ing JSON API of a RESTful model backed by Ohm (Redis), for RSpec 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Shared examples take a model class as parameters, and expect: | |
# 1. ``create_attrs`` and ``update_attrs`` to be available in the context. | |
# 2. ``user`` method to be available in the context, representing currently logged in user. | |
# 3. Factory to be defined for the model, and ``build`` method to be included into examples. | |
# | |
# EXAMPLE | |
# ------- | |
# | |
# 1. factories.rb: | |
# FactoryGirl.define do | |
# factory :jaeger do | |
# id { SecureRandom::uuid } | |
# name { Faker::Name.name } | |
# year { Faker::Number.number(4) } | |
# end | |
# end | |
# | |
# 2. jaeger_spec.rb: | |
# | |
# # ... bootstrapping, API setup etc | |
# context 'Jaeger API' do | |
# let(:create_attrs) { { name: 'Striker Eureka', year: '2019' } } | |
# let(:update_attrs) { { name: 'Chrome Brutus', year: '2017' } } | |
# | |
# it_behaves_like 'a RESTful Ohm resource', Jaeger | |
# end | |
# | |
# This spec also assumes that all requests and responses are JSON data, with model name as the root key, e.g.: | |
# { jaeger: { name: 'Striker Eureka' } } | |
# | |
RSpec.shared_examples "a RESTful Ohm resource" do |model| | |
let(:path) { '/' + model.to_s.underscore.pluralize } | |
let(:class_str) { model.to_s.underscore } | |
let(:class_sym) { class_str.to_sym } | |
describe 'POST' do | |
subject(:create_resource) { post path, class_sym => create_attrs } | |
it 'creates new resource' do | |
expect { create_resource }.to change { model.all.size }.by(1) | |
end | |
describe 'created resource' do | |
let!(:new_resource) do | |
old_ids = model.all.ids | |
create_resource | |
id = (model.all.ids - old_ids).last | |
expect(id).to_not be_nil | |
model[id] | |
end | |
it 'returned in the response' do | |
expect(last_response.status).to eq 201 | |
expect( | |
JSON.parse(last_response.body)[class_str] | |
).to represent_entity_of(new_resource) | |
end | |
it 'is assigned to the current user' do | |
expect(new_resource.user).to eq user | |
end | |
it 'is given a UUID' do | |
expect(new_resource.id).to_not be_nil | |
end | |
end | |
end | |
describe "#{model.to_s.underscore.pluralize}/:id" do | |
let(:resource) { build(class_sym, user: user).tap(&:save) } | |
describe 'GET' do | |
before { get "#{path}/#{resource.id}" } | |
it 'returns resource data' do | |
expect(last_response.status).to eq 200 | |
expect( | |
JSON.parse(last_response.body)[class_str] | |
).to represent_entity_of(resource) | |
end | |
end | |
describe 'PUT' do | |
before { put "#{path}/#{resource.id}", class_sym => update_attrs } | |
it 'updates resource' do | |
expect(resource.load!.attributes).to include update_attrs | |
end | |
it 'returns updated resource data' do | |
expect(last_response.status).to eq 200 | |
expect( | |
JSON.parse(last_response.body)[class_str] | |
).to represent_entity_of(resource.load!) | |
end | |
end | |
describe 'DELETE' do | |
before { delete "#{path}/#{resource.id}" } | |
it 'deletes resource' do | |
expect(model[resource.id]).to be_nil | |
end | |
it 'returns deleted resource data' do | |
expect(last_response.status).to eq 200 | |
expect( | |
JSON.parse(last_response.body)[class_str] | |
).to represent_entity_of(resource) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment