Undefined name method test error in Rails3 - ruby-on-rails-3

Working through Michael Hartl's RailsTutorial and came across the following error - even though I have followed everything to the 'T'.
1) UsersController GET 'index' for signed-in users should have an element for each user
Failure/Error: response.should have_selector("li", :content => user.name)
undefined method `name' for #<Array:0x000001032c07c8>
Did anyone else get a similar error and know how to fix it?
I am in Chapter 10.
Btw, when I try the page it does what it is supposed to do. It's just that the test fails in RSpec.
FYI, here is the related test code from the users_controller_spec.rb
require 'spec_helper'
describe UsersController do
render_views
describe "GET 'index'" do
describe "for non-signed-in users" do
it "should deny access" do
get :index
response.should redirect_to(signin_path)
flash[:notice].should =~ /sign in/i
end
end
describe "for signed-in users" do
before(:each) do
#user = test_sign_in(Factory(:user))
second = Factory(:user, :email => "another#example.com")
third = Factory(:user, :email => "another#example.net")
#users = [#user, second, third]
end
it "should be successful" do
get :index
response.should be_success
end
it "should have the right title" do
get :index
response.should have_selector("title", :content => "All users")
end
it "should have an element for each user" do
get :index
#users.each do |user|
response.should have_selector("li", :content => user.name)
end
end
end
end
My spec/spec_helper.rb file looks like the following:
require 'rubygems'
require 'spork'
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you'll
# need to restart spork for it take effect.
ENV["RAILS_ENV"] ||= 'test'
unless defined?(Rails)
require File.dirname(__FILE__) + "/../config/environment"
end
require 'rspec/rails'
# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
Rspec.configure do |config|
# == Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
config.mock_with :rspec
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, comment the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
### Part of a Spork hack. See http://bit.ly/arY19y
# Emulate initializer set_clear_dependencies_hook in
# railties/lib/rails/application/bootstrap.rb
ActiveSupport::Dependencies.clear
def test_sign_in(user)
controller.sign_in(user)
end
def integration_sign_in(user)
visit signin_path
fill_in :email, :with => user.email
fill_in :password, :with => user.password
click_button
end
end
end
Spork.each_run do
end

it appears your test_sign_in method is returning an instance of an array rather than a User object. Are you explicitly returning a user object in the test_sign_in method? If not, have a look at the last line that's executed in that method, I have a feeling the result of it is an array.

I solved this issue, and the answer can be found on the railstutorial official forums.

Related

Can't get any FactoryGirl factories to register

I'm trying to set up Rspec and FactoryGirl on an existing Rails 3 project which previously has had no automated testing.
The error I'm getting when running the test as below is Factory not registered: admin
I can't see why this would be failing, it happens for every test through my specs that use a factory.
/Gemfile.rb (concatenated for brevity)
group :development, :test do
gem 'rspec-rails'
gem 'factory_girl_rails
end
/config/application.rb (concatenated for brevity)
config.generators do |g|
g.test_framework :rspec, fixture: true
g.fixture_replacement :factory_girl, dir: "spec/factories"
end
/spec/spec_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/mechanize'
require 'factory_girl_rails'
HTTPI.log = false
FactoryGirl.factories.clear
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.mock_with :rspec
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.expect_with :rspec do |c|
c.syntax = :expect
end
config.include Devise::TestHelpers, type: :controller
config.extend ControllerMacros, type: :controller
end
/spec/support/controller_macros.rb
module ControllerMacros
def login_admin
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in FactoryGirl.create(:admin)
end
end
end
/spec/factories/users.rb
FactoryGirl.define do
factory :admin do
sequence(:email) {|n| "user#{n}#local.test"}
password "password"
password_confirmation "password"
association :user_role, factory: :admin_role
trait :as_reseller do
association :user_role, factory: :reseller_role
end
trait :as_customer do
association :user_role, factory: :customer_role
end
end
factory :reseller, parent: :admin do
as_reseller
end
factory :customer, parent: :admin do
as_customer
end
end
/spec/controllers/accounts_controller_spec.rb
describe AccountCodesController do
describe "as administrator" do
login_admin
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
end
end
This line FactoryGirl.factories.clear confuse me a lot.
According to doc you needn't do any spec_helper modification (if you use it in Rails app and through Bundle).
This is my spec_helper in one of my APP and I use factories in it successfully.
It's explain on the link
The stable documentation is here :
http://github.com/thoughtbot/factory_girl/tree/1.3.x

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 :)

FactoryGirl,Rspec2 and devise 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

how can you test the 'catch all route' using ordinary controller tests?

Note: As per RafaeldeF.Ferreira's suggestion, this question has been heavily edited since its original form.
My JSON-based app needs to return something sensible when given a bad route. We already know that the following rescue_from ActionController::RoutingError doesn't work in Rails 3.1 and 3.2:
# file: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from ActionController::RoutingError, :with => :not_found
...
end
(This is well documented in https://github.com/rails/rails/issues/671.) So I implemented what José Valim describes in this blog entry (item 3), and details are provided below.
But testing it has been problematic. This controller rspec test:
# file: spec/controllers/errors_controller.rb
require 'spec_helper'
require 'status_codes'
describe ErrorsController do
it "returns not_found status" do
get :not_found
response.should be(StatusCodes::NOT_FOUND)
end
end
fails with:
ActionController::RoutingError: No route matches {:format=>"json", :controller=>"sites", :action=>"update"}
Yet this integration test calls ErrorsController#not_found and succeeds:
# file: spec/requests/errors_spec.rb
require 'spec_helper'
require 'status_codes'
describe 'errors service' do
before(:each) do
#client = FactoryGirl.create(:client)
end
it "should catch routing error and return not_found" do
get "/v1/clients/login.json?id=#{#client.handle}&password=#{#client.password}"
response.status.should be(StatusCodes::OK)
post "/v1/sites/impossiblepaththatdoesnotexist"
response.status.should be(StatusCodes::NOT_FOUND)
end
end
So: Is there a way to test the 'catch all route' using ordinary controller tests?
implementation details
If you want to see the implementation, here are the relevant code snippets
# config/routes.rb
MyApp::Application.routes.draw do
... all other routes above here.
root :to => "pages#home"
match "/404", :to => "errors#not_found"
end
# config/application.rb
module MyApp
class Application < Rails::Application
config.exceptions_app = self.routes
...
end
end
# config/environments/test.rb
MyApp::Application.configure do
...
config.consider_all_requests_local = false
...
end
# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
def not_found
render :json => {:errors => ["Resource not found"]}, :status => :not_found
end
end

"Expected css... to return something" : rspec fail while test by hand works (can't reproduce the fail myself)

I'm working on a training app which is an Ogame-Like game (https://github.com/arnlen/ogame-like).
I'm using rspec (with Capybara) in order to test my app.
I'm stacked for several hours because rspec is complaining for an error which *I can't reproduce * by myself with my browser.
Here is my rspec code :
describe 'Planet pages' do
let(:user){FactoryGirl.create(:user)}
before {sign_in user}
subject {page}
describe "new planet page" do
before {visit new_planet_path}
describe "with valid information" do
before do
visit new_planet_path
fill_in "Name", with: "MyPlanet"
click_button "Validate"
end
# This test doesn't pass
it {should have_selector('h1', text: "Planet")}
end
end
end
The failure :
1) Planet pages new planet page with valid information
Failure/Error: it {should have_selector('h1', text: "Planet")}
expected css "h1" with text "Planet" to return something
# ./spec/requests/planet_pages_spec.rb:34:in `block (4 levels) in <top (required)>'
Here is the involved code.
My function "sign_in" used by rspec (location : spec/support/utilities.rb)
def sign_in(user)
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
My UsersController
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :show, :edit, :update, :destroy]
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
redirect_to new_planet_path
else
render 'new'
end
[...]
My PlanetsController
class PlanetsController < ApplicationController
before_filter :signed_in_user
def index
#planets = current_user.planets
end
def new
#planet = Planet.new
end
def create
#planet = Planet.new(name: params[:planet][:name],
coordinates: generate_coordinates,
metal_ressource: 1000,
user_id: current_user.id)
if #planet.save
flash[:success] = "Welcome on your first planet!"
redirect_to action: 'index'
else
flash[:error] = "Error naming your planet"
render 'new'
end
end
end
And My Planet Index view
<% #planets.each do |planet| %>
<h1>Planet : <%= planet.name %></h1>
<p><%= "Coordinates : #{planet.coordinates}" %></p>
<% end %>
I tried to user the Capybara method "save_and_open_page", but rspec raised an error "undefined method"
I also tried step by step debugging by iterations on my spec file, and it revealed that the error occurs right after the "click_button 'Validate'". For an unknown reason, rspec seems not to be able to reach the planets_path ("index" action from PlanetsController).
I'm out, if anybody has an idea, I take it !
EDIT : SOLVED - Found the problem!
Using the "save_and_open_page" method from Capybara, I figured out what was going on: the planet created by rspec didn't have any coordinates, which was not allowed by the model.
How to debug with the wonderful "save_and_open_page" method
Add this to your gemfile : "gem 'launchy'"
Install it : bundle install
Put the command "save_and_open_page" wherever you want
Hope it could help. :)
Capybara also has a save_page method, which is easier to use as it does not seem to need the "launchy" gem. The pages are saved in tmp/capybara. In the rspec tests, be sure to use save_page inside before, it, or some other block. It will not work as a separate command. Example:
before { visit signup_path; save_page }