Getting inconsistent "Unable to find css" errors with Rspec + Capybara + Ember Getting inconsistent "Unable to find css" errors with Rspec + Capybara + Ember selenium selenium

Getting inconsistent "Unable to find css" errors with Rspec + Capybara + Ember


Figured this out. SO, when looking for elements on a page you have a few methods available to you:

first('.some-selector')all('.some-selector') #returns an array of coursefind('.some-selector')

.first and .all are super useful as they let you pick from non unique elements.

HOWEVER .first and .all don't seem to auto-wait for the element to be on the page.

The Fix

The fix then is to always use .find(). .find WILL honour the capybara wait time. Using .find has almost completely fixed my tests (with a few unrelated exceptions).

The gotcha of course is that you have to use more unique selectors as .find MUST only return a single element, otherwise you'll get the infamous Capybara::Ambiguous exception.


Ember works asynchronously. This is why Ember generally recommends using Qunit. They've tied in code to allow the testing to pause/resume while waiting for the asynchronous functions to return. Your best bet would be to either attempt to duplicate the pause/resume logic that's been built up for qunit, or switch to qunit.

There is a global promise used during testing you could hook up to: Ember.Test.lastPromise

Ember.Test.lastPromise.then(function(){  //continue});

Additionally visit/click return promises, you'll need some manner of telling capybara to pause testing before the call, then resume once the promise resumes.

visit('foo').then(function(){  click('.expand-thing').then(function(){    assert('foobar');  })})

Now that I've finished ranting, I'm realizing you're not running these tests technically from inside the browser, you're having them run through selenium, which means it's not technically in the browser (unless selenium has made some change since last I used it, possible). Either way you'll need to watch that last promise, and wait on it before you can continue, testing after an asynchronous action.