Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Devise+Omniauth(Facebook) with Cucumber

Here is my feature:

 Scenario: Professor is not signed up and tries to sign in with Facebook
      Given I do not exist as a professor
      When I sign in as a professor with Facebook
      Then I should see a successful sign in message
      When I return to the site
      Then I should be signed in as a professor

Here is the step definition for When I sign in as a professor with Facebook

When /^I sign in as a professor with Facebook$/ do
  set_omniauth
  visit "/professors/auth/facebook"
end

And here is the definition of set_omniauth helper:

def set_omniauth(opts = {})
  default = {:provider => :facebook,
             :uuid     => "1234",
             :facebook => {
                            :email => "[email protected]",
                          }
            }

  credentials = default.merge(opts)
  provider = credentials[:provider]
  user_hash = credentials[provider]

  OmniAuth.config.test_mode = true

  OmniAuth.config.mock_auth[provider] = {
    'uid' => credentials[:uuid],
    "extra" => {
    "user_hash" => {
      "email" => user_hash[:email],
      }
    }
  }
end

So... When I visit /professors/auth/facebook, this action is called

def facebook
    @professor = Professor.find_for_facebook_oauth(request.env["omniauth.auth"], current_professor)
    if @professor.persisted?
      flash[:notice] = "Welcome! You have signed up successfully."
      sign_in_and_redirect @professor, :event => :authentication
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_professor_registration_url
    end
  end

And finally, the method find_for_facebook_oauth definition is:

def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
    data = access_token["extra"]["raw_info"]
    if professor = self.find_by_email(data.email)
      professor
    else # Create a professor with a stub password. 
      self.create(:email => data.email, :password => Devise.friendly_token[0,20]) 
    end
  end

When running this feature, I get the following error message:

undefined method `email' for {"email"=>"[email protected]"}:Hash (NoMethodError)

So, I checked what Facebook actually returns:

#<Hashie::Mash email="[email protected]" ...

But this is a different object than a normal hash set in:

OmniAuth.config.mock_auth[provider] = {
    'uid' => credentials[:uuid],
    "extra" => {
    "user_hash" => {
      "email" => user_hash[:email],
      }
    }

So, my question is: How would I test this properly? I followed OmniAuth Integration Tetsing and they set a Hash, and not a Hashie.

like image 816
Nobita Avatar asked Nov 03 '22 22:11

Nobita


1 Answers

You need to create your Hash using a built in OmniAuth method for creating a Hashie object:

OmniAuth.config.mock_auth[provider] = OmniAuth::AuthHash.new({
'uid' => credentials[:uuid],
"extra" => {
"user_hash" => {
  "email" => user_hash[:email],
  }
})
like image 88
Matt Crouch Avatar answered Nov 15 '22 21:11

Matt Crouch