Capybara visit method is not working

2019-04-08 16:13发布

问题:

I'm not sure what's going on, but I can't get simple tests to work because Capybara's visit method is not working for me. I've been trying to finish this railscast on testing.

Once I get to the point where Capybara needs to visit the login page the test fails because it's only able to visit my root_url. Here's what the failure looks like. Note that it's failing because it can't even visit the login page. It's getting stuck on the homepage:

Running: spec/requests/password_resets_spec.rb
Running tests with args ["--color", "--failure-exit-code", "2", "--format", "progress", "--format", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--require", "/Users/lee/.rvm/gems/ruby-1.9.3-p0@supply_side/gems/guard-rspec-0.6.0/lib/guard/rspec/formatters/notification_rspec.rb", "spec/requests/password_resets_spec.rb"]...
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Home | My App</title>
<link href="/assets/application.css" media="all" rel="stylesheet" type="text/css">
<script src="/assets/application.js" type="text/javascript"></script>
</head>
<body>
  <ul class="user_nav">
<li><a href="/signup">Sign up</a></li>
      <li><a href="/login">log in</a></li>
  </ul>
<h1>Supply Side</h1>
<p>
  This is the home page for My App.
</p>

<h2>Visit the <a href="/secret">Secret Page</a>.</h2>


</body>
</html>
F

Failures:

  1) PasswordResets emails user when requesting password reset
     Failure/Error: click_link "Forgot Your Password?"
     Capybara::ElementNotFound:
       no link with title, id or text 'Forgot Your Password?' found
     # (eval):2:in `click_link'
     # ./spec/requests/password_resets_spec.rb:8:in `block (2 levels) in <top (required)>'

Finished in 0.40915 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/requests/password_resets_spec.rb:4 # PasswordResets emails user when requesting password reset
Done.

I've added the print page.html to show that it's not making it to the login page. Here's what the test looks like:

require 'spec_helper'

describe "PasswordResets" do
  it "emails user when requesting password reset" do
    user = Factory(:user)
    visit login_path
    print page.html
    click_link "Forgot Your Password?"
    fill_in "Email", :with => user.email
    click_button "Reset Password"
  end
end

Here's my spec/spec_helper.rb:

require 'rubygems'
require 'spork'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However, 
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.
  # This file is copied to spec/ when you run 'rails generate rspec:install'
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'capybara/rspec'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    config.mock_with :rspec

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    config.treat_symbols_as_metadata_keys_with_true_values = true
    config.filter_run :focus => true
    config.run_all_when_everything_filtered = true
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.
  FactoryGirl.reload
end

Here's my gemfile:

gem 'rails', '3.2.0'
gem 'heroku'
gem 'jquery-rails'
gem 'sorcery'

group :production do
  gem 'pg'
end

group :development, :test do 
  gem 'sqlite3'
  gem 'rspec-rails'
  gem 'factory_girl_rails'
  gem 'capybara'
  gem 'guard-rspec'
  gem 'spork'
  gem 'guard-spork'
  gem 'rb-fsevent'
  gem 'wirble'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

My routes:

  get "logout" => "sessions#destroy", :as => "logout"
  get "login" => "sessions#new", :as => "login"
  get "signup" => "users#new", :as => "signup"
  resources :users do
    member do
      get :activate
    end
  end
  resources :sessions
  match "/forgot_password" => "sessions#forgot_password"
  resources :password_resets
  match "/secret" => "pages#secret"
  root :to => "pages#home"

And finally my config/environments/test.rb

 # Settings specified here will take precedence over those in config/application.rb

  # The test environment is used exclusively to run your application's
  # test suite. You never need to work with it otherwise. Remember that
  # your test database is "scratch space" for the test suite and is wiped
  # and recreated between test runs. Don't rely on the data there!
  config.cache_classes = true

  # Configure static asset server for tests with Cache-Control for performance
  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=3600"

  # Log error messages when you accidentally call methods on nil
  config.whiny_nils = true

  # Show full error reports and disable caching
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Raise exceptions instead of rendering exception templates
  config.action_dispatch.show_exceptions = false

  # Disable request forgery protection in test environment
  config.action_controller.allow_forgery_protection    = false

  # Tell Action Mailer not to deliver emails to the real world.
  # The :test delivery method accumulates sent emails in the
  # ActionMailer::Base.deliveries array.
  config.action_mailer.delivery_method = :test

  # Raise exception on mass assignment protection for Active Record models
  config.active_record.mass_assignment_sanitizer = :strict

  # Print deprecation notices to the stderr
  config.active_support.deprecation = :stderr

  config.action_mailer.default_url_options = { :host => 'localhost:3000' }

I'm running Rails 3.2 on ruby 1.9.3. I'm at a loss for why this isn't working. Thanks in advance!

回答1:

In your test log, when the test executes visit login_path, are you initially hitting that action but then being redirected back to your homepage?