1
votes

I'm fairly new to writing integration tests, so excuse me if this question appears rudimentary (although I spent hours looking for an answer online).

I'm working with Rails 4, RSpec and Capybara.

Here is my code:

RSpec.feature "Sign up" do
  it "has a working link to sign in page" do
    visit '/users/new'
    click_on("Sign in")
    expect(page).to have_content "Sign in to continue" <= the problem is here
  end
end

Error:

1) Sign up has a working link to sign in page
     Failure/Error: expect(page).to have_content "Sign in to continue"
       expected to find text "Sign in to continue" in ""

Link works fine in the browser. I tried save-and-open-page and it indeed shows a blank page. All my RSpec unit tests are working with the current configuration. Can it be the controller not rendering my page and if so, how can I fix it? I don't have any controller tests at this point.

Thanks a lot for any ideas!

My spec-helper:

RSpec.configure do |config|
  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
end

My rails-helper:

require 'capybara/rspec'

# This file is copied to spec/ when you run 'rails generate     rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.include FactoryGirl::Syntax::Methods
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
end

The full view:

<header class='header'>
  <div class='dog-logo'></div>
  <aside>
    <a class='blue-button' href='<%= new_session_url %>'>Sign in</a>
  </aside>
</header>

<h1 class='create-new-account-header-text'>Create your account!</h1>

<form class='create-account-form group' id='create-account-form'>
  <label>Name</label>
  <input type='text' for='Name' name='user[first_name]'
                     placeholder="First" class='sign-up-first-name'>

  <input type='text' for='Name' name='user[last_name]'
                     placeholder="Last" class='sign-up-last-name'>
  </label>

  <label>Choose your username</label>
  <input type='text' name='user[username]'
         for='Choose your username'>

  <label>Create a password</label>
  <input type='password' name='user[password]' class='sign-up-password'
         for='Create a password'>

  <label>Confirm your password</label>
  <input type='password' name='confirmPassword' class='sign-up-confirm-password'
         for='Confirm your password'>

  <label>Birthday</label>
  <select name='birthday-month' for='Birthday'>
    <option>January</option>
    <option>February</option>
    <option>March</option>
    <option>April</option>
    <option>May</option>
    <option>June</option>
    <option>July</option>
    <option>August</option>
    <option>September</option>
    <option>October</option>
    <option>November</option>
    <option>December</option>
  </select>
  <input name='birthday-day' type='text' placeholder="Day"     for='Birthday'>
  <input name='birthday-year' type='text' placeholder="Year" for='Birthday'>

  <label>Gender</label>
  <select name="user[gender]" for='Gender'>
    <option value="" disabled selected style='display:none;'>I am</option>
    <option value='M'>Male</option>
    <option value='F'>Female</option>
    <option value='O'>Other</option>
  </select>

  <input type='checkbox' for='I agree to be awesome!'
         class='sign-up-checkbox'>
  <label class='sign-up-awesome-label'>I agree to be awesome!</label>

  <button class='blue-button'>Create account</button>
</form>

UsersController:

class UsersController < ApplicationController
  before_action :redirect_current_user

  def new
    render :new
  end
end

SessionsController:

class SessionsController < ApplicationController
  before_action :require_user!, only: [:destroy]
  before_action :redirect_current_user, only: [:new]

  def new
    render :new
  end

  def destroy
    current_user.reset_session_token!
    session[:session_token] = nil
    redirect_to new_session_url
  end
end

ApplicationController:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user, :logged_in?

  def current_user
    @current_user ||= User.find_by(session_token:     session[:session_token])
  end


  def logged_in?
    !!current_user
  end

  def log_in!(user)
    user.reset_session_token!
    session[:session_token] = user.session_token
  end

  def log_out!
    current_user.reset_session_token!
    session[:session_token] = nil
  end

  def require_user!
    redirect_to new_session_url unless logged_in?
  end

  def redirect_current_user
    redirect_to root_url if current_user
  end
end
1
Do you have other links or buttons that contain "Sign in"?Alexey Shein
Nope, it is the only one with "Sign in" textPetr Gazarov
Could you share your view so we can see the markup?Alexey Shein
Just updated the question.Petr Gazarov
I took a look at your new session view. If I'm reading your code right, all of the rendering from that view comes out of a Backbone view. You may need to do some additional configuration to get your RSpec tests to run with JavaScript. This post may help: stackoverflow.com/questions/15312572/…dwenzel

1 Answers

1
votes

RESOLVED:

As correctly pointed out by @dwenzel in the comments, the content that was supposed to be present after the click, was being entirely rendered by Javascript.

When using Capybara, the default setting is that Javascript on the page does not get run. The issue was resolved by installing capybara-webkit (see capybara-webkit github for more info) and including the line

Capybara.javascript_driver = :webkit

in my spec_helper.rb. Note that you need to explicitly tell RSpec that tests involve JS by writing js: true when defining example group, like so:

RSpec.feature "Sign up", js: true do
  ...
  // your test examples here
  ...
end