It seems that there is little information and guides on the web how to test Ember apps in Rails environment, like best practices, what tools to use.
Unfortunately this testing category is a bit outdated too. Now we face a problem that the app is growing bigger and Rspec tests are not sufficient.
What we are after is a simple setup of Ember tests run in Rails environment. Test should be automated / run in a headless browser. We are using newest Ember and Ember Data.
Weāre preparing a presentation on this for the next Ember.js meetup in Toronto so weāll post more details for you then, but the gist of our approach is this:
We use Cucumber / Capybara with Poltergeist. Obviously, you need to use the javascript driver for every scenarioā¦ but we also found we also needed to tie into the ember runloop and make sure that each step verifies that the run loop has been completed before proceeding. Soā¦ something like this:
AfterStep '@ember-fuckery' do
wait_for_ember_run_loop_to_complete
end
and that runs this:
using_wait_time 20 do
patiently do
return if page.evaluate_script "(typeof Ember === 'object') && !Ember.run.hasScheduledTimers() && !Ember.run.currentRunLoop"
sleep 0.1
end
end
Check out Jo Lissās Testing Ember Apps presentation. Itās a little out of date (Ember didnāt have explicit testing support when it was made), but the basic idea is really solid - write thorough integration tests in JavaScript (she suggests using Konacha/Mocha+Chai), and then a single full-stack happy-path integration test for each feature to make sure data makes it properly from the client- to the server-side. The pure JS tests are super fast and easy to debug, and the full-stack tests make sure the whole app is working together properly.
My student Steven Ferguson has been working on a Rails+Ember address book that tests using this approach, if you want an up-to-date example of how to set things up.
Weāve refined our approach a little recently because all the āpatiently/using_wait_timeā stuff was causing us some trouble. Hereās the new version:
patiently do
return unless page.has_css? '.ember-application'
end
2000.times do #this means up to 20 seconds
return if page.evaluate_script "(typeof Ember === 'object') && !Ember.run.hasScheduledTimers() && !Ember.run.currentRunLoop"
sleep 0.01
end
Iāve been futzing around with this a bit. Iām taking Jo Lissās approach of writing pure-JS integration tests for most of my app (āclient-side integration testsā), and doing a single client-to-DB test (āend-to-end integration testā) for each feature. For the end-to-end tests, hereās an example of what I came up with:
By using page.should have_content job.title within the expect block, Iām tapping into Capybaraās built-in waiting abilities. And because the block doesnāt finish running until the page is updated, which doesnāt happen until the server responds, I can be sure that I donāt check the database until itās done saving.
At a glance it seems nice, i followed Emberjs guide for integration testing which includes setting ember in testing mode, and spawning a div for the test enviroment to live in. But the inconsistencies i had between my dev and test environment was a dealbreaker for me. Some of my issues included missing social share buttons, page titles were not updating in routes, strange behavior when switching page. Now there is of course a possibility that i might just have messed it up, but then again, there is not much configuration that you could mess up.
Also, if you have created specs using Capybara, Rspec etc. the experience is just very poor, everything you test is mainly using css selectors, say you have to click a button in a menu, then you have to write click(āa[href=āmylink/blablaā]ā).
I should point out, that i used it only for integrations test.
We donāt use Cucumber, but I was able to use much of this information with Rspec integration tests. We are using Selenium as well, because I was having issues with Poltergeist. I will throw the wait_for_ember method in the spec if there is a page load, etc. I think one other thing to mention would be that Database Cleaner is essential to making it all work as well. Thanks for your good work!