FactoryGirl,Rspec2 and devise rails 3 - ruby-on-rails-3

I am using Rspec, FactoryGirl and Spork for my tests.There are 2 things I am a litte unclear on, first is the location of my factories.rb file. At present I have it located in
spec/support/factories.rb
And it looks like this
FactoryGirl.define do
factory :user do
email "example#yahoo.com"
password "password"
password_confirmation "password"
confirmed_at Time.now
end
end
Within my spec_helper I have
config.include FactoryGirl::Syntax::Methods
Secondly I want to login a user before starting my tests for a controller , this particular controller has a before filter :authenticate_user!
I am using devise for my authentication so have added
config.include Devise::TestHelpers, :type => :controller
Reading the devise docs you can add a controller_macros.rb and specify methods like so to use
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
sign_in user
end
end
And so i added this also to my spec_helper
config.include ControllerMacros, :type => :controller
So when I add login_user before my controller tests i get undefined method login_user. Am i using two tools here to do the same thing? Do I actually need the devise methods or can it all be done with factoryGirl. If so how do i setup the login process before i can test a controller?

Factories location should be in spec/factories. Check out this example app https://github.com/RailsApps/rails3-devise-rspec-cucumber/tree/master/spec.
For login, generally you seems to doing it right. Check the example app again and here: https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29
For the undefined method login_user error be sure to have
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
and
config.extend ControllerMacros, :type => :controller
in spec_helper. Devise methods should be available wtih subject:
subject.current_user.should_not be_nil

Related

ActiveAdmin and Warden route constraint

We recently updated to ActiveAdmin 1.1.0, on a site which maintains two distinct user models - Users and AdminUsers. ActiveAdmin authenticates AdminUsers, and the rest of the site authenticates Users. Both paths use Devise, like this:
devise_for :users, controllers: {sessions: :practitioner_sessions, passwords: :practitioner_passwords}
admin_devise_config = ActiveAdmin::Devise.config
admin_devise_config[:controllers][:sessions] = :sessions
devise_for :admin_users, admin_devise_config
Now, I have a Rails engine (Resque::Server) mounted which I want to restrict to admins, using a routing constraint like this in config/routes.rb:
module RouteConstraint
class Admin
def self.matches?(request)
request.env['warden'].user && request.env['warden'].user.admin?
end
end
end
mount ResqueWeb::Engine, :at => "/resque", :constraints => RouteConstraint::Admin
This used to work. However, now when an AdminUser is logged in to ActiveAdmin, request.env['warden'].user returns nil and request.env['warden'].authenticated? returns false.
Where do I go to check if a user is authenticated with ActiveAdmin in this configuration?
The "scopes" section of the Warden wiki gave me the clues I needed to rewrite two route constraints. Instead of querying the user method of the Warden object, I passed the relevant Devise scopes as arguments to the authenticated?() method. Remember that the Devise scopes can be found in routes.rb, e.g.:
devise_for :admin_users, admin_devise_config
devise_scope :admin_user do
# some stuff
end
So then constraints can be written like this:
module RouteConstraint
class SuperAdmin
def self.matches?(request)
warden = request.env['warden']
warden.authenticated?(:admin_user)
end
end
end
module RouteConstraint
class LoggedIn
def self.matches?(request)
warden = request.env['warden']
warden.authenticated?(:user) || warden.authenticated?(:admin_user)
end
end
end
Then I was able to use the constraints in the same way as before:
mount Resque::Server, :at => "/resque", :constraints => RouteConstraint::SuperAdmin
mount JobState::Engine, :at => "/job_state", :constraints => RouteConstraint::LoggedIn

Request spec with Devise + Rspec2 + Spork/Guard

I have setup Rspec2 + Spork + Guard + Devise
My files are as follows
#spec_helper.rb
Spork.prefork do
#code
Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f}
RSpec.configure do |config|
config.extend ControllerMacros, :type => :controller
end
end
Spork.each_run do
# This code will be run each time you run your specs.
FactoryGirl.reload
include ControllerMacros
end
#spec/support/controller_macros.rb
module ControllerMacros
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mapping[:user]
user = FactoryGirl.create(:user)
sign_in user
end
end
end
#spec/support/devise.rb
Spec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
in my request spec
#spec/features/documents_spec.rb
require 'spec_helper'
describe "Documents" do
login_user
describe "GET /documents" do
it "should display document name as sameera CV" do
#spec code
end
end
end
and when I run bundle exec guard, I get
1) Documents GET /documents should display document name as sameera CV
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `env' for nil:NilClass
# ./spec/support/controller_macros.rb:4:in `block in login_user'
So far I have done lots of fixes via google and nothing seems to be working, can someone help me :)
I'm on
rails 3.2.9
rspec 2.12.0
devise 2.2.3
any help would be greatly appreciated
Try changing #request.env["devise.mapping"] = Devise.mapping[:user] to request.env["devise.mapping"] = Devise.mapping[:user] in spec/support/controller_macros.rb
Here I'm answering my own question, and I was able to find a workaround for the question I asked.
Following are the steps I did
1) removed the controller_macros.rb and devise.rb from support directory
2) removed the ControllerMacros references from spec_helper.rb
3) Added the following code to
#spec/features/documents_spec.rb
before(:each) do
user = FactoryGirl.create(:user)
visit root_path
fill_in 'user_email', :with => user.email
fill_in 'user_password', :with => user.password
click_button 'Sign in'
end
I'm sure there should be a more elegant way (as describe in devise wiki), but this WORKS :)

rspec2 acceptance testing with capybara

I'm trying to implement a feature with rspec2 and rails3 , basically I have a Post model which I'm trying to test by creating a Post (I'm using device for authentication)
this is my feature
spec/acceptance/new_post_feature_spec.rb
require 'spec_helper'
require 'rspec/example_steps'
feature "Creating a new post" do
include Devise::TestHelpers
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryGirl.create(:user)
sign_in user
end
Steps "Add a new post" do
page.visit "/posts"
page.should have_content("New Post")
end
end
But I'm getting this error
undefined method `env' for nil:NilClass
Following are the gems I'm using
gem "rspec-rails", "~> 2.0"
gem 'database_cleaner'
gem 'capybara'
gem "factory_girl_rails", ">= 4.1.0"
gem 'rspec-example_steps'
with Guard/Spork
any help would be appreciated
#request is a controller test variable. It's not what you want here. In fact, in capybara specs you don't need to specify the devise mapping and you cant use sign_in.
Capybara fires up a browser, you must tell it to go to your login page and sign in through the same steps that you would do in a browser.
Try this: (you may need to change some input and button names)
let(:user) { FactoryGirl.create(:user) }
before(:each) do
page.visit new_user_session_path
# note: use the email/password input names below if yours are different
page.fill_in "user[email]", :with => user.email
page.fill_in "user[password]", :with => user.password
page.click_button "Sign in"
end

Why can't rspec find _path method?

The app's routes.rb has
resources :users, :only => :show
The user view has
User: #{link_to user.name, user}
The view spec has
describe 'home/index.html.haml' do
it 'should render the users' do
#users = User.all
render
end
end
It does the right thing if I hit the app locally but if I run rspec on the view, I get
Failure/Error: render
ActionView::Template::Error:
undefined method `user_path' for #<#<Class:0x109f2a468>:0x109db5128>
Spork turned out to be the culprit. Restarted it and the specs now pass.

Install recaptcha gem with exsisting devise gem with rubymine 3.1

What I've tried doing already: I've tried reading the documentation at github and getting it to work on Rubymine and I've managed to confuse myself with what is needed as far as controllers, and what is needed in the config folder. I've tried google and found some pretty good tutorials but their missing steps that I don't necessarily know to jump too.
What I'm trying to figure out: I want to be able use recaptcha in a login registration utlitizing the devise gem, I've already generated the pages for my devise login.
What I have so far:
I've installed and attached: devise 1.2.rc and recaptcha 0.3.1 I'm running Rubymine on windows xp. Ruby SDK 1.8.7-p302, with Rails 3.0.3
I've been to google and have my public and private keys
The next step tells me I'm supposed to add my keys to project/config/initializers/recaptcha.rb This is what is contained in that file:
Recaptcha.configure do |config|
config.public_key = 'myKey'
config.private_key = 'myKey'
end
Now I'm supposed to fix up my gemfile with:
gem 'recaptcha', :require => 'recaptcha/rails'
I also have my config/application.rb reading:
require 'rails/all'
require 'net/http'
I've also added to my External Libraries/[gem] devise/app/views/devise/registrations/new.html.erb the recaptcha tag:
<%= recaptcha_tags %>
<p><%= f.submit "Sign up" %></p>
Where I am running into issues (I think) is the
app/controllers/registrations_controller.rb and the config/routes.rb
I'm kinda of at a loss for what exactly goes into these files. Any help would be appreciated or a tutorial someone has written that walks me through this step by step would be very helpful. Thanks
Here's what I have done after Felix's post:
external libraries/app/controllers/devise/registrations_controller.rb
class Devise::RegistrationsController < Devise::RegistrationsController
def create
if verify_recaptcha then
super
else
build_resource
clean_up_passwords(resource)
flash[:notice] = 'Invalid Captcha'
render_with_scope :new
end
build_resource
if resource.save
if resource.active?
set_flash_message :notice, :signed_up
sign_in_and_redirect(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s
expire_session_data_after_sign_in!
redirect_to after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
render_with_scope :new
end
end
From Project/config/routes.rb:
devise_for :users, :controllers => {:registrations => 'registrations'}
This is the error that its spitting out:
ActionController::RoutingError (uninitialized constant RegistrationsController):
Rendered C:/Ruby/lib/ruby/gems/1.8/gems/actionpack-3.0.3/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (0.0ms) ..... any ideas?
For your routes, you can keep your normal devise routes except specifying your custom controller:
devise_for :users, :controllers => {:registrations => 'registrations'}
In the registrations_controller.rb, you want to subclass the Devise RegistrationsController and override the 'create' method:
class RegistrationsController < Devise::RegistrationsController
def create
if verify_recaptcha then
super
else
build_resource
clean_up_passwords(resource)
flash[:notice] = 'Invalid Captcha'
render_with_scope :new
end
end
end