Reputation: 11509
I have an app with users who can post and also vote for other posts. In testing with Capybara, I am having trouble getting the right actions to come through.
I have simplified my tests as much as possible to try to find the error easily, to no avail:
requests/users_spec.rb
require 'spec_helper'
describe "Users" do
before :all do
Warden.test_reset!
Warden.test_mode!
end
describe "when logged in, CAN" do
before :all do
User.all.map(&:destroy)
Post.all.map(&:destroy)
@user = User.create!(email: "[email protected]",
username: "foobar",
password: "foobar",
password_confirmation: "foobar",
confirmed_at: Time.now - 1.minute)
@user2 = User.create!(email: "[email protected]",
username: "foobar2",
password: "foobar",
password_confirmation: "foobar",
confirmed_at: Time.now - 1.minute)
@post = Post.create!(
title: Faker::Lorem.sentence(5),
content: Faker::Lorem.sentence(25),
post_type: "temporary",
user_id: @user2.id
)
vote = LoggedUpvote.create!(user_id: @user2.id, post_id: @post.id)
login_as(@user, scope: :user)
end
it "create Upvotes", js: true do
count = Upvotes.all.count
visit post_path(@post.obfuscated_id)
page.find('.upvote').click
Upvotes.all.count.should eq(count + 1)
end
end
end
In my spec_helper.rb file I have:
Capybara.run_server = true
Capybara.server_port = 7000
Capybara.app_host = "http://localhost:#{Capybara.server_port}"
Capybara logs in just fine, navigates fine, and performs the actions fine, but the database record for the upvote is not created (despite showing visual confirmation that it has been created and that the right user is logged in).
The upvote is submitted through ajax, and a success response is shown on the screen, but no record is created in the database.
How can I get the record to create?
EDIT My spec_helper file looks like:
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
require 'capybara/rails'
require 'rubygems'
require 'spork'
include Warden::Test::Helpers
# From http://stackoverflow.com/questions/8662554/how-to-use-the-test-database-with-capybara
Capybara.run_server = true
Capybara.server_port = 7000
Capybara.app_host = "http://localhost:#{Capybara.server_port}"
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
Spork.prefork do
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.infer_base_class_for_anonymous_controllers = false
config.order = "random" # From http://railscasts.com/episodes/413-fast-tests
config.include FactoryGirl::Syntax::Methods
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run focus: true
config.run_all_when_everything_filtered = true
config.filter_run_excluding :slow unless ENV["SLOW_SPECS"]
config.before(:all) { DeferredGarbageCollection.start }
config.after(:all) { DeferredGarbageCollection.reconsider }
config.before(:suite) { DatabaseCleaner.strategy = :truncation }
config.before(:each) { DatabaseCleaner.start }
config.after(:each) { DatabaseCleaner.clean }
end
end
Spork.each_run do
FactoryGirl.reload
end
Upvotes: 0
Views: 206
Reputation: 11509
As it turns out, the database setup was fine, but Capybara was not waiting properly for the AJAX transaction to finish.
The solution was to add the following after the Upvote click and before the test assertion:
require "timeout"
Timeout.timeout(Capybara.default_wait_time) do
sleep(0.1) until Upvote.all.count == count + 1
end
And now everything works great.
Source: https://gist.github.com/jnicklas/d8da686061f0a59ffdf7
Upvotes: 0
Reputation: 1400
I'm assuming that you are using a driver other than RackTest (based on your mention of ajax, you'd need some sort of javascript support). If so, you may not have setup Capybara correctly to share a database with the selenium driver. See this SO answer, this blog post or this part of the README for more details.
Upvotes: 1