Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test classList.add/remove using Jest?

Tags:

jestjs

Disregarding the use of doing it at all, how can I test a function like that:

export const toggleClass = (elementDOM, className) => {
  if (elementDOM.classList.contains(className)) {
    elementDOM.classList.remove(className);
  } else {
    elementDOM.classList.add(className);
  }
};

I can, of course, create a DOM element and check the className property after each call of toggleClass, but how can I test if classList.ad/remove has been called? I've tried setting mock functions like this:

const addSpy = jest.fn();
const removeSpy = jest.fn();
Element.prototype.classList = {
  add: addSpy,
  remove: removeSpy
};

but this just yields the following error message:

TypeError: Cannot read property 'classList' of undefined

  at Node.get [as classList] (node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/generated/Element.js:450:46)
  at Object.<anonymous> (app/Resources/scripts/helper/utils.test.js:23:37)
  at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
  at process._tickCallback (internal/process/next_tick.js:109:7)

Am I lacking understanding of Jest or the concept of testing or is this just not feasible?

like image 503
RSeidelsohn Avatar asked Feb 25 '26 23:02

RSeidelsohn


1 Answers

Here is the completed solution based on @Or B's comment:

index.ts:

export const toggleClass = (elementDOM, className) => {
  if (elementDOM.classList.contains(className)) {
    elementDOM.classList.remove(className);
  } else {
    elementDOM.classList.add(className);
  }
};

index.spec.ts:

import { toggleClass } from '.';

describe('toggleClass', () => {
  const mockedElementDOM = { classList: { contains: jest.fn(), remove: jest.fn(), add: jest.fn() } };

  it('should remove the class', () => {
    const className = 'a';
    mockedElementDOM.classList.contains.mockReturnValueOnce(true);
    toggleClass(mockedElementDOM, className);
    expect(mockedElementDOM.classList.remove).toBeCalledWith('a');
  });

  it('should add the class', () => {
    const className = 'a';
    mockedElementDOM.classList.contains.mockReturnValueOnce(false);
    toggleClass(mockedElementDOM, className);
    expect(mockedElementDOM.classList.add).toBeCalledWith('a');
  });
});

Unit test result with 100% coverage report:

 PASS  src/stackoverflow/45918386/index.spec.ts
  toggleClass
    ✓ should remove the class (4ms)
    ✓ should add the class (1ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.575s, estimated 9s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/45918386

like image 182
slideshowp2 Avatar answered Mar 03 '26 01:03

slideshowp2



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!