4
votes

I'm using rspec to perform feature tests and I can't save the user in the DB before the log in. I'm using factory girl to build the object. fixture are saved in db at the beginning of the test but are not deleted at the end.(maybe because the test fail. I don't know)

So I can not save the user before clicking on logIn and I get this errror message

-- DEPRECATION WARNING: an empty resource was given to Devise::Strategies::DatabaseAuthenticatable#validate. Please ensure the resource is not nil. (called from set_required_vars at app/controllers/application_controller.rb:43)

spec/features/login_to_mainpage_spec.rb (no error are rescued)

require "rails_helper"

feature 'Navigating to homepage' do
  let(:user) { create(:user) }
  let(:login_page) { MainLoginPage.new }

  scenario "login" do
    login_page.visit_page.login(user)
    sleep(20)
  end
end

A simple page object: spec/features/pages_objects/main_login_page.rb

class MainLoginPage
  include Capybara::DSL

  def login(user)
    fill_in 'email', with: user.email
    fill_in 'password', with: "password"
    click_on 'logIn'
  end

  def visit_page
    visit '/'
    self
  end
end

my rails_helper

require 'spec_helper'
require 'capybara/rspec'
require 'capybara/poltergeist'
require "selenium-webdriver"
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/features/page_objects/**/*.rb")].each { |f| require f }

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = false
  config.before :each do
    DatabaseCleaner.start
  end
  config.after :each do
    DatabaseCleaner.clean
  end

  config.infer_spec_type_from_file_location!

  config.include Devise::TestHelpers, :type => :controller
end

Capybara.default_driver = :selenium
Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, :browser => :firefox)
end

in spec helper:

require 'simplecov'
require 'factory_girl'
require 'rspec/autorun'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'


ENV["RAILS_ENV"] ||= 'test'
RSpec.configure do |config|
  include ActionDispatch::TestProcess
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
  config.disable_monkey_patching!

  if config.files_to_run.one?
    config.default_formatter = 'doc'
  end

  config.profile_examples = 10

  config.order = :random

  Kernel.srand config.seed
end

EDIT 1

I switch "gem 'factory_girl'" to "gem 'factory_girl_rails'"

and add this to application.rb

config.generators do
|g|
  g.test_framework :rspec,
                   :fixtures => true,
                   :view_specs => false,
                   :helper_specs => false,
                   :routing_specs => false,
                   :controller_specs => true,
                   :request_specs => true
  g.fixture_replacement :factory_girl, :dir => "spec/factories"
end

I still can not save the user in DB. Everything pass but I put some sleep(10) in by code to refresh my DB and see te records and user is never saved

EDIT 3

My problem is actually very simple. FactoryGirl.create never save the data in DB if I put in my rails_helper:

config.use_transactional_fixtures = true

or

config.before :each do
 DatabaseCleaner.start
end
config.after :each do
 DatabaseCleaner.clean
end

/spec/factories

FactoryGirl.define do
  factory :user  do
    email '[email protected]'
    password 'password'
    password_confirmation 'password'
end

/spec/support/factory_girl.rb

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

spec/features/login_to_mainpage_spec.rb

let(:user) { create(:user) }
scenario "login" do
  login_page.visit_page.login(create(:user))
  sleep(5)
end

User will not be saved because of the config I cited before. I need to have data reseted between tests.

EDIT 4

If I'm using the console

RAILS_ENV=test rails c
FactoryGirl.create(:user) it is saved in db.

I don't understand why it does not work in my tests.

3

3 Answers

1
votes

Try using let! to create your user. From the rSpec documentation:

Note that let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can use let! to force the method's invocation before each example.

0
votes

You said that you are using FactoryGirl but I do not see this in your test. To create my Users with FactoryGirl I always do something like this:

FactoryGirl.create(:user, password: 'test', password_confirmation: 'test', name: 'test')

If setup correctly in your Factory you can just write:

FactoryGirl.create(:user)
0
votes

To solve your problem with the unique fields FactoryGirl provides you sequences:

sequence :email do |n|
    "person#{n}@example.com"
end

factory :user do
    email { generate(:email }
end

This will start with "[email protected]" and add 1 to the number each time FactoryGirl.create(:user) is called.