Как протестировать classList.add / remove с помощью Jest?

Не обращая внимания на использование этого вообще, как я могу протестировать такую ​​функцию:

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

Конечно, я могу создать элемент DOM и проверять свойство className после каждого вызова toggleClass, но как я могу проверить, был ли вызван classList.ad/remove? Я пробовал устанавливать такие фиктивные функции:

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

но это просто дает следующее сообщение об ошибке:

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)

Мне не хватает понимания Jest или концепции тестирования, или это просто невозможно?


person RSeidelsohn    schedule 28.08.2017    source источник
comment
Передайте фиктивный элемент DOM: { classList: { contains: jest.fn(), remove: jest.fn(), add: jest.fn() } }   -  person Or B    schedule 28.08.2017
comment
Это настолько очевидно, что я прочитал это - большое спасибо!   -  person RSeidelsohn    schedule 28.08.2017


Ответы (1)


Вот законченное решение, основанное на комментарии @Or B:

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');
  });
});

Результат модульного тестирования с отчетом о 100% покрытии:

 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

Исходный код: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/45918386.

person slideshowp2    schedule 27.09.2019