waltzio/waltz — pull request #281 by josephwegner (2014-01-27 21:01:21+00:00)
Title: Mocha unit tests

There's a lot to talk about here. The architecture is a little bit weird, so everyone who's interested should look over it before we officially merge. I've bounced back and forth a number of times between testing frameworks this weekend, and I don't want to change it again. Let's do this right from now on.

# Why
Previously we were using jasmine for our unit tests. @jessepollak had set them up to run in the browser, which is the standard flow for jasmine tests. I wanted to be able to run unit tests on our CI, Travis, which meant they needed to run outside of a browser. I ended up using a PhantomJS solution that ran the tests in a headless browser on Travis' server.

That all worked fine, until I started running into certain pain spots. Specifically, the one that put me over the edge is that `delegate` depends on `navigator.online`, which Phantom defaults to `false`. Setting `navigator.online` to true manually caused Webkit to think it was online, which resulted in everything blowing up.

At this point I realized that there were going to be gross hacks to get our tests running one way or another, and we might as well do them the *less* gross way. To me, that means dumping anything that resembles a headless browser.

And I like Mocha more than jasmine, so there's that.

# Architecture
As usual, mocha specs are just .js files stored in `/test`. Technically, naming conventions don't matter, but I think it's best to name them as `Spec.js` - see `cryptoSpec.js` as an example.

## Helpers

There is a folder called `helpers`. This folder can contain anything that will be useful to most specs. Currently, everything in there are polyfills for things that commonly exist in the browser. I'm trying to do the bare minimum in recreating the structure of browser objects like `chrome` and `location`.

## Eval Loading Vendor Resources
In `cryptoSpec.js` you will see this gross line:

eval(fs.readFileSync(__dirname+'/../static/js/vendor/aes.js')+''); global.CryptoJS = CryptoJS;

This is a technique that should allow us to load vendor JS files. The reason we have to do this is that Node's standard module system - `require` - only works if the modules utilizes `module.exports`. Obviously, browser js files won't do that. This eval thing lets us grab the raw JS and execute it in the spec's scope. You can see that on the end of the line I'm moving the vendor JS into the global scope manually, so that Waltz libraries can access them.

### A Word on jQuery
For those of you that are exceedingly attentive, you're probably wondering why I'm using a helper to load in jQuery, rather than eval-loading. For some reason, when I tried to eval jQuery I got some errors about `createElement` getting called on objects that don't exist. It's as if it was parsing the jQuery file wrong and running some commands that should really be inside functions. So, I created a helper class instead. DEAL WITH IT.

## Exporting Waltz Classes
I've started to add this snippet to the bottom of each of our classes:

```js
if(typeof(module) === "object" && typeof(module.exports) === "object") {
module.exports = Crypto;
}
```

That should not break anything in the browser, and will allow us to do a standard Node.js `require` to load in the Waltz libraries.

---

Please let me know if you guys like this structure, have any additions/subtractions, or general comments. As I said, I want to do this right, and not worry about testing architecture ever again. Testing needs to be an important part of our development, and I want it to be as painless as possible.