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 => "[email protected]").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 => "[email protected]", :password => "my_secret")
get :facebook
end
it { flash[:notice].should == "Your email [email protected] 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 => "[email protected]", :password => "my_secret")
sign_in user
get :facebook
end
it "should add facebook authentication to current user" do
user = User.where(:email => "[email protected]").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 => "[email protected]", :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 => "[email protected]").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" => "[email protected]" } } } }
@controller.stub!(:env).and_return(env)
end
@jalcine
Copy link

jalcine commented Nov 4, 2013

Why do you stub in the ominauth.auth field when you don't stub in Devise's hash as well?
You might as well just set in and shorten the call stack. Adding to that, the information you set from https://github.com/intridea/omniauth/wiki/Integration-Testing could be taken into play here.

@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" => "[email protected]" } } } }
  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: "[email protected]", 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