w3resource

DOM Manipulation


In this tutorial we are going to demonstrate how to perform DOM manipulation with Jest. As you already know users of every application wants a way to receive a response based on a defined request.

Codes that manipulate the DOM is another class of function that is often considered difficult to test. Let us see how we can test the following snippet of jQuery code that will listen to a click event, fetch some data asynchronously and then set the content of a span.

// displayUser.js

'use strict';

const $ = require('jquery');
const fetchCurrentUser = require('./fetchCurrentUser.js');

$('#button').click(() => {
  fetchCurrentUser(user => {
    const loggedText = 'Logged ' + (user.loggedIn ? 'In' : 'Out');
    $('#username').text(user.fullName + ' - ' + loggedText);
  });
});

Again, we have to create a test file in the __tests__/ folder:

// __tests__/displayUser-test.js

'use strict';

jest.mock('../fetchCurrentUser');

test('this will display a user after a click', () => {
  // this will set up our document body
  document.body.innerHTML =
    '<div>' +
    '  <span id="email" />' +
    '  <button id="button" />' +
    '</div>';

  // The module has a side-effect
  require('../displayUser');

  const $ = require('jquery');
  const fetchCurrentUser = require('../fetchCurrentUser');

  // Tells the fetchCurrentUser mock function to automatically invoke
  // the callback with some data
  fetchCurrentUser.mockImplementation(cb => {
    cb({
      fullName: '[email protected]',
      loggedIn: true,
    });
  });

  // Uses jquery to emulate a click on our button
  $('#button').click();

  // Asserts that the fetchCurrentUser function was called, and that the
  // #email span's inner text was updated as we'd expect it to.
  expect(fetchCurrentUser).toBeCalled();
  expect($('#email').text()).toEqual('[email protected] - Logged In');
});

The function that is being tested will add an event listener on the #button DOM element, so we have to set up our DOM correctly for the test. Jest comes with jsdom which will simulate a DOM environment as if you were in the browser. What this means is that every DOM API that we call can be observed in the same way it would be observed in a browser!

We will be mocking fetchCurrentUser.js so that our test does not make a real network request but instead will resolve to mock data locally. This will ensure that our test can complete in milliseconds rather than seconds and will guarantee a fast unit test iteration speed.

Using the email to mock is not a rule, you can use the username if that is what you prefer to use, here is an implementation of DOM manipulation using the username as the mock parameter:

// __tests__/displayUser-test.js

'use strict';

jest.mock('../fetchCurrentUser');

test('this will display a user after a click', () => {
  // this will set up our document body
  document.body.innerHTML =
    '<div>' +
    '  <span id="username" />' +
    '  <button id="button" />' +
    '</div>';

  // The module has a side-effect
  require('../displayUser');

  const $ = require('jquery');
  const fetchCurrentUser = require('../fetchCurrentUser');

  // Tells the fetchCurrentUser mock function to automatically invoke
  // the callback with some data
  fetchCurrentUser.mockImplementation(cb => {
    cb({
      fullName: 'Yuksek Galip',
      loggedIn: true,
    });
  });

  // Uses jquery to emulate a click on our button
  $('#button').click();

  // Asserts that the fetchCurrentUser function was called, and that the
  // #username span's inner text was updated as we'd expect it to.
  expect(fetchCurrentUser).toBeCalled();
  expect($('#username').text()).toEqual('Yuksek Galip - Logged In');
});


Inviting useful, relevant, well-written and unique guest posts