Writing tests with Mocha and jsdom
Mocha is a testing framework built in Node. To start using its command line interface, install it globally via $ npm install -g mocha
. Then, you can run the example tests in the repo like this:
$ cd /path/to/repo/jsxquery-demo
$ npm test
This runs every test written in the test
directory. You can run just those tests in a single file if you want, too:
$ npm test test/main_menu_spec.js
Setting up a DOM within Node using jsdom
If you take a look at that main_menu_spec.js
file, you will notice that those two blocks for 'when user is logged in'
and 'when user is not logged in'
contain before
hooks.
It's thanks to these that the global variables $
and window
available in your tests. Now, you can use jQuery to interact with the DOM just like you would in the browser!
test/main_menu_spec.js
// ...
describe('Main menu navigation component', () => {
describe('when user is logged in', () => {
before((done) =>
setupDom(<MainMenu {...user.userIsLoggedIn} />, done)
);
// ...
});
});
That setupDom()
function uses jsdom to render markup from a component MainMenu
. Those props are made up of some pre-written test data.
Now we can write tests for our component without opening up a browser or anything! Jsdom is especially nice because it's lightweight, and much faster than similar tools like Selenium or PhantomJS.
Writing assertions
Tests are made up of assertions. A little library called expect makes the process of writing assertions really simple.
Testing for the presence of an element in the DOM
Since we have our window
and jQuery available in our tests now, we can use basic jQuery to test for the presence of an element.
test/main_menu_spec.js
// ...
describe('Main menu navigation component', () => {
describe('when user is logged in', () => {
// ...
it('displays welcome message', () => {
expect($('#welcome-message').length).toEqual(1)
});
});
});
We can run $ npm test
and watch this pass because MainMenu
contains an element with the id 'welcome-message'
.
$ npm test
...
Main menu navigation component
when user is logged in
✓ displays welcome message
...
Testing for the absence of an element in the DOM
However, MainMenuComponent
is only supposed to render '#welcome-message'
if its prop
userIsLoggedIn
is true
. To test this behavior, we set up a new DOM with MainMenuComponent
and different test data.
test/main_menu_spec.js
describe('Main menu navigation component', () => {
// ...
describe('when user is not logged in', () => {
before((done) =>
setupDom(<MainMenu {...user.userIsNotLoggedIn} />, done)
);
// ...
});
});
In this block, we're using the object userIsNotLoggedIn
instead of userIsLoggedIn
from our pre-written test data. Now, the prop
userIsLoggedIn
is set to false
, meaning the element should not render. Sure enough, this test passes, too.
$ npm test
...
Main menu navigation component
when user is logged in
✓ displays welcome message
...
when user is not logged in
✓ does not display welcome message
...
More advanced testing
The repo is set up with examples for more complex tests, including tests for jQuery event handlers/DOM manipulation. Notice the code in the tests is just ordinary jQuery! Once you understand the basics of the Mocha/expect APIs, you can use your existing jQuery skills to set up automated tests that can do in seconds what would take you minutes. Take a moment to explore the examples and you'll see what I mean.