Как протестировать метод с setTimeout и jquery с помощью jest

Я немного пытаюсь найти решение о том, как проверить эту экспортированную функцию с помощью шутки.

export const scrollToError = () => {
  setTimeout(() => {
    const hasErrorElement = jQuery('.has-error');
    if (!hasErrorElement.length) return;
    jQuery('html,body').animate({
      scrollTop: hasErrorElement.offset().top - 50,
    }, 'slow');
  }, 400);
};

Я импортировал его в свой тестовый файл и попытался запустить:

import { scrollToError } from './utils';

describe('Utils', () => {
  it('should scroll to error', () => {
    const result = scrollToError();
    expect(result).toBe(true); //added this just to force an error and got result as undefined 
  });
});

Может ли кто-нибудь дать мне какие-либо советы о том, как тестировать код с этими зависимостями?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
407
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

scrollToError() — это асинхронная функция, и вы не можете вызвать ее и ожидать немедленного результата. Вам нужно подождать это количество мс (400 в вашем случае), прежде чем тестировать его.

Асинхронный код в Jest тестируется немного иначе: Тестирование асинхронного кода. Вы также можете использовать взять под контроль таймеры или объединить все это с ручные издевательства и переопределить сам jQuery.

но как насчет jquery.. Я пытался найти способ издеваться над ним..

sergioviniciuss 13.02.2019 21:05

Как вы используете jQuery?

Я имею в виду, вы получили это с помощью npm или пряжи? для имитации node_modules вы можете перейти по этой ссылке: https://jestjs.io/docs/en/manual-mocks#mocking-node-modules

В противном случае вам придется создать макет вручную. Вы можете посмотреть, как это сделать здесь: https://jestjs.io/docs/en/manual-mocks

Обновлено:

самый простой способ — переопределить его при настройке теста в методе beforeXXX.

Вы можете просто поставить что-то вроде window.JQuery = jest.fn();

это самый простой макет, но вам придется создать такие методы, как animate и другие методы, связанные с jquery.

Подумав здесь и посмотрев на свою функцию, если вы издеваетесь над jQuery, что еще осталось протестировать?

Если вы издеваетесь, вы будете проверять, выполняет ли ваш fn шаги, которые вы определили здесь. Например, проверьте, был ли jQuery fn вызван с классом .has-error или animate получил правильные параметры.

Этот вид теста никак вам не поможет, он просто проверяет, следует ли он построчно вашему алгоритму. Проблема здесь в том, что вы можете сделать некоторые рефакторинги, такие как изменение имени класса .has-error или метода анимации на другой улучшенный.

Что вам действительно нужно изменить, если он делает в конце то, что должен делать. Отображение div или того, что должно отображаться. Если вы проверите это, независимо от того, как вы реорганизуете свой код, тест проверит, работает ли окончательное решение, и это важно.

Я был ясен? Английский не мой родной язык, поэтому он может немного сбивать с толку.

сложность здесь в том, чтобы создать для него ручной макет... я не использую его из node_modules...

sergioviniciuss 13.02.2019 21:20
Ответ принят как подходящий

Наконец-то мне удалось найти правильное решение. Я написал для него три тест-кейса:

jest.useFakeTimers();
describe('utils', () => {
  afterEach(() => {
    document.body.innerHTML = '';
  });
  it('ScrollToError - should run the settimeout for 400 ms', () => {
    scrollToError();
    expect(setTimeout).toHaveBeenCalledTimes(1);
    expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 400);
  });
  it('ScrollToError - should scroll to error', () => {
    document.body.innerHTML = formStep1ErrorMock;
    window.setTimeout = fn => fn();
    const result = scrollToError();
    expect(result).toBe(true);
  });
  it('ScrollToError - should do nothing as has no errors', () => {
    document.body.innerHTML = formStep1Mock;
    window.setTimeout = fn => fn();
    const result = scrollToError();
    expect(result).toBe(true);
  });
});

Итак, в основном, сначала я проверяю, был ли вызван setTimeout с правильным количеством секунд (не то чтобы это важно).

Затем я издеваюсь над setTimeout, делая это window.setTimeout = fn => fn();, чтобы он работал, не дожидаясь задержки. Я также издеваюсь над html с нужными мне деталями.

И, наконец, я просто расскажу о другом сценарии.

PS: Я добавил оператор return true в метод scrollToError, чтобы упростить получение ожидаемого результата.

Таким образом, я добился 100% покрытия для этого метода.

Другие вопросы по теме