Search code examples
jqueryruby-on-railscapybaraintegration-testingtestunit

Rails: how can I test a stopwatch in my Capybara integration tests?


Currently writing tests for my Rails app's time tracking functionality. I can't figure out a way to simulate clicking the "play" button on the timer, waiting a few seconds, clicking pause and then submitting the form (creating a new Timestamp object).

test "track time with stopwatch" do
    visit new_project_timestamp_path(@project)
    find('#play_button').click 
    sleep 4.0
    find('#pause_button').click
    click_button "submit_new_timestamp"
    visit project_path(@project)
    assert page.has_content? "4 seconds"
 end

^This is the gist of what I want it to do, but sleep obviously doesn't work because it suspends the thread completely, whereas I want the test to kind of "wait around" while the stopwatch does its thing for a few seconds. The above test fails because no time is actually tracked; pause is clicked immediately after play, in the eyes of the timer, and so the form is submitted with no actual time logged, which of course throws a validation error.

Is there a way I'd be able to simulate waiting a few seconds without actually suspending the thread?


Solution

  • (Note: huge thanks to Tom Walpole for his answer. The issue was that I wasn't using a JS-enabled web driver. Thought I'd write this for anyone else having similar problems due to the same lack of understanding I had.)

    The issue is that I wasn't using a web driver that executes Javascript. By default Capybara uses the :rack_test driver which, while fast, doesn't execute Javascript.

    So for integration tests that rely on JS being executed (in my case interacting with a stopwatch), something like :poltergeist is a good idea. To set it up, add

      gem 'poltergeist'
      gem 'phantomjs', :require => 'phantomjs/poltergeist'
    

    to the Gemfile and run bundle install.

    You'll need to add

      require 'capybara/poltergeist'
      Capybara.javascript_driver = :poltergeist
    

    to your test/spec helper file. Then all you need to do is set Capybara.current_driver = Capybara.javascript_driver wherever you need a JS-enabled integration test.