Attempted to assign to readonly property on Capybara - ruby-on-rails

I'm working on updating a rails 3.2 app to rails 4.2.10, I've got almost everything worked out, unit tests and integration tests passing.
I'm having some issues with feature tests, I'm using capybara 3.3.0 and poltergeist 1.18.1 and it throws me error on visit '/'
I've looked at lots of issues on Stack regarding Attemped to assign to readonly property but none of them apply to my case here,
This is my stripped down spec file
require 'vcr'
Capybara.default_max_wait_time = 10
feature "Create something" do
include SpecHelpers
include Acceptance
before do
setup_database
end
after do
teardown_database
end
scenario "Creating a Consignment", :js => true do
puts "Running with #{Capybara.current_driver}"
VCR.use_cassette('cassette_name.yml') do
page.driver.resize(1000,2200) unless Capybara.current_driver == :selenium
visit '/'
expect(page).to have_content 'EMAIL'
expect(page).to have_content 'PASSWORD'
end
end
end
This is my stripped down spec helper file
ENV["RAILS_ENV"] ||= 'test'
require_relative '../config/environment.rb'
require 'rspec/rails'
require 'capybara/rails'
require 'capybara/poltergeist'
require 'shoulda/matchers'
require 'redis'
require 'redis-namespace'
require 'resque'
require 'mock_redis'
require 'bcrypt'
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
# rspec
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
RSpec.configure do |config|
config.deprecation_stream = 'log/deprecations.log'
end
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, :type => :controller
end
RSpec::Expectations.configuration.on_potential_false_positives = :nothing
BCrypt::Engine.cost = 1
if (ENV['DEBUG_CAP'])
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
else
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {js_errors: true})
end
Capybara.javascript_driver = :poltergeist
end
Capybara.server_port = 31337
Capybara.server = :webrick
module SpecHelpers
def setup_database
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start
end
def teardown_database
DatabaseCleaner.clean
end
end
module Acceptance
VCR.configure do |c|
require 'webmock'
c.hook_into :webmock
c.cassette_library_dir = 'fixtures/vcr_cassettes'
c.allow_http_connections_when_no_cassette = true
c.default_cassette_options = {:record => :new_episodes}
c.ignore_request do |request|
URI(request.uri).port == Capybara.server_port || request.uri=~/shutdown/ || request.uri=~/session/
end
end
def wait_until(timeout = Capybara.default_max_wait_time)
require "timeout"
begin
Timeout.timeout(timeout) do
sleep(0.3) until value = yield
value
end
rescue => e
save_screenshot "capybara_#{Time.now.to_i}.png"
puts e.message
puts e.backtrace
raise e
end
end
end
require "rspec/mocks/standalone"
....
This is the error stack trace
Running with poltergeist
Error: Attempted to assign to readonly property.
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:22:3139
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:3551
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:19730
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12707
s#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:20964
g#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12573
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:16265
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:22205
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4884
$digest#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:7801
$apply#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:9410
http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26430
a#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26340
Z#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26051
http://127.0.0.1:31337/lib/bfd57c67.components.js:7:28112
d#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:18351
fireWith#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:19152
ready#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:13970
wt#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:11347
Error: Attempted to assign to readonly property.
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:22:3139
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:3551
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:19730
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12707
s#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:20964
g#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12573
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:16265
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:22205
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4884
$digest#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:7801
$apply#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:9410
http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26430
a#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26340
Z#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26051
http://127.0.0.1:31337/lib/bfd57c67.components.js:7:28112
d#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:18351
fireWith#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:19152
ready#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:13970
wt#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:11347
Error: Attempted to assign to readonly property.
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:22:3139
r#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:3551
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:19730
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12707
s#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:20964
g#http://127.0.0.1:31337/lib/bfd57c67.components.js:5:12573
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:16265
http://127.0.0.1:31337/lib/bfd57c67.components.js:5:22205
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
c#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4206
http://127.0.0.1:31337/lib/bfd57c67.components.js:6:4884
$digest#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:7801
$apply#http://127.0.0.1:31337/lib/bfd57c67.components.js:6:9410
http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26430
a#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26340
Z#http://127.0.0.1:31337/lib/bfd57c67.components.js:4:26051
http://127.0.0.1:31337/lib/bfd57c67.components.js:7:28112
d#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:18351
fireWith#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:19152
ready#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:13970
wt#http://127.0.0.1:31337/lib/bfd57c67.components.js:1:11347
Update 1
Upon some debugging, it turns out that error gets thrown from angularjs-bootstrap-datetimepicker package when it tries to set $render to a function,
var ngModelController = $element.controller('ngModel')
var configuration = createConfiguration()
$scope.screenReader = configuration.screenReader
// Behavior
$scope.changeView = changeView
ngModelController.$render = $render --> in this line

Related

Rails Rspec showing different results than console

I have a feature which works fine in production and in development, but the test I wrote for it doesn't pass. It seems like the data is not persisting, although when I use byebug it shows that it's fine.
Here's my spec:
it "cancels a user plan" do
plan = FactoryBot.create(:plan, name: 'MOMLab', paypal_id: 'MOMLab15')
user = FactoryBot.create(:user, email: 'payer#email.com',
payer_id: '6M5AMEDMVMSNL')
user_plan = FactoryBot.create(:user_plan, user: user, plan: plan, end_date: nil)
ipn = FactoryBot.create(:ipn, :cancelation)
sign_in FactoryBot.create(:user, :admin)
visit ipn_path(ipn)
expect(user_plan.status).to eq('Active')
click_on 'Process'
sleep 10
expect(ipn.reload.complete?).to be_truthy
expect(user_plan.reload.end_date.to_date).to eq(Time.zone.now.to_date)
expect(user_plan.status).to eq('Canceled')
end
Here's the code:
def cancel_subscription
#user = find_user
#user_plan = #plan.user_plans.where(user: #user).active.first
if #user_plan
#user_plan.end_date = Time.zone.now
#user_plan.status = 'Canceled'
#user_plan.save!
if #user_plan.persisted?
#ipn.update(complete: true)
else
handle_errors("User plan didn't save")
end
else
handle_errors("Couldn't find subscription")
end
end
I put the object with inspect during the execution and in the test - in the execution it appears like everything is okay and changes have persisted (it goes into the persisted? tree, but outside in the test it shows as if the object has never been saved.
Any ideas?
Edit:
Here's my rails_helper.rb:
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require "capybara/rspec"
require 'devise'
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
Capybara.register_driver :headless_chrome do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: { browser: 'ALL' })
opts = Selenium::WebDriver::Chrome::Options.new
chrome_args = %w[--headless --no-sandbox --disable-gpu --window-size=1920,1080 --remote-debugging-port=9222]
chrome_args.each { |arg| opts.add_argument(arg) }
Capybara::Selenium::Driver.new(app, browser: :chrome, options: opts, desired_capabilities: caps)
end
Capybara.javascript_driver = :headless_chrome
Capybara.current_driver = :headless_chrome
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.include Devise::Test::IntegrationHelpers, type: :feature
config.include Devise::Test::IntegrationHelpers, type: :request
config.infer_spec_type_from_file_location!
config.include Warden::Test::Helpers
Warden.test_mode!
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
end
and my spec_helper.rb:
require 'webmock/rspec'
require 'capybara/rspec'
include WebMock::API
require 'etsy'
RSpec.configure do |config|
Capybara.default_max_wait_time = 10
Capybara.register_driver :insecure_selenium do |app|
Capybara::Selenium::Driver.new(
app,
browser: :firefox,
desired_capabilities: { accept_insecure_certs: true }
)
end
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.shared_context_metadata_behavior = :apply_to_host_groups
begin
config.filter_run_when_matching :focus
config.example_status_persistence_file_path = "spec/examples.txt"
config.disable_monkey_patching!
if config.files_to_run.one?
config.default_formatter = "doc"
end=
config.profile_examples = 3
Kernel.srand config.seed
end
end

Rails - Singleton class troubles with rspec feature

I have a problem testing a functionality that depends of a Singleton class. That class (ERPDao) is a suite with diferent methods that helps application to connect with external ERP vía REST services using Faraday gem. URLMaker is a helper class for build requests strings. When i try to run a feature spec that depends of one of this methods i have the following message in rspec:
Failure/Error: result = ERPDao.instance.get_credit_info(erp_id)
NoMethodError:
undefined method `instance' for ERPDao:Class
Did you mean? instance_of?
Did you mean? instance_of?
My class ERPDao
class ERPDao
def initialize
#end_points = EndPoint.first
#connection = Faraday.new(:url => #end_points.url_base, request: {
open_timeout: 10, # opening a connection
timeout: 10 # waiting for response
})
end
##instance = ERPDao.new
def self.instance
return ##instance
end
def get_credit_info(erp_id)
begin
return #connection.get URLMaker.instance.get_uri('credit_info', erp_id)
rescue Faraday::Error::ConnectionFailed => e
puts "Connection failed: #{e}"
return 0, false, 0
end
end
...
end
My rails_helper.rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot'
require 'support/wait_for_ajax'
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
config.before :suite do
DatabaseCleaner.strategy = :truncation
end
config.before :each do
DatabaseCleaner.clean
end
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.include Warden::Test::Helpers
config.include Devise::TestHelpers, type: :controller
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
Capybara.javascript_driver = :webkit
Capybara::Webkit.configure do |config|
config.debug = false
config.allow_unknown_urls
config.skip_image_loading
config.timeout = 15
config.raise_javascript_errors = false
end
end
My version of rails is 4.2.6, ruby 2.3.1, factory_bot 4.8.2 and rspec-rails 3.7.
Someone knows about this error?
Thanks!
ERPDao is [also] being defined somewhere else. Maybe someone decided to add a method to it by re-opening the class like
class ERPDao
def some_new_method
...
end
end
Don't do that. Use modules and prepend instead.
module HasMyNewMethod
def some_new_method
...
end
end
ERPDau.prepend HasMyNewMethod
Otherwise you end up accidentally referencing the re-opening of the class and that becomes the definition - so the autoloader doesn't load it since it's already defined.
Search your codebase for 'class ERPDao'. Modify the ones that are not the initial declaration.

Slow tests on Heroku

I can understand this question is quite general, but I'm having an issue that my tests on Heroku are incredibly slow (20+ minutes) vs when I run them locally that takes around 9 or 10 minutes. And I was wondering if I could get pointed in a good direction on what the issue might be. This is my rails_helper.rb:
require 'simplecov'
SimpleCov.start
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'shoulda/matchers'
require 'sidekiq/testing'
Sidekiq::Testing.fake!
require 'public_activity/testing'
PublicActivity.enabled = false
# Checks for pending migrations before tests are run.
ActiveRecord::Migration.maintain_test_schema!
require 'capybara/rspec'
Capybara.asset_host = ENV['CAPYBARA_ASSET_HOST'] || "http://localhost:#{ENV.fetch('PORT', 3000)}"
Capybara.register_driver :headless_chrome do |app|
chrome_bin = ENV.fetch('GOOGLE_CHROME_SHIM', nil)
chrome_opts = chrome_bin ? { 'binary': chrome_bin } : {}
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome chromeOptions: { args: %w[headless disable-gpu disable-dev-shm-usage no-sandbox] }.merge(chrome_opts)
Capybara::Selenium::Driver.new app, browser: :chrome, desired_capabilities: capabilities
end
Capybara.javascript_driver = :headless_chrome
Capybara.server = :puma, { Silent: true }
# NOTE: Running with sauce REQUIRES SAUCE CONNECT tunnel driver
# so that saucelabs instance can communicate with your test server.
# run with...
# bin/sc -u obiefernandez -k 24e2ec72-ff16-4526-9a35-d7e8bd180d5a
#
# require "selenium/webdriver"
# Capybara.register_driver :sauce do |app|
# caps = Selenium::WebDriver::Remote::Capabilities.chrome()
# caps['platform'] = 'macOS 10.12'
# caps['version'] = '52.0'
# sauce_endpoint = "http://obiefernandez:24e2ec72-ff16-4526-9a35-d7e8bd180d5a#ondemand.saucelabs.com:80/wd/hub"
# Capybara::Selenium::Driver.new app, :browser => :remote, :url => sauce_endpoint, :desired_capabilities => caps
# end
# Capybara.javascript_driver = :sauce
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.before(:suite) do
# compile front-end and load manifest
`bin/webpack`
Webpacker::Manifest.load
DatabaseCleaner.allow_remote_database_url = true
DatabaseCleaner.strategy = :truncation, { pre_count: true, except: %w(ar_internal_metadata) }
DatabaseCleaner.clean
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
config.backtrace_exclusion_patterns << %r{/rails_helper\.rb:}
module SignInHelpers
extend ActiveSupport::Concern
class_methods do
def managing_project(&block)
if block_given?
let!(:project, &block)
let(:organization) { project.organization }
let(:project_manager) { create(:user, organization: organization, organization_admin: true) }
else
let!(:organization) { create(:organization_with_project_manager) }
let!(:project) { create(:project, organization: organization) }
let(:project_manager) { organization.admins.first }
end
before do
set_current_user(project_manager)
sign_in(project_manager) if respond_to?(:sign_in)
end
end
end
end
config.fixture_path = 'spec/fixtures'
config.include Devise::Test::ControllerHelpers, type: :controller
Devise::Test::ControllerHelpers.module_eval do
alias_method :original_sign_in, :sign_in
def sign_in(resource, deprecated = nil, scope: nil)
original_sign_in(resource, scope: scope)
# needed because devise integration helper bypasses normal ApplicationController logic
set_current_user(resource)
end
end
config.include Devise::Test::IntegrationHelpers, type: :feature
Devise::Test::IntegrationHelpers.module_eval do
alias_method :original_sign_in, :sign_in
def sign_in(resource, scope: nil)
original_sign_in(resource, scope: scope)
# needed because devise integration helper bypasses normal ApplicationController logic
set_current_user(resource)
end
end
config.include SignInHelpers # needed everywhere
# https://github.com/state-machines/state_machines-rspec
config.include StateMachinesRspec::Matchers
module IntegrationHelpers
extend ActiveSupport::Concern
included do
subject { page }
end
def visit(url, *args)
super(polymorphic_path(url), *args)
rescue
super
end
end
config.before(:each) do
Sidekiq::Worker.clear_all
end
config.include IntegrationHelpers, type: :feature
end
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end

Rspec - uninitialized constant error User

I have written tests on Rspec for my model User and get error while starting 'rspec spec'
NameError: uninitialized constant User
my test spec/models/ivd/user_spec.rb
require 'rails_helper'
module Ivd
RSpec.describe User, type: :model do
let(:user) { FactoryGirl.create(:ivd_user, email: "user#example.org", password: "very-secret", admin: true) }
it 'has a valid factory' do
expect(user).to be_valid
end
describe '.find_for_oauth' do
let!(:user) { FactoryGirl.create(:ivd_user) }
describe 'twitter' do
let(:auth) { OmniAuth::AuthHash.new({provider: 'twitter', uid: '12345'})}
context 'user has already authorization' do
it 'return user' do
user.identities.create({provider: 'twitter', uid: '12345'})
expect(User.find_for_oauth(auth)).to eq user
end
end
end
end
end
end
spec_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require 'simplecov'
# SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
SimpleCov.start :rails do
add_filter do |source_file|
source_file.lines.count < 5
end
end
require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'factory_girl_rails'
require 'capybara/poltergeist'
# require 'capybara/rails'
require 'ivd/seeder'
# http://www.thegreatcodeadventure.com/stubbing-with-vcr/
require 'vcr'
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
# load(Rails.root.join("db", "seeds.rb"))
# Configure capybara for integration testing
# Capybara.default_driver = :rack_test
# Capybara.default_selector = :css
# js_options = {js_errors: false}
# above is sometimes useful to troubleshoot errors with tests
js_options = {}
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_options)
end
Capybara.javascript_driver = :poltergeist
# Capybara.ignore_hidden_elements = false
# http://stackoverflow.com/questions/24078768/argumenterror-factory-not-registered
# as per above, need to explicitly set below
FactoryGirl.definition_file_paths = [File.expand_path('../factories', __FILE__)]
FactoryGirl.find_definitions
# Oddly above does not occur if factory_girl_rails is only referrenced in ivd.gemspec
# but not main gemfile
Rails.backtrace_cleaner.remove_silencers!
# Load support files
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
ActionController::Base.prepend_view_path "#{Ivd::Engine.root}/app/themes/default/views/"
RSpec.configure do |config|
# TODO - consider precompiling assets to speed up tests
# config.before(:suite) do
# Rails.application.load_tasks
# Rake::Task["assets:precompile"].invoke
# end
config.include JsonSpec::Helpers
config.warnings = false
config.mock_with :rspec
config.infer_base_class_for_anonymous_controllers = false
config.order = 'random'
# config.include Ivd::ApplicationHelper
# config.include Rails.application.routes.url_helpers
# config.include Ivd::Engine.routes.url_helpers
config.use_transactional_fixtures = false
#
# Make sure the database is clean and ready for test
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
Ivd::Seeder.seed!
end
config.after(:all) do
# http://renderedtext.com/blog/2012/10/10/cleaning-up-after-before-all-blocks/
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
# truncation is slower but more reliable
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
rails_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../dummy/config/environment.rb', __FILE__)
abort('The Rails environment is running in production mode!') if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'rails-controller-testing'
# Add additional requires below this line. Rails is not loaded until this point!
require 'devise'
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.warnings = false
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{Ivd::Engine.root}/spec/fixtures"
# above used by fixture_file_upload
# eg in:
# /Users/etewiah/Ed/sites-2016-oct-ivd/ivd/spec/services/ivd/import_properties_spec.rb
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
[:controller, :view, :request].each do |type|
config.include ::Rails::Controller::Testing::TestProcess, type: type
config.include ::Rails::Controller::Testing::TemplateAssertions, type: type
config.include ::Rails::Controller::Testing::Integration, type: type
end
# https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)
config.include Devise::Test::ControllerHelpers, type: :controller
config.include FeatureHelpers, type: :feature
config.extend ControllerMacros, type: :controller
# https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs
config.include ControllerHelpers, type: :controller
# https://github.com/plataformatec/devise/wiki/How-To:-sign-in-and-out-a-user-in-Request-type-specs-(specs-tagged-with-type:-:request)
config.include RequestSpecHelpers, type: :request
end
I have model User, which has been inherited from ApplicationRecord.
File .rspec contains only:
--color
--require byebug
--require rails_helper
Is your model itself within the module Ivd? i.e.
module Ivd
class User
If so, you want to be using RSpec.describe Ivd::User rather than wrapping the call in the module.

Rails: Can not save on DB during rspec features test

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 'pierre#tralala.com'
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.
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.
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)
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 "person1#example.com" and add 1 to the number each time FactoryGirl.create(:user) is called.

Resources