javascript unit testing
TRANSCRIPT
Unit Testing JavaScript
Keir Bowden CTO, BrightGen @bob_buzzard
Unit Tests – They’re not just for Apex
• Introduction
• Tools
• Visualforce
• Lightning Components
• Q & A
What we’ll cover
Introduction
Why write unit tests
• Give confidence
• Reduce cost of bugs
• Produce testable code
• Promote refactoring
Introduction
No test context for client
• Changes aren’t rolled back
Side effects
• DOM manipulation
• Server calls
ChallengesJavaScript on Salesforce
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; }....
Github: bobbuzz.me.uk/JSUTSF
Public Site
• Jobs:
• bobbuzz.me.uk/1Ad25OG
• Tests:
• bobbuzz.me.uk/1PvhII3
Demo App
Tools
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
Module – group of tests
Test – single test
Assert – confirm behaviour
ConceptsQUnit
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");
Pure JavaScript
Works with any test framework
Three key concepts
• Spies – records execution, parameters
• Stubs – Spies + replace functions
• Mocks – Stubs + expected behaviour
Sinon.JS
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);
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>
Blanket.JS
Visualforce
Dedicated test page
Replicate markup as required
Include JavaScript to be tested
Can capture coverage
Demo
Visualforce
Lightning Components
Components are isolated
JavaScript in controller + helper
Cannot capture coverage
Markup is fixed
How to trigger tests?
ChallengesLightning Components
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
Unobtrusive JavaScript
Functional decomposition
Avoid anonymous functions
No client-side test contextStubs are your best friend
Takeaways
Q & A
Keir Bowden CTO, BrightGen @bob_buzzard