Question

I'm using Capybara and Poltergeist to test an index page that uses setTimeout to periodically refresh page content. The page content transitions between three states, based on an external service, and I've got a cassette for each of these states.

I'm trying to test the refresh using code like this:

VCR.use_cassette 'object_new' do
  visit index_path
  page.should have_content 'New'
end

VCR.use_cassette 'object_running' do
  page.should have_content 'Running'
end

VCR.use_cassette 'object_complete' do
  page.should have_content 'Complete'
end

The first have_content succeeds, but the second does not. Capybara should be waiting for any async calls to return and update the DOM so that these assertions pass. I've tried using_wait_time to force the assertion to wait long after the ajax call returns, but it doesn't help. Any ideas as to what might be missing from my spec to make this work? The functionality does work in the browser; it's just the tests that aren't passing.

Was it helpful?

Solution 2

The initial implementation is actually correct, but my JS wasn't resilient enough to handle server errors. Requests were being fired between cassette reloads, and were returning non-success HTTP statuses.

Updating the JS to handle erroneous requests and continuing polling solved this issue, and in the end, is the how the JS should have been behaving anyway.

OTHER TIPS

When you use the poltergeist driver to run your tests, your pages are actually being rendered in a separate process (i.e. a phantomjs process).

This means if your javascript loads any external content, PhantomJS will actually load the external content rather than loading the VCR cassette, as VCR only affects HTTP calls made within the Ruby process running your tests.

Rather than trying to test your JS code with Capybara, you should consider testing your JS with something like Jasmine, where you will have the chance to mock out the calls to the external service.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top