Acceptance Testing With Ember.js
This article was originally written here.
It’s been about a year since we started the development of our Ember app. The framework has been evolving a lot since then for the good and many conventions and practices have been established as well. Here we share some improvements and practices we’ve done regarding our tests suite.
You might have heard this from Martin Fowler. This pattern suggests to treat each page/route/section as a whole object where each element (buttons, input fields, paragraphs, etc.) represent an attribute of such object.
You can achieve this easily with Ember Page Object, here’s a before/after example on how it’d look like.
As you can see, the main advantage here is isolation. Page Objects only responsibility is to hold the connection with UI elements and act as an interface so you can interact through them and reuse from any place you’d need.
HTML data attributes
In the previous example we rely on id attributes as selectors for UI elements. What would happen if a coworker changes any of those ids just for style purposes? Yes, tests will fail and shouldn’t. Relying on id attributes makes our Page Objects fragile.
A solution approach for this is the convention of using data-* attributes for test selectors. This way you only know they’re related to, and only to, our tests suite.
From now on the convention would be, use class attributes for CSS style, data-tests for tests selectors and maybe id for anything else.
Mocking external APIs
This was a game changer for us. For any Ember app that communicates with an external API, it’s crucial to have it mocked up in the test environment. We recently migrated from a custom approach to using Ember CLI Mirage.
Ember CLI Mirage goes beyond a single mock server and provides both factories and a runtime database out of the box. In other words, you can manipulate how the backend would behave in order to exercise your tests suite at your will.
Overall it definitely increases the reliability of your tests suite. The only caveat is that you have to manually ensure your mock server is always up-to-date with the actual backend for obvious reasons.