Categories
Elixir English

JavaScript Unit Tests in a Phoenix Application

There’s a guide to writing browser acceptance tests for Phoenix. Acceptance tests are nice, but sometimes you want to have unit tests. This is very easy to do with your Elixir code, but what about your JavaScript code that lives inside your Phoenix application?

I couldn’t find a good guide on this, so I’ll go over what I have set up for one of my latest Phoenix projects.

Setup

First, install mocha if you haven’t already. I’ll be using mocha, but you can use whatever test runner you want to. You’ll also need babel-register — this will allow you to use Babel while the tests are being run in Node.

$ npm install --save-dev mocha
$ npm install --save-dev babel-register

Set up mocha to run your tests in package.json. The default Phoenix & Brunch installation doesn’t include a “scripts” section, so you’ll probably have to create it. If it’s already there, just add the “test” line.

{
  "dependencies": {
    ...
  },
  "scripts": {
    "test": "mocha --compilers js:babel-register test/js/**/*.js"
  }
}

Now, set up Babel to pick up the default preset (if you’re setting a different preset in your brunch-config.js, you just replace es2015 with what you have there). Put this in .babelrc in the root directory of your project.

{
  "presets": ["es2015"]
}

Now, you can put JavaScript unit tests in test/js and by running npm test, they will run inside Node.

Note that npm test will not be automatically run when you run mix test, so you’ll have to change the way tests are run on your CI run by either changing the test command to mix test && npm test or adding the npm test command to your CI configuration.

Example Test

Say we have a module that does nothing but export a function that returns the string "something":

export default function() {
  return "something";
}

This file lives in web/static/js/something.js.

Now, let’s write a test for it in test/js/something_test.js:

import assert from 'assert';
import something from '../../web/static/js/something';

describe('something()', function() {
  it('does something', function () {
    assert.equal('something', something());
  });
});

Now, run the tests:

$ npm test

> @ test /Users/keita/personal/phoenix-mocha-example
> mocha --compilers js:babel-register test/js/**/*.js



  something()
    ✓ does something


  1 passing (8ms)

This example project is available on GitHub if you would like to take a closer look at it. As always, please leave a comment or get in touch if you’d like to provide some input!

3 replies on “JavaScript Unit Tests in a Phoenix Application”

Is there any way to configure “mix test” to run BOTH the original “mix test” and “npm test” and && the exit codes?

Sure. You can set up aliases in mix.exs (see the example)

defp aliases do
  ["test": [&run_npm_test/1, "test"]]
end

defp run_npm_test(_) do
  {_, status} = System.cmd "npm", ["test"],
    into: IO.stream(:stdio, :line)

  if status > 0 do
    Mix.raise ~s("npm test" failed with status #{status})
  end
end

Note that this won’t run them in parallel.

Leave a Reply to Keita Kobayashi Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.