Tyler
Tyler

Reputation: 11509

Capybara actions not affecting test database

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

Answers (2)

Tyler
Tyler

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

Dhruv
Dhruv

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

Related Questions