I've been working on an app for learning purposes which includes OmniAuth for Facebook logins, Cucumber for BDD and CanCan & Rolify for permissions and roles. No Devise is used so far. I'm trying to write a test that involves logging a user with admin role and then visiting a restricted path. Also, users that have been created with OmniAuth have simple attributes: If the user has been confirmed to use the site, he/she will have confirmed: 1 and confirmation_token: nil; otherwise it will be confirmed: 0 and confirmation_token: . The idea actually works if I'm not in a Cucumber environment, but inside it, the page gives me a CanCan::AccessDenied error. Oh, and I've also set OmniAuth test mode, that works fine, env["omniauth.auth"] returns a proper mock hash.
This is my test (I'm still learning so bear with me)
@omniauth_test
Given /^I am logged as an admin$/ do
#ensure no session is active
visit '/signout'
@user = FactoryGirl.create(:user, confirmed: 1, confirmation_token: nil)
@user.add_role :admin
visit root_url
click_link "log_in" #means going to '/auth/facebook/callback'
end
And /^I check the user list$/ do
visit users_path #fails
end
This is my Factory for user, nothing complicated:
FactoryGirl.define do
factory :user do |u|
u.email 'test@example.com'
end
end
This is my SessionsController:
class SessionsController < ApplicationController
def create
reset_session
service = Service.from_omniauth(env["omniauth.auth"])
session[:user_id] = service.user.id
session[:service_id] = service.id
session[:expires_at] = 5.minutes.from_now
if service.user.confirmed == 0
redirect_to edit_user_path(service.user)
elsif service.user.confirmed == 1
if service.user.has_role? :member
redirect_to root_url
elsif service.user.has_role? :admin
redirect_to users_path
else
redirect_to root_url, :notice => "Work in progress!"
end
end
end
And finally, Service.rb:
class Service < ActiveRecord::Base
attr_accessible :user_id, :provider, :uid, :name, :token, :updated_at
validates_uniqueness_of :uid, :scope => [:provider]
belongs_to :user
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |service|
if !service.user
user = User.create(:email => auth.info.email)
service.user = user
#for some reason, instance variable @user created by FactoryGirl is nil at this point (test env)
user.add_role :signedup
end
service.provider = auth.provider
service.uid = auth.uid
service.name = auth.info.name
service.token = auth.credentials.token
service.save!
end
end
What I would like is to somehow use the OmniAuth hash and add the admin role and the confirmed attributes only for test mode, without messing too much with the production code (if possible), maybe adding helper methods to env.rb, and logging in with that user.