Better UI testing in Ember

Appaloosa Store
Appaloosa Store Engineering
6 min readMar 23, 2017

--

At appaloosa.io, we believe that testing your code is very important, it ensures reliability and helps reducing the amount of bugs shipped in production.

Even if often left behind, testing your frontend (which is your first interface with your customers) is as important as testing your backend.

One of the most painful parts in web development is to make sure that your UI stays consistent everywhere. I’m not talking about responsivity but the fact that your website/webapp does not break the UI as you move from version x to x+4. How can we ensure that changes on page A did not break page B?

We are currently rebuilding our old admin dashboard with a new fancy one made with ember.js.

Our new fancy dashboard

In order to reduce the time spent on UI checks and UI bug fixes, we have decided to use a bunch of cool ember addons and follow some coding conventions that make us able to strongly test our UI.

Let’s see how we do it at Appaloosa.

How we deal with CSS

Before talking about testing, let’s have a quick look about the way we deal with CSS.

Most of visual glitches in web development come from CSS (duplicate class names, rules overly generic…). At Appaloosa we’ve decided to use some conventions and ember addons that make our styles more robust.

We use the SASS preprocessor with ember-cli-sass, which make us able to define variables used everywhere like fonts sizes or colors.

We also use autoprefixer (ember-cli-autoprefixer) which deals with vendor prefixes for us. This keeps our styles clean as we only write CSS properties following the W3C specs and not the vendor prefixes.

We follow the css BEM OOCSS syntax that helps us having a consistent CSS and reducing CSS cross modification errors.

BEM OOCSS syntax

The main advantage of BEM is its clear syntax (which is human readable). It avoids the use of big CSS cascades as all component descendants are prefixed, so there is no need for deep nesting.

Thanks to SASS we can also split our styles into smaller, more maintainable portions. Every component/template has its own style file. Combined with the BEM syntax, this allows us to greatly reduce the number of issues caused by CSS by removing the possibility of accidental duplication.

To make sure a component cannot be impacted by side effects (or produce some), we also use ember-component-css. This addon allows us to create a stylesheet file per component and all rules inside the files will be nested inside a unique class generated by the addon. So a component’s CSS cannot apply outside (no side effect), and outside CSS will have to be very specific in order to override the component’s CSS.

How we test

Because the UI is what our customers see, we prioritised testing on our components/views as much as possible to avoid any surprises in production. If a component is supposed to render text using data, we check the rendered text. If a component parts is rendered conditionally, we try to test all possible use cases. We try to test every states of our components in order to make sure that an imperfect component will never be shipped to production.

Components are in fact just HTML + CSS + some Javascript. In order to test the rendering of a component, we need an access to the HTML. Accessing and testing only parts of HTML can be really painful for rich components. You can end up with some big, overly complicated and unreadable querySelector that you will need to change every time you update the template of your component. The solution is to use something that will never change even if you change the DOM of the component.

For that we use ember-test-selectors, this Ember addon allows you to declare custom selectors that you can use in your tests and that will not be shipped to production.

For example, let’s say I have a component rendering a list of apps (Android, WindowsPhone, iOS…) that can be filtered. Let’s focus on the platforms filters.

As you can see it’s pretty simple, we have two checkboxes linked with two variables androidFilter and iosFilter. Now, how can we click the android filter checkbox within a test?

There’s plenty of ways to achieve it, for example :

  • We can get all checkboxes and only click the first one : $('input[type="checkbox"]').first().click()
    This works but we might need to update our test if we add or remove another checkbox.
  • We can add a CSS class to my filter .android-filter and do this : $('.android-filter').click()

Ok, but is it really necessary to pollute the DOM with CSS classes only used in tests?

Instead, you can update the checkbox code like this.

{{input type=”checkbox” checked=androidFilter data-test-android-filter}}

As mentioned before, ‘ember-test-selector’ allows you to add custom data attributes, to a component or HTML tag, that will not be shipped in production.

At this point, we only talked about how we test our component rendering. Now is the time to see how we test that our components look the way they should. For that, we use Percy.io and its Ember addon ember-percy.

Percy.io cute logo =3

Percy.io is a visual reviews service that checks on every pull request if the aspect of a component hasn’t changed (even by one pixel). It really is easy to use with ember thanks to the addon. Here is a simple example using a colored div:

Here percySnapshot will send a snapshot of our div to Percy. Then this snapshot will generate and add a screenshot in our Percy dashboard.

Now let’s change our block’s width and height:

Here we have updated our component style, percySnapshot will again send a snapshot to our percy dashboard. But because our component has changed, we now have a visual diff.

On the right our original div and on the left our modified div

As you see it’s very easy to figure out UI changes.

At appaloosa we use Percy a lot, in fact all our UI changes are validated using it. In regard of our usage, the only lacking feature as of today is that it does not offer a way to test on multiple browsers (tests are run on Firefox only).

Impacts

Our processes are not perfect yet and we still have visual issues appearing in production from time to time. The most common reasons are incomplete tests and browser specific behavior. We also have no way to test animations.

But the use of Percy.io allows us to easily test our components’ rendering. It can even detect changes in complex components such as graphs (svg graphs generated with d3js) which would have been painful to test otherwise.

Awesome graph, painful to test

This new workflow we designed a few months ago helped us gain robustness and swiftness in the process of our frontend development. We managed to dramatically reduce CSS side effects on our project. Almost all visual regressions or issues are detected before going into production. We are also very proud to announce that a few weeks ago, we released some pages of our new dashboard to a few users and none report UI issues.

We would like to give special thanks to Mike Fotinakis CEO of Percy for his feedback on this article.

You should subscribe to our blog to be notified whenever a new article is available!

This article was written by part of Appaloosa’s dev team:
Benjamin JEGARD

Want to be part of Appaloosa? Head to Welcome to the jungle.

--

--