0

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: "foo@bar.baz",
                      username: "foobar",
                      password: "foobar",
                      password_confirmation: "foobar",
                      confirmed_at: Time.now - 1.minute)
      @user2 = User.create!(email: "foo2@bar.baz",
                      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
Tyler
  • 11,272
  • 9
  • 65
  • 105

2 Answers2

1

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.

Community
  • 1
  • 1
Dhruv
  • 1,380
  • 12
  • 20
  • Thank you for the resources, but everything appears to be OK based on those pages; I'll add the setup info to my question. – Tyler Jun 13 '13 at 22:42
  • This solved exactly the problems I was having. The issue was using selenium and not having RSpec configured with `config.use_transactional_fixtures = false` and the `database_cleaner` gem set up. – Alex Lynham Oct 14 '13 at 10:25
0

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

Tyler
  • 11,272
  • 9
  • 65
  • 105