I'm Matthew J. Morrison.

A Passionate, professional software developer & hobbyist; Language nerd & regular user of Unix, Python, Ruby & JavaScript.

Fork me on GitHub

As you may have noticed, I have been working in UI design a lot this week. Today was no exception. Yesterday, my pair (the great and powerful @jarrodctaylor) and I were discussing testing responsive web applications. We use Ember.js and ember testing to do integration testing for our web applications. The challenge is that with the tools that we use (Karma and Testem) it is not really possible to test responsive web applications because there are no mechanisms in place to allow you to control the size of the browser window…or so we thought.

Yesterday evening, after having our discussion, I did some looking to see if there was a way to launch the Google Chrome browser with a specific window size. Lo and behold I found that there is in fact a flag called --window-size. Unfortunately, testem is not very friendly to extensibility. In testem’s source the command line arguments are hard coded:

args: ["--user-data-dir=" + tempDir + "/testem.chrome", "--no-default-browser-check", "--no-first-run"]

Karma, however, is much more extensible. To launch Google Chrome in karma, an external package called karma-chrome-launcher is used. Since karma-chrome-launcher supports customLaunchers it will allow you to pass additional flags to Google Chrome when it is launched. By adding a few lines of configuration to your karma.conf.js file you can launch Google Chrome with a specific window size.

module.exports = function(config) {
  config.set({
    /* SNIP other configuration */
    browsers: ['mobile', 'desktop'],
    customLaunchers: {
      mobile: {
        base: "Chrome",
        flags: "--window-size=320,600"
      },
      desktop: {
        base: "Chrome",
        flags: "--window-size=700,600"
      }
    }
  });
}

Mind blown yet? Maybe it is, but wait. This will not work. Have you figured out why, yet? The thing about responsive design is that it is heavily dependent on css stylesheets. Unfortunately, with both karma and testem the default behavior does not include any css stylesheets. You get all of your JavaScript source included but that is really it. To be able to test the responsive design the css would need to be included as well.

To include css in your tests you’ll need to tweak karma’s configuration to be something like this:

module.exports = function(config) {
  config.set({
    /* SNIP other configuration */
    files: [
      /* SNIP Other files */
      {pattern: 'path/to/css/files.css', included: false}
    ]
  });
}

This will not include it on the page, but it will make it available to the server that karma spins up behind the scenes. It is up to you to include the css on the page. In a test helper file (included in the files setting) you will need to add something like the following:

$("body").append("<link rel='stylesheet' href='/base/path/to/css/files.css' />");

The /base/ is important. That is the root of the url for the server that karma spins up, so make sure your css url starts with that.

The last gotcha comes with the actual tests. Because responsive design takes advantage of hiding and showing things on the page using css media queries you need to be careful when accessing elements on the page because they may or may not be visible.

Here is an example of a test for both the mobile and desktop version of the application. Take note of the jquery :visible pseudo selector.

test "Test large layout", ->
  visit "/"
  andThen ->
    welcome = find("#big-version:visible").text()
    equal(welcome, "The desktop")

test "Test mobile layout", ->
  visit "/"
  andThen ->
    welcome = find("#mobile-version:visible").text()
    equal(welcome, "The mobile version")

When these tests run, the first one will fail on the mobile version and the second one will pass. Then on the desktop version the first one will pass and the second one will fail.