How to DRY api specs with rspec shared contexts and metadata
Shared context/shared examples and metadata are great features of RSpec which can be used to DRY your specs.
Today, I’d like to share some basic usages of them to DRY api specific specs.
DRY API GET REQUESTS
Before:
describe "GET /articles" do
it "returns status code 200" do
get articles_path
expect(response).to have_http_status(200)
end
end
describe "GET /posts" do
it "returns status code 200" do
get posts_path
expect(response).to have_http_status(200)
end
end
After:
RSpec.shared_context 'api get request', :get do
it "returns status code 200" do
get url
expect(response).to have_http_status(200)
end
end
describe "GET /articles", :get do
let(:url) { '/articles' }
end
describe "GET /posts", :get do
let(:url) { '/posts' }
end
DRY API POST REQUESTS
Before:
describe "POST /articles" do
context 'with valid params' do
let(:valid_params) { { content: 'text' } }
it 'returns status code 201' do
post '/articles', valid_params
expect(response).to have_http_status(201)
end
end
context 'with invalid params' do
let(:invalid_params) { { content: '' } }
it 'returns status code 422' do
post '/articles', invalid_params
expect(response).to have_http_status(422)
end
end
end
describe "POST /posts" do
context 'with valid params' do
let(:valid_params) { { content: 'text' } }
it 'returns status code 201' do
post '/posts', valid_params
expect(response).to have_http_status(201)
end
end
context 'with invalid params' do
let(:invalid_params) { { content: '' } }
it 'returns status code 422' do
post '/posts', invalid_params
expect(response).to have_http_status(422)
end
end
end
After:
RSpec.shared_context 'api post request', :post do
context 'with valid params' do
it 'returns status code 201' do
post url, valid_params
expect(response).to have_http_status(201)
end
end
context 'with invalid params' do
it 'returns status code 422' do
post url, invalid_params
expect(response).to have_http_status(422)
end
end
end
describe "POST /posts", :post do
let(:url) { '/posts' }
let(:valid_params) { { text: 'text' } }
let(:invalid_params) { { text: '' } }
end
describe "POST /articles", :post do
let(:url) { '/articles' }
let(:valid_params) { { text: 'text' } }
let(:invalid_params) { { text: '' } }
end
DRY API AUTHENTICATED REQUESTS
Before:
describe "DELETE /articles/:id" do
let(:article) { Article.create(content: 'text') }
let(:user) { create(:user) }
context 'when not authenticated' do
it 'returns http status code 401' do
delete "/articles/#{article.id}"
expect(response).to have_http_status(401)
end
end
context 'when authenticated' do
before :each do
login_as(user)
end
it 'returns http status code 200' do
delete "/articles/#{article.id}"
expect(response).to have_http_status(200)
end
it 'deletes the article' do
pending
end
end
end
describe "PUT /posts/:id/archive" do
let(:post) { Post.create(content: 'text') }
let(:user) { create(:user) }
context 'when not authenticated' do
it 'returns http status code 401' do
put "/posts/#{post.id}/archive"
expect(response).to have_http_status(401)
end
end
context 'when authenticated' do
before :each do
login_as(user)
end
it 'returns http status code 200' do
put "/posts/#{post.id}/archive"
expect(response).to have_http_status(200)
end
it 'archives the post' do
pending
end
end
end
After:
RSpec.shared_context "authenticated api request", :auth do
let(:user) { create(:user) }
before :each do
login_as(user)
end
after :each do
Warden.test_reset!
end
context 'when not authenticated' do
before :each do
logout
send(method, url)
end
it 'returns http status code 401' do
expect(response).to have_http_status(401)
end
end
it 'returns http status code 200' do
send(method, url)
expect(response).to have_http_status(200)
end
end
describe "DELETE /articles/:id", :auth do
let(:article) { Article.create(content: 'text') }
let(:method) { :delete }
let(:url) { "/articles/#{article.id}" }
it 'deletes the article' do
pending
end
end
describe "PUT /posts/:id/archive", :auth do
let(:post) { Post.create(content: 'text') }
let(:method) { :put }
let(:url) { "/posts/#{post.id}/archive" }
it 'archives the post' do
pending
end
end