- Intro to baseapp
- Client-Side Unit Tests
- Server-Side Unit Tests
- WebDriver Integration Tests
- Other Grunt Goodies
- Continuous Integration
Let's look at the configuration in the Gruntfile:
The output of these tests (in JUnit XML format) is dumped into the options.junit.path directory - one XML file per test suite.
Finally the grunt-template-jasmine-istanbul package is leveraged to generate code coverage information, the HTML output of which is dumped into the 'options.templateOptions.report' directory. We also persist the 'coverage.json' file so it can be aggragated later with other tests (like server-side unit tests and webdriver tests).
% grunt jasmine
Will run all of this stuff.
The most interesting bits are the fixture setup and the jQuery AJAX spy.
Jasmine-jquery and also load fixtures from a webserver, which is especially nice if you are using templates (which you are!), so you can test using your application's actual HTML. As these fixtures are very simple I did not do that here. Also beware of how the fixture loading interacts with jQuery's AJAX object which I will discuss with more detail next.
Jasmine is espcially nice for providing spies for interacting with your code's dependencies. The logout component relies on an AJAX call to actually log the user out, but while unit testing we do not have a web server running so we need to mock out the AJAX call. We do that using the "spyOn($, 'ajax')" function call.
All subsequent calls that use jQuery's AJAX mechanism will instead get routed to this spy, the underlying AJAX call will NOT get executed (note jasmine does provide a way to also call through to the actualy implementation but we do not want to do that here).
The spy allows us to verify the ajax method was called with the expect arguments. Spies let us do more than just verify arguments and call through to the real underlying implementation, take a look at loginSpec.js to see more!
Search for the 'andCallFake' method - using that method you can have the spied on method execute and return any code you like! Let's take a close look at the "should handle failure default response" test case.
First I set up the HTML fixture for this test, then I create the login component I will test along with some other canned values I will be using more than once so I DRM (Don't Repeat Myself). Now I create a spy for the $.ajax method and inform jasmine whenever that method is called to actually execute the given function instead. Note my function receives the argument list, and in this case I simply turn around and call the provided 'error' callback with some canned data to test that code path. I then set some form elements and 'submit' the form. As this is all synchronous the error callback will get called via 'andCallFake' and finally I expect the error message is being shown properly. Finally note the 'toHaveText' matcher came from jasmine-jquery, which comes chock full of lots of great jQuery-specific matches for us to leverage. Be sure to check them out.
So all of our client-side unit test files must reside in the spec/client directory and be named with the word 'Spec' in them - follow that pattern for your own sanity! As you create more component keep adding tests, they can be at any depth in the spec/client tree, jasmine will find them!
_SpecRunner.html and Debugging Tests
Test results are output in the JUnit XML format with pass/fail information and dumped to the build/reports/jasmine/ directory with one XML file per-suite. The most interesting thing about this format is its wide support.