Rails developers may quite familiar with Devise and RSpec. In a recent application, I need to custom Devise controllers. And of course, I need to write RSpec these. In this blog post, I will tell about RSpec custom Devise Request.
First, because I wanna create custom Devise, I need to set custom routes, like this:
devise_for :users, :controllers => { :registrations => "users/registrations", :sessions => "users/sessions"}
And this is my custom devise for being able to response with Json request:
# users/sessions_controller.rb
# ofcourse, require no authentication for this
def create
build_resource
resource = User.find_for_database_authentication(:email=>params[:user][:email])
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user][:password])
sign_in("user", resource)
render :json=> {:success=>true, :user => resource}
return
end
invalid_login_attempt
end
Ok, I have an api for custom login via: POST: 'users/sign_in'
And this is my RSpec:
# spec/request/sessions_requests_spec.rb
require "rails_helper"
RSpec.describe "Post #create", type: :request do
before(:all) do
User.create(
email: "test@example.com",
password: 'password',
password_confirmation: 'password',
)
end
it "responds successfully with an HTTP 201 status code" do
user_params = {user: { email: "test@example.com", password: "password"}}.to_json
post "users/sign_in", user_params, request_headers
expect(response).to be_success
expect(response).to have_http_status(200)
expect(json).to be_has_key("user")
expect(json["user"]).to be_has_key("authentication_token")
end
it "responds unsuccessfully with an HTTP 401 status code" do
user_params = {user: { email: "test@example.com", password: "wrong password"}}.to_json
post "users/sign_in", user_params, request_headers
expect(response).not_to be_success
expect(response).to have_http_status(401)
expect(json["message"]).to eql("Error with your login or password")
end
end
In this RSpec, I used two helpers variables, json
and request_headers
.
I created them in a support modules for DRY spec.
# spec/supports/request_helpers.rb
module Requests
module JsonHelpers
def json
@json ||= JSON.parse(response.body)
end
def request_headers
{
"Accept" => "application/json",
"Content-Type" => "application/json"
}
end
end
end
And add these helpers in configure file:
# spec/spec_helper.rb
require 'supports/request_helpers'
...
config.include Requests::JsonHelpers, type: :request