Can't get any FactoryGirl factories to register - ruby-on-rails-3

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

Related

cannot log-in user using rspec integration testing

I am trying to create a test for Login; The functionality has been implemented and working fine but I am trying to create a test for it. However, User model is empty in sessions controller but it has content in the test code. On the code below, I added binding.pry(debugger) to check for the User model.
It's working fine too when I am not using webdriver(js: true), if it's just purely like this:
post "/api/user/sign_in", {
user: {
email: user.email,
password: user.password
}
}
expect(response).to be_success
I've been using the same test code before which is working fine. I am not just sure if it has something to do with my front-end is AngularJS.
TEST CODE
require 'rails_helper'
describe Model, js: true do
let(:model) { Model }
let!(:user) { create(:user) }
it "Login" do
binding.pry ### #user exists in User.all #####
visit root_path
find('#btn-signin').click
find('#tab-signin').click
fill_in 'user_email', with: user.email
fill_in 'user_password', with: user.password
find('#btn-login').click
binding.pry #### user exists in User.all ####
expect(page).to have_css '.profile-pic'
end
end
SESSIONS CONTROLLER
def create
puts User.pluck(:email).join(', ') #### user does not exists (it's actually blank) ####
warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
render :json => current_user.to_json
end
GEMS
group :development, :test do
gem 'factory_girl_rails'
gem 'pry'
gem 'quiet_assets'
gem 'rspec-rails', '~> 3.0.0'
end
group :test do
gem 'codeclimate-test-reporter', require: nil
gem 'shoulda-matchers'
gem 'jasmine'
gem 'capybara'
gem 'selenium-webdriver', '~> 2.38.0'
end
RAILS SPEC
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.include Capybara::DSL
config.include FactoryGirl::Syntax::Methods
config.use_transactional_fixtures = true
config.include UserMacros
config.infer_spec_type_from_file_location!
end
SOLUTION:
GEMFILE
gem 'database_cleaner'
RAILS_HELPER.RB
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end

Capybara visit not working

ok I not sure what I am missing on the setting up of capybara, but on testing the visit link would appear not to be working. so I have a 3.2 app, I have my specs_helper set up like so:
require "spork"
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'factory_girl'
require 'capybara/rspec'
require 'capybara/rails'
Capybara.javascript_driver = :selenium
Capybara.default_wait_time = 5
include Devise::TestHelpers # see spec/support/devise.rb
include CarrierWave::Test::Matchers
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
include New_spec_helpers
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 = false
config.before :each do
Capybara.default_selector = :css
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after do
DatabaseCleaner.clean
end
end
end
Spork.each_run do
FactoryGirl.factories.clear
FactoryGirl.define do
sequence(:code) { |n| "code#{n}" }
sequence(:title) { |n| "title#{n}" }
end
Dir[Rails.root.join("spec/factories/**/*.rb")].each{|f| load f}
PortfolioNew::Application.reload_routes!
end
Then my test set up like this:
before(:each) do
build_projects
visit(projects_path)
end
it "test js" , :js=>true do
current_path.should == projects_path
end
However all i get in return is this:
Failure/Error: current_path.should == projects_path
expected: "/projects"
got: nil (using ==)
i have checked my routes and the projects path is definitely correct and working. Any thoughts on what the issue is would be gratefully received
Ok I found the issue in a comment on the this similar post Rails 3 rspec + capybara - current_path is nil?
Turns out the webrat conflicts with Capybara which was left in when from old tests.
So for anyone interested I just commented out of my gemfile and all good!
Try moving the visit call into the it block:
before(:each) do
build_projects
end
it "test js" , :js=>true do
visit(projects_path)
current_path.should == projects_path
end

Setting HTTP_REFERER does not work in before hook of RSpec config

I saw various versions of how to setup a global HTTP_REFERER in RSpec, but none of them worked with RSpec 2.6.4:
RSpec.configure do |config|
config.before(:each, :type => :controller) do
request.env["HTTP_REFERER"] = root_url
end
end
The request is always nil:
undefined method `env' for nil:NilClass
RSpec is calling this:
def self.eval_before_eachs(example)
world.run_hook_filtered(:before, :each, self, example.example_group_instance, example)
ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example.example_group_instance) }
end
# spec/support/http_referer.rb
module HttpReferer
def self.included(base)
base.class_eval do
setup :setup_http_referer if respond_to?(:setup)
end
end
def setup_http_referer
#request.env["HTTP_REFERER"] = "/back"
end
end
# spec/spec_helper.rb
RSpec.configure do |config|
config.include HttpReferer, :type => :controller
end
This link may help get you pointed in the right direction...
https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29
You'll need to make a module like...
module Foo
def set_referer
#request.env["HTTP_REFERER"] = root_url
end
end
Then configure RSpec...
RSpec.configure do |config|
config.extend Foo, :type => :controller
end
Then call it in each of your controller specs...
describe MyController do
set_referer
end
We're using a similar approach to set our session cookie, but YMMV.

How do I mock a devise objects association return values?

I have an Employee model, Client model, and an Office model. Devise is controlling the authentication logic on the Employee. I have multiple controllers which are subclassing a base controller which sets everything needed for all controllers (DRY). When testing these controllers, I need to be able to mock a returned office on the signed in devise employee in order for the controller tests to function properly, but am having issues.
The question: how can I mock User#office to return mock_office on the current_employee when current_employee is a real object.
Here is all the code needed to describe my problem.
app/models/employee.rb
class Employee < ActiveRecord::Base
devise :database_authenticatable, :token_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :lockable, :timeoutable
attr_accessible :username, :password_confirmation, :password, :email, :office_id
belongs_to :office
end
app/models/client.rb
class Client < ActiveRecord::Base
belongs_to :office
end
app/models/office.rb
class Office < ActiveRecord::Base
has_many :employees
has_many :clients
end
config/routes.rb
Project::Application.routes.draw do
devise_for :employees
namespace :employees do
resources :clients
end
end
app/controllers/employees/base_controller.rb
class Employees::BaseController < ApplicationController
before_filter :authenticate_employee! && :set_office
private
def set_office
#office = current_employee.office
end
end
app/controllers/employees/clients_controller.rb
class Employees::ClientsController < Employees::BaseController
def create
flash[:notice] = Message::SOME_MESSAGE
end
end
spec/support/controller_macros.rb
module ControllerMacros
def login_employee
let(:current_employee) { Factory(:employee) }
let(:mock_office) { mock_model Office }
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:employee]
sign_in :current_employee, current_employee
current_employee.should_receive(:office).and_return(:mock_office)
end
end
end
spec/spec_helper.rb
require 'rubygems'
require 'spork'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
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.include Devise::TestHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller
end
end
Spork.each_run do
end
spec/controllers/employees/clients_controller_spec.rb
require 'spec_helper'
describe Users::ClientsController do
login_employee
it { should inherit_from(Users::Admin::BaseController) }
describe 'basic test' do
before do
post :create, {}
end
it {should respond_with_content_type(:html)}
end
end
results of running the specs
(in /Users/developer/Development/Workspace/Project.ror3)
/Users/developer/.rvm/rubies/ruby-1.9.2-p180/bin/ruby -S bundle exec rspec ./spec/controllers/employees/clients_controller_spec.rb
No DRb server is running. Running in local process instead ...
.F
Failures:
1) Users::ClientsController basic test
Failure/Error: post :create, {}
NoMethodError:
undefined method `office' for nil:NilClass
# ./app/controllers/employees/base_controller.rb:6:in `set_office'
# ./spec/controllers/employees/clients_controller_spec.rb:12:in `block (3 levels) in '
Finished in 1.09 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/controllers/employees/clients_controller_spec.rb:15 # Users::ClientsController basic test
rake aborted!
ruby -S bundle exec rspec ./spec/controllers/employees/clients_controller_spec.rb failed
(See full trace by running task with --trace)
NOTE: There was a lot of code slimming to get all the information above. I re-read many times and believe the problem is not in the setup but the devise object itself (using sign_in). If you need more, please request.
module ControllerMacros
def login_employee
let(:current_employee) { mock_model Employee }
let(:mock_office) { mock_model Office }
before(:each) do
request.env['warden'] = mock(Warden, :authenticate => current_employee,
:authenticate! => current_employee)
current_employee.should_receive(:office).and_return(:mock_office)
end
end
end

Undefined name method test error in Rails3

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.