I am trying to build a rails login process with devise that will allow the user to signin/signout through a mobile application.
I created a SessionsController like that :
class SessionsController < Devise::SessionsController
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_to do |format|
format.html { super }
format.json {
render :status => 200, :json => { :error => "Success", :user => resource}.to_json
}
end
end
def destroy
super
end
end
My routes :
devise_for :users, :controllers => {:sessions => "sessions"}
resources :users
Then I have the following spec to test the process :
require 'spec_helper'
describe SessionsController do
describe "POST 'signin'" do
before (:each) do
@user = Factory(:user)
end
it "should login with json request" do
@expected = @user.to_json
post :create, :user => {:email => '[email protected]', :password => 'please'}, :content_type => 'application/json', :format => :json
response.body.should == @expected
end
end
end
And I get the following error :
Failure/Error: post :create, :user => {:email => '[email protected]', :password => 'please'}, :content_type => 'application/json', :format => :json
AbstractController::ActionNotFound:
Could not find devise mapping for path "/users/sign_in.json?content_type=application%2Fjson&user%5Bemail%5D=user%40test.com&user%5Bpassword%5D=please".
Maybe you forgot to wrap your route inside the scope block?
[EDIT] It seems like the functionality is ok but only the test is broken ; because if I run this small script :
require 'rest_client'
require "active_support/core_ext"
RestClient.post "http://localhost:3000/users/sign_in", {:user => {:email => '[email protected]', :password => 'please'}}.to_json, :content_type => :json, :accept => :json
I get the following result :
"{\"error\":\"Success\",\"user\":{\"email\":\"[email protected]\",\"name\":\"First User\"}}"
which is the expected one.
I do not know if it is the best solution but here is how I successfully test my json login process through webservices on devise :
require 'spec_helper'
require 'rest_client'
require 'active_support/core_ext'
describe "sign up / sign out / sign in edit / cancel account" do
before (:each) do
@user = {:name => "tester", :email =>"[email protected]"}
end
describe "POST 'sign up'" do
it "should sign up with json request" do
response_json = RestClient.post "http://localhost:3000/sign_up", {:user=>{:name=>"tester", :email => "[email protected]", :password => "FILTERED", :password_confirmation => "FILTERED"}}.to_json, :content_type => :json, :accept => :json
response = ActiveSupport::JSON.decode(response_json)
response["response"].should == "ok"
response["user"].should == @user.as_json
@@token = response["token"]
@@token.should_not == nil
end
end
describe "DELETE 'sign out'" do
it "should logout with json request" do
response_json = RestClient.delete "http://localhost:3000/users/sign_out?auth_token=#{@@token}", :accept => :json
response = ActiveSupport::JSON.decode(response_json)
response["response"].should == "ok"
end
end
describe "POST 'sign in'" do
it "should login with json request" do
response_json = RestClient.post "http://localhost:3000/users/sign_in", {:user => {:email => "[email protected]", :password => "FILTERED"}}.to_json, :content_type => :json, :accept => :json
response = ActiveSupport::JSON.decode(response_json)
response["response"].should == "ok"
response["user"].should == @user.as_json
@@token = response["token"]
@@token.should_not == nil
end
end
describe "PUT 'edit'" do
it "should edit user name with json request" do
response_json = RestClient.put "http://localhost:3000/users?auth_token=#{@@token}", {:user => {:name => "tester2", :email => "[email protected]", :current_password => "FILTERED"}}.to_json, :content_type => :json, :accept => :json
response = ActiveSupport::JSON.decode(response_json)
response["response"].should == "ok"
response["user"]["email"].should == "[email protected]"
response["user"]["name"].should == "tester2"
@@token = response["token"]
@@token.should_not == nil
end
end
describe "DELETE 'account'" do
it "should logout with json request" do
response_json = RestClient.delete "http://localhost:3000/users?auth_token=#{@@token}", :accept => :json
response = ActiveSupport::JSON.decode(response_json)
response["response"].should == "ok"
end
end
end
With that I can create a new user, log out, log in again, edit the account and delete the account. Everything through 5 webservices in json. This order of execution allows the tests to be played every time, but I think there is missing a real rollback process to be executed at the end of the campaign.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With