LWC Debugging and Testing with Toronto Salesforce Developer Group
4 min readSep 25, 2020
At the Toronto, Canada, Salesforce Developer group, we spent a couple of hours today trying to learn LWC Debugging Techniques and Jest Testing.
We set ourselves below learning objectives.
- Explore Debugging Techniques
- Take a sample Lightning Web Components (LWC) and write some Jest tests.
Debugging Techniques Identified
- Local Development Server has limited debugging capability due to no proper source maps.
- Debugging on org can be done by setting breakpoints in code once we enable Lightning to run in the debug mode.
- Use the Sources tab in chrome and look under the lightning/page/modules/c folder to find your component.js file.
- Add JavaScript breakpoints to step through the code.
- We identified black boxing helps. We black-boxed a couple of Salesforce JavaScript files like aura_proddebug.js and scenarioTracker.js to make debugging easier.
- Also, make sure you turn on the custom formatter in chrome on so one can read the @api variables on the HTML template.
The component code
treeView.html
<template><lightning-card title={label}><lightning-tree items={items}></lightning-tree><lightning-button label=”Change Selected” onclick={handleClick}></lightning-button></lightning-card></template>
treeView.js
import {
api,
LightningElement
} from 'lwc';export default class TreeView extends LightningElement {
@api
label;items = [{
label: 'Western Sales Director',
name: '1',
expanded: true,
items: [{
label: 'Western Sales Manager',
name: '2',
expanded: true,
items: [{
label: 'CA Sales Rep',
name: '3',
expanded: true,
items: []
},
{
label: 'OR Sales Rep',
name: '4',
expanded: true,
items: []
}
]
}]
},
{
label: 'Eastern Sales Director',
name: '5',
expanded: false,
items: [{
label: 'Easter Sales Manager',
name: '6',
expanded: true,
items: [{
label: 'NY Sales Rep',
name: '7',
expanded: true,
items: []
},
{
label: 'MA Sales Rep',
name: '8',
expanded: true,
items: []
}
]
}]
},
{
label: 'International Sales Director',
name: '9',
expanded: true,
items: [{
label: 'Asia Sales Manager',
name: '10',
expanded: true,
items: [{
label: 'Sales Rep1',
name: '11',
expanded: true,
items: []
},
{
label: 'Sales Rep2',
name: '12',
expanded: true,
items: []
}
]
},
{
label: 'Europe Sales Manager',
name: '13',
expanded: false,
items: [{
label: 'Sales Rep1',
name: '14',
expanded: true,
items: []
},
{
label: 'Sales Rep2',
name: '15',
expanded: true,
items: []
}
]
}
]
}
];handleClick(e) {
const evt = new CustomEvent('treeclick', {
detail: {
node: 'xyz'
}
});
this.dispatchEvent(evt);
}
}
Writing Test Code
We use sfdx-lwc-jest npm module in our project dev-dependencies.
Writing test code was a breeze once we have scaffolded the project using the below command
sfdx force:lightning:lwc:test:create -f <folderpath>/force-app/main/default/lwc/treeView/treeView.js
We wanted to cover test for
- Verify Component DOM had rendered properly
- Verify that the component event was dispatched successfully with the right data. The trick here is you create a jest mock function using jest.Fn() and add as a listener so when the button is clicked the element can invoke a mock function instead.
- Also, we learned that when jest dispatches mock handler the handler has a mock property that has calls and results in an array to get information around arguments of the call and results of calls respectively.
- Check the JEST mock API here
jest test code
import {
createElement
} from 'lwc';
import TreeView from 'c/treeView';describe('c-tree-view', () => {afterEach(() => {
// The jsdom instance is shared across test cases in a single file so reset the DOM
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
});it('renders tree view component', () => {
const element = createElement('c-tree-view', {
is: TreeView
});
element.label = 'Roles';
document.body.appendChild(element);
const cardElement = element.shadowRoot.querySelector('lightning-card');
return Promise.resolve().then(() => {
expect(cardElement.title).toBe('Roles');
});
});it('renders tree view component with label', () => {
const element = createElement('c-tree-view', {
is: TreeView
});
element.label = 'hello';
document.body.appendChild(element);
const cardElement = element.shadowRoot.querySelector('lightning-card');
return Promise.resolve().then(() => {
expect(cardElement.title).toBe('hello');
});
});it('dispatches event on button click', () => {
const element = createElement('c-tree-view', {
is: TreeView
});
element.label = 'hello';
document.body.appendChild(element);
// Mock handler for toast event
const handler = jest.fn();
element.addEventListener('treeclick', handler);
const buttonElement = element.shadowRoot.querySelector('lightning-button');
buttonElement.click();
return Promise.resolve().then(() => {
expect(handler).toHaveBeenCalled();
expect(handler.mock.calls[0][0].detail.node).toBe('xyz');
});
});
});
Running the jest code
- Salesforce Extension pack in vscode has excellent support for running and debugging jest tests
- Use alpha version of vscode-jest extension from jest community to get code overlay.
- Getting coverage is also easy via command line using the below command
npm run test:unit:coverage
References
- Lightning stubs in sfdx-lwc-jest are found here
- Official Salesforce documentation on lwc jest testing
- Trailhead Module on jest
- Explore some awesome test coverage in lwc recipes app
- Official jest documentation for writing jest tests