Jamie Starke bio photo

Jamie Starke

I develop for my career, but I also develop for fun, and whenever I think it can solve a problem I'm having. This has lead me to create side projects, such as Rental Map and BusTimes, among others.

Consulting Newsletter Email LinkedIn Github Stackoverflow More

Overview

Motivation

In my previous post, “Using Web Components to create a card playing algorithm”, I explained my motivation behind starting this project. The gist of it, I wanted to beat the Triple Triad mini-game in Final Fantasy VIII, I wanted to try out Web Components (for a while now), and I wanted to try out some basic AI algorithms I haven’t used in a while.

As I started building the app, I found that there were things I constantly wanted to test, and doing it manually would likely be too onerous. Unit tests would not only be ideal, they would actually make it kind of fun. But I had very little experience with JavaScript unit tests, much less Web Components. That’s where Web-Component-Tester comes in.

Web-Component-Tester

When I wanted to start doing tests with Polymer, I was lucky enough to come across “Unit Testing Polymer Elements”. If you’re just getting started testing Web components, I definitely recommend checking it out. It describes what web-component-tester is (a combination of mocha, chai, and selenium to run them in a number of browsers), how to use it (with examples), and why they made it. To get started, check out their Quick Start

Since I was building a number of custom dom-module elements, the .html suites made a lot of sense for me. I’ll go over at least at a high level one of my tests. The check my repository for the full file.

How to build a test

Personally, I find it nice to look at examples and try to figure out how they work. As such, I’ll deconstruct an example test from my <triad-card>.

<body>
    ...
    <script>
      function createCardElement () {
        container.innerHTML = "";
        var card = document.createElement('triad-card');
        container.appendChild(card);

        return card;
      }

      suite('<triad-card>', function() {
        ...
        test('color flip: the color should change, and back', function () {
          var card = createCardElement();
          card.color = "red";

          var expectedColor = "blue";

          card.flip();

          assert.equal(card.color, expectedColor, "The color should change to blue");

          expectedColor = "red";

          card.flip();

          assert.equal(card.color, expectedColor, "The color should change to red");
        });
      });
    </script>
  </body>
</html>
  • createCardElement: This is a helper function I made. I found that even though my <triad-card> element has a shadow dom, it’s not fully accessible until it hits the dom (specifically I don’t think the css class exists). As such, when testing elements, I found it useful to apply the element to the dom for consistency. This method clears my dom test container, and adds a new element to it I can manipulate in the tests.
  • suite('<triad-card>', ...: The text here can be whatever you want it to be. You can have multiple suites in a single html file, and several tests in a suite. You can also re-run only the tests for a particular file, suite, or even a single test.
  • assert.equal(..., "The color should change to blue");: The string here is the message you’ll see if something goes wrong, make it meaningful.

Now that we’ve build a test .html, if you try to run it, you’ll find that it doesn’t really do anyhting. To make it work, use WCT.loadSuites. This is my test/index.html:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

    <script src="../bower_components/webcomponentsjs/webcomponents-lite.js"></script>
    <script src="../bower_components/web-component-tester/browser.js"></script>
  </head>
  <body>
    <script>
      // Load and run all tests (.html, .js):
      WCT.loadSuites([
        'card-rep.html',
        'board-rep.html',
        'triad-card.html',
        'triad-board.html'
      ]);
    </script>
  </body>
</html>

This tells the system which files to load, and in which order run them. I’m pretty sure this is just the Mocha.js component.

Now that you have this together, you’ll want to pick up your favorite lightweight web-server to serve the files to your web-browser. The imports will not run correctly if run using the file schema. I personally like a simple python -m SimpleHTTPServer from the base of my project.

If your server places root at the base of your project, you can run your tests by going to http://localhost:8000/test.

wct

Once you’re happy with how your tests run in the browser, you can try the power of wct. What wct does is launch a light-weight server, serve up your tests, then run them through a number of browsers (All of the ones on your computer, if you’re lucky), using Selenium. If you don’t have wct installed, check the Quick Start from Polymer.

Travis-CI

I always see the little build badge around from Travis-CI. If you don’t know the one I’m referring to, it looks a little something like this.

Triple Triad build status

That’s actually the current build status for my App. I really like that. It displays confidence to anyone that might be checking out your project that it actually works, or at least your tests are running.

I wanted to get that, but how to make Travis-CI work with web-component-tester was a little more on the fringe. That is to say, I couldn’t find any documentation about it, even though the “Unit Testing Polymer Elements” references it directly. To make it work, you’ll need to get a sauce account, configure npm, and add a wct configuration. I’ll cover these below.

Configuring npm

To run web-component-tester on Travis-CI you need to configure npm to install all the necessary dependencies. Here’s an example that will probably get you started.

{
  "name": "a-project",    
  "description": "This is a brief description fo your project",
  "author": "Your Name",  
  "license": "MIT",
  "scripts": {
    "test": "wct --plugin sauce"
  },
  "devDependencies": {
    "web-component-tester": "*",
    "bower": "*"
  }
}

Note the "scripts" object. When Travis-CI runs the project, it will call npm test. When we wct on Travis-CI, we want to outsource the running of the in a number of browsers to sauce labs, which is why we call the sauce plugin.

Configuring wct

Once we have npm configured, we need to configure wct, so that the wct-sauce knows what browsers to use. I found it useful to test with Chrome, Firefox, Safari and Internet Explorer 11 (I don’t know if Web-Components are available in anything lower, but I’d love to hear in the comments if I’m wrong).

module.exports = {
    verbose: true,
    testTimeout: 5 * 60 * 1000,
    plugins: {
        sauce: {
            disabled: true,
            browsers: [
                "Windows 8.1/internet explorer",
                "OS X 10.10/chrome",
                "OS X 10.10/firefox",
                "OS X 10.10/safari"
            ]
        }
    }
};

I came to testTimeout of 5 minutes by trial and error. If for some reason the test runners take longer, that’s fine, as long as the tests pass. The timeout here as best I can tell is for a whole set of tests to run. I frequently was getting timeouts in the 30 second range.

We want disabled: true so that it doesn’t try to run sauce all of the time, but it’s easy to run with wct --plugin sauce. This means that when you run wct, it will run locally, and it runs very fast. If you set this value instead to false, it will run all the time whenever you call wct, even locally.

The browsers array contains [OS]/[browser] combinations. You can also apparently specify versions using [OS]/[browser]@[version]. I can’t seem to find an exact syntax referenced anywhere.

Configuring Sauce Labs

Sauce labs give you easy access to a Selenium cluster for performing your tests on a number of machines. They also currently give free accounts to Open Source projects. Check out their Sign up to get started.

Once your account is set up, you can test out sauce locally. First thing you will want to export your sauce configurations to your terminal

export SAUCE_USERNAME=[your sauce username] export SAUCE_ACCESS_KEY=[your sauce key]

You can then test out wct using the sauce plugin using wct --plugin sauce.

Configuring Travis-CI

To get travis started, you’ll want to add a .travis.yml file to your repo.

language: node_js
node_js:
- '0.12'
branches:
  except:
  - gh-pages

The language here tells Travis what language your project is, so that it can use the appropriate build tools. Given that web-component-tester uses npm for its dependencies, it seemed like an obvious choice.

node_js specifies the version of node to test with. In my case, node is really just running wct for me.

I set an except on gh-pages, because once I successfully build, I deploy to GitHub Pages, so I don’t want to have to build and test the same thing again.

Next we’ll want to set up the sauce credentials. If you are testing an open source project, sauce can tell you want you need to add to your .travis.yml file, using their Adding credentials for a public GitHub repo assistance.

In the case that your repo is private, or you want to learn what’s going on, you can do what the above tool would do for you. First you’ll want the to install the travis gem

gem install travis

Assuming you followed the instructions above, you can add a secured version of your username using the travis command

travis encrypt SAUCE_USERNAME=[your sauce username] --add

and your access key using

travis encrypt SAUCE_ACCESS_KEY=[your sauce access key] --add

In this case, the --add inserts the encrypted versions into your .travis.yml file for you.

Building with Travis CI

Now that your repo is all set up, go to Travis CI and set up your account. This is really easy assuming you’re using GitHub.

From your profiles page, flick the switch on the project you want to build.

Now just perform a push on your repository, and wait for your build.

As a little Added treat, if you go to the project page, and click on the build status (beside the name) you can get the code to embed your build status in your README.md file.

I hope this helps others more quickly get this up and running.

As always, let me know if you have any questions along the way.

If you found this walkthrough useful, and you’re interested in checking out other articles I write in the future, join my newsletter.