Slide deck for my Unit Testing JavaScript talk given at London's Calling and the London Salesforce Developer's February Meetup. Includes links to the demo application and Github repository.
4. Why write unit tests
• Give confidence
• Reduce cost of bugs
• Produce testable code
• Promote refactoring
Introduction
5. No test context for client
• Changes aren’t rolled back
Side effects
• DOM manipulation
• Server calls
Challenges
JavaScript on Salesforce
6. Unobtrusive JavaScript
Avoid anonymous functions
Functional decomposition
• Function to decide on action
• Function to take the action
Writing Testable Code
function redirectToURL(url) {
if (“#”===url.charAt(0)) {
window.location.hash=url;
} else if (“/”===url.charAt(0))
window.location.pathname=url;
}
....
9. Pure JavaScript Unit Test Framework
Executes in-browser
From the developers of jQuery
QUnit
<apex:includeScript
value="{!$Resource.qunitJS}"/>
<apex:stylesheet
value="{!$Resource.qunitCSS}"/>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
Test markup container
10. Module – group of tests
Test – single test
Assert – confirm behaviour
Concepts
QUnit
QUnit.module("JOBLIST", {
beforeEach: function(assert) {
// setup code
},
afterEach : function(assert) {
// teardown code
}
});
QUnit.test("Show Progress", function( assert ) {
jobCtrl.showProgress();
});
assert.equal(jobCtrl.progressCount, 1,
"Progress count is one");
11. Pure JavaScript
Works with any test framework
Three key concepts
• Spies – records execution, parameters
• Stubs – Spies + replace functions
• Mocks – Stubs + expected behaviour
Sinon.JS
12. Sinon Stub
this.searchStub = sinon.stub(jobCtrl,
"doSearch");
var jobCtrl={
doSearch : function(ev) {
// remote call to server
}
};
jobCtrl.doSearch(event);
doSearch : function() {
// sinon stub code
}
assert.equal(this.searchStub.callCount,1,
"search called once");
this.searchStub.restore();
doSearch : function(ev) {
// remote call to server
}
$('#searchbtn').on("click",
jobCtrl.doSearch);
13. Code coverage!
Pure JavaScript
Works with QUnit, Mocha and Jasmine
JavaScript must be external
Blanket.JS
<apex:includeScript value="{!$Resource.blanketJS}"/>
<script src="{!$Resource.JobsJS}" data-cover="true"></script>
18. Components are isolated
JavaScript in controller + helper
Cannot capture coverage
Markup is fixed
How to trigger tests?
Challenges
Lightning Components
19. Qunit tests in helper function
• Controller method to execute helper function
Lightning test application (page equivalent)
Tests executed via event
• Fired by application
• Handled by component under test
Demo
My Solution!
Lightning Components