Files
zulip/docs/testing/testing-with-node.md
Steve Howell ae92ec2b57 node docs: Simplify and fix node docs.
This is a first pass at fixing node docs.  This commit eliminates
some text that is either obsolete or just overly confusing, and
it fixes some of the code samples to reflect how the API has
evolved in the last couple years.  We also prominently tell
you how to run the tests.
2018-04-17 17:52:19 -07:00

119 lines
3.5 KiB
Markdown

# JavaScript unit tests
As an alternative to the black-box whole-app testing, you can unit test
individual JavaScript files.
You can run tests as follow:
```
tools/test-js-with-node
```
The JS unit tests are written to work with node. You can find them
in `frontend_tests/node_tests`. Here is an example test from
`frontend_tests/node_tests/stream_data.js`:
```
(function test_get_by_id() {
stream_data.clear_subscriptions();
var id = 42;
var sub = {
name: 'Denmark',
subscribed: true,
color: 'red',
stream_id: id
};
stream_data.add_sub('Denmark', sub);
sub = stream_data.get_sub('Denmark');
assert.equal(sub.color, 'red');
sub = stream_data.get_sub_by_id(id);
assert.equal(sub.color, 'red');
}());
```
The names of the node tests generally align with the names of the
modules they test. If you modify a JS module in `static/js` you should
see if there are corresponding test in `frontend_tests/node_tests`. If
there are, you should strive to follow the patterns of the existing tests
and add your own tests.
## Coverage reports
You can automatically generate coverage reports for the JavaScript unit
tests like this:
```
tools/test-js-with-node --coverage
```
If tests pass, you will get instructions to view coverage reports
in your browser.
Note that modules that
we don't test *at all* aren't listed in the report, so this tends to
overstate how good our overall coverage is, but it's accurate for
individual files. You can also click a filename to see the specific
statements and branches not tested. 100% branch coverage isn't
necessarily possible, but getting to at least 80% branch coverage is a
good goal.
## Handling dependencies in unit tests
The following scheme helps avoid tests leaking globals between each
other.
You want to categorize each module as follows:
- Exercise the module's real code for deeper, more realistic testing?
- Stub out the module's interface for more control, speed, and
isolation?
- Do some combination of the above?
For all the modules where you want to run actual code, add statements
like the following toward the top of your test file:
> zrequire('util');
> zrequire('stream_data');
> zrequire('Filter', 'js/filter');
For modules that you want to completely stub out, please use a pattern
like this:
> set_global('page_params', {
> email: 'bob@zulip.com'
> });
>
> // then maybe further down
> page_params.email = 'alice@zulip.com';
Finally, there's the hybrid situation, where you want to borrow some of
a module's real functionality but stub out other pieces. Obviously, this
is a pretty strong smell that the other module might be lacking in
cohesion, but that code might be outside your jurisdiction. The pattern
here is this:
> // Import real code.
> zrequire('narrow');
>
> // And later...
> narrow.stream = function () {
> return 'office';
> };
## Creating new test modules
The test runner (`index.js`) automatically runs all .js files in the
`frontend_tests/node directory`, so you can simply start editing a file
in that directory to create a new test.
The nodes tests rely on JS files that use the module pattern. For example, to
test the `foobar.js` file, you would first ensure that code like below
is at the bottom of `foobar.js`:
> if (typeof module !== 'undefined') {
> module.exports = foobar;
> }
This means `foobar.js` follow the CommonJS module pattern, so it can be
required in Node.js, which runs our tests.