capybara: fill_in sometimes does not finish filling in a field

Meta

Capybara Version: 2.13.0 Driver Information (and browser if relevant): selenium-webdriver (3.4.3) with chrome Version 59.0.3071.115

Expected Behavior

Using fill_in finishes filling in the field before moving on.

Actual Behavior

Sometimes when filling in a text field with fill_in, the desired content is not done filling in before capybara moves on, causing subsequent expectations to fail.

Steps to reproduce

  • Fill in a text field with capybara
  • Have an expectation later that checks for the content of that field
  • Sometimes (not always), the expectation will fail because the field was only partially filled in

Example:

    fill_in 'my_text_field', with: 'This is a test'
    click_on 'Submit'
    expect(page).to have_content 'This is a test'

=> Failure/Error: expect(page).to have_content 'This is a test'
       expected to find text "This is a test" in "This is a te"

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 8
  • Comments: 16 (5 by maintainers)

Commits related to this issue

Most upvoted comments

After switching from poltergeist/phantomjs to headless chrome, I had similar issues which were related to CSS3 animations with Bootstrap modals. The final solution was to remove the fade class for those modals, other ways of disabling animations in tests didn’t work for me.

I tried the solutions listed here, and others like checking for any elements matching jQuery’s :animated selector, but the only thing that consistently worked was to remove fade like @lacco suggested.

i’m using send_keys

module Macroses
  module Auth
    module_function

    def native_fill_field(selector, text)
      text.split('').each { |c| find_field(selector).native.send_keys(c) }
    end

    def login(user)
      visit root_path
      find('.nav-right', text: 'LOGIN').click

      within '#new_user' do
        native_fill_field 'user[password]', user.password
        native_fill_field 'user[email]',    user.email
      end

      click_link_or_button 'LOGIN'

      expect(page).to have_current_path root_path
      expect(page).to have_content('Signed in successfully')
    end
  end
end

I also ran into this issue, and was able to come up with a simple repro-script. The culprit is a bootstrap modal, so the problem seems to be caused by animated elements. This script fails always for me:

begin
  require "bundler/inline"
rescue LoadError => e
  $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
  raise e
end

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "capybara"
  gem "selenium-webdriver"
end

require "capybara"

html = DATA.read
app = proc { |env| [200, { "Content-Type" => "text/html" }, [html] ] }

INPUT = ("STRING" * 100)

sess = Capybara::Session.new(:selenium_chrome_headless, app)
sess.visit("/")
sess.click_button "Launch demo modal"
sess.fill_in "test-input", with: INPUT
value = sess.find("#test-input").value
raise "Input error: #{value} not equal input" if value != INPUT

__END__

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
      Launch demo modal
    </button>

    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title" id="myModalLabel">Modal title</h4>
          </div>
          <div class="modal-body">
            <textarea id="test-input"></textarea>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Save changes</button>
          </div>
        </div>
      </div>
    </div>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
  </body>
</html>

I guess the reason why this comes up more often now is that headless chrome is more susceptible to this than phantomjs (this test passes when poltergeist is used as a driver).

I was able to get this to pass by doing the following:

jQuery(function() {
  $.support.transition = false;
})

This also makes the problems go away in my test suite.

So in conclusion: this most probably has nothing to do with capybara.

Another approach was to disable animations/transitions/transformations in CSS. But there still were ~ 30% probability of errors when we have been using Bootstrap modals with fade class. Removing fade class in test environment solved the problem. Thanks @lacco!