0

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.

1 Answers1

0

Silly me. This did the trick:

@omniauth_test
  Given /^I am logged as an admin$/ do
    @user = FactoryGirl.create(:user, confirmed: 1, confirmation_token: nil)
    @user.add_role :admin
    @service = FactoryGirl.create(:service, user: @user, uid: '1234567', provider: 'facebook')
  end