Skip to content

Instantly share code, notes, and snippets.

@jittuu
Created January 24, 2011 02:19
Show Gist options
  • Save jittuu/792715 to your computer and use it in GitHub Desktop.
Save jittuu/792715 to your computer and use it in GitHub Desktop.
Test Omniauth Facebook Callback Controllers in Devise with rspec
require 'spec_helper'
describe Users::OauthCallbacksController, "handle facebook authentication callback" do
describe "#annonymous user" do
context "when facebook email doesn't exist in the system" do
before(:each) do
stub_env_for_omniauth
get :facebook
@user = User.where(:email => "ghost@nobody.com").first
end
it { @user.should_not be_nil }
it "should create authentication with facebook id" do
authentication = @user.authentications.where(:provider => "facebook", :uid => "1234").first
authentication.should_not be_nil
end
it { should be_user_signed_in }
it { response.should redirect_to tasks_path }
end
context "when facebook email already exist in the system" do
before(:each) do
stub_env_for_omniauth
User.create!(:email => "ghost@nobody.com", :password => "my_secret")
get :facebook
end
it { flash[:notice].should == "Your email ghost@nobody.com is already exist in the system. You need to sign in first."}
it { response.should redirect_to new_user_session_path }
end
end
describe "#logged in user" do
context "when user don't have facebook authentication" do
before(:each) do
stub_env_for_omniauth
user = User.create!(:email => "user@example.com", :password => "my_secret")
sign_in user
get :facebook
end
it "should add facebook authentication to current user" do
user = User.where(:email => "user@example.com").first
user.should_not be_nil
fb_authentication = user.authentications.where(:provider => "facebook").first
fb_authentication.should_not be_nil
fb_authentication.uid.should == "1234"
end
it { should be_user_signed_in }
it { response.should redirect_to authentications_path }
it { flash[:notice].should == "Facebook is connected with your account."}
end
context "when user already connect with facebook" do
before(:each) do
stub_env_for_omniauth
user = User.create!(:email => "ghost@nobody.com", :password => "my_secret")
user.authentications.create!(:provider => "facebook", :uid => "1234")
sign_in user
get :facebook
end
it "should not add new facebook authentication" do
user = User.where(:email => "ghost@nobody.com").first
user.should_not be_nil
fb_authentications = user.authentications.where(:provider => "facebook")
fb_authentications.count.should == 1
end
it { should be_user_signed_in }
it { flash[:notice].should == "Signed in successfully." }
it { response.should redirect_to tasks_path }
end
end
end
def stub_env_for_omniauth
# This a Devise specific thing for functional tests. See https://github.com/plataformatec/devise/issues/closed#issue/608
request.env["devise.mapping"] = Devise.mappings[:user]
env = { "omniauth.auth" => { "provider" => "facebook", "uid" => "1234", "extra" => { "user_hash" => { "email" => "ghost@nobody.com" } } } }
@controller.stub!(:env).and_return(env)
end
@zakelfassi
Copy link

I agree with @jalcine.
A safer approach would be request.env["omniauth.auth"] = env["omniauth.auth"] and so the stub_env_for_omniauth will be:

def stub_env_for_omniauth
  # This a Devise specific thing for functional tests. See https://github.com/plataformatec/devise/issues/closed#issue/608
  request.env["devise.mapping"] = Devise.mappings[:user]
  env = { "omniauth.auth" => { "provider" => "facebook", "uid" => "1234", "extra" => { "user_hash" => { "email" => "ghost@nobody.com" } } } }
  request.env["omniauth.auth"] = env["omniauth.auth"]
end

@kakipo
Copy link

kakipo commented Jun 23, 2014

It would be better to use OmniAuth::AuthHash.new in order to simulate the params; otherwise you could get errors if you accessed params in your code like request.env["omniauth.auth"].provider

def stub_env_for_omniauth
  # This a Devise specific thing for functional tests. See https://github.com/plataformatec/devise/issues/closed#issue/608
  request.env["devise.mapping"] = Devise.mappings[:user]

  request.env["omniauth.auth"] = OmniAuth::AuthHash.new({
    "provider"=>"facebook",
    "uid"=>uid,
    ...
  })
end

@vfonic
Copy link

vfonic commented Jun 7, 2015

Great tests! I used them in my project. Thanks!

Couple of tests I'd add would be to test when user rejects facebook authentication.

Also, here's another test I added, which is not necessarily needed, but I like to have it around:

it "should alias #facebook to #auth_all" do
  expect(Users::OauthCallbacksController.instance_method(:facebook)).to eq(Users::OauthCallbacksController.instance_method(:auth_all))
end

@glaucocustodio
Copy link

glaucocustodio commented May 8, 2024

For those who are doing request tests in Rails 7:

RSpec.describe OmniauthCallbacksController, type: :request do
  context "when admin does not exist" do
    it "should redirect admin to new session path" do
      OmniAuth.config.test_mode = true
      OmniAuth.config.mock_auth[:google_oauth2] = OmniAuth::AuthHash.new(
        provider: "google_oauth2",
        uid: "123",
        info: OmniAuth::AuthHash::InfoHash.new(email: "foo@bar.com", name: "jose"),
        extra: {
          raw_info: OmniAuth::AuthHash.new(email_verified: true)
        }
      )
      Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:google_oauth2]

      get admin_google_oauth2_omniauth_callback_path

      expect(response.code).to eq("302")
      expect(response).to redirect_to(new_admin_session_path)
      expect(flash[:alert]).to eq("User not found")
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment