Testing a Javascript function that writes to the DOM
It is generally easy to test a simple javascript function like the one below that has no access to the DOM:
function sum(numberOne, numberTwo) {
return numberOne + numberTwo;
}
I am going to do a basic demonstration of testing another function that writes to the DOM. It’s going to be based still on the calculator function above, but this time, it returns answer and inserts in the DOM. We shall make sure through testing that the DOM receives the answer. The live demo of project we’ll work on as well as github repo is below:
Live demo → https://bit.ly/39L0BOA
Github repo → https://github.com/shloch/DOM_testing_tutorial
This small project is built with ES6, managed with Webpack (read how to setup here), testing is done with Jest.
My “src/” folder has 03 files :
function sum(numberOne, numberTwo) {
return numberOne + numberTwo;
}
export default sum;
- displayAnswer.js
(collects form data, calculates sum and display answer to DOM, inside the HTML tag with id=notification. This is what we shall mainly test)
import sum from './calculator'; const displayAnswer = () => {
const notification = document.querySelector("#notification");
const numberOne = +document.querySelector("#numberOne").value;
const numberTwo = +document.querySelector("#numberTwo").value;
const answer = sum(numberOne, numberTwo);
notification.innerHTML = `The sum is = ${answer}`;
}
export default displayAnswer;
just contains the submission button (#addBtn) with an event listener waiting to be clicked before addition begins. It’s the entry point file for webpack too ;)
import displayAnswer from './displayAnswer';const addBtn = document.querySelector("#addBtn");
addBtn.addEventListener("click", displayAnswer);
I got a test folder with one test file :
- calculator.test.js
import displayAnswer from '../src/displayAnswer';
import sum from '../src/calculator';beforeEach(() => {
document.body.innerHTML = `
<div id="calculator">
<h3 id="notification"></h3>
<input type="number" value="5" name="numberOne" id="numberOne" />
+
<input type="number" value="3" name="numberTwo" id="numberTwo" />
<button id="addBtn">GET ANSWER</button>
</div>`;
});//-----test1---------------
test('Ensure SUM function works', () => {
expect(sum(2, 3)).toBe(5);
expect(sum(10, 1)).toBe(11);
expect(sum(-2, 6)).toBe(4);
});//------test2--------------
describe('Testing that Result displays in DOM', () => {
test('Check answer Notification', () => {
const notification = document.querySelector('#notification');
displayAnswer();
expect(notification.innerHTML).toEqual("The sum is = 8");
});
});
A clone of the DOM is copied into test file
Notice the beforeEach() of the test file contains a copy of the DOM structure. Remember our test file is ran via a console, so it wont have access to a browser. So we’ll reproduce the DOM structure of our HTML file (Click here to see original HTML file).
Also notice that the inputs (of the beforeEach() function) are preloaded with values (5 and 3). We’re therefore expecting into the DOM a display of the text:
“The sum is = 8”
So before Each of the tests (test1 + test2) that follows is run, the DOM structure will be reproduced.
test1 ←is a test of the simple javascript function of the calculator.js file
test2 ←is the test of the sum being displayed into the DOM (our virtual DOM to be precised), after calling displayAnswer() function from the displayAnswer.js file.
Running the test:
Dont forget to visit the Github repo, for the entire project-folder structure.
You need to clone project locally, install npm packages, run webpack and open file into your browser. You can also just test the live demo above :)
The command to run the test :
npm run test
Test result:
Hope this helps more than one person ;)