Я немного пытаюсь найти решение о том, как проверить эту экспортированную функцию с помощью шутки.
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
});
});
Может ли кто-нибудь дать мне какие-либо советы о том, как тестировать код с этими зависимостями?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


scrollToError() — это асинхронная функция, и вы не можете вызвать ее и ожидать немедленного результата. Вам нужно подождать это количество мс (400 в вашем случае), прежде чем тестировать его.
Асинхронный код в Jest тестируется немного иначе: Тестирование асинхронного кода. Вы также можете использовать взять под контроль таймеры или объединить все это с ручные издевательства и переопределить сам jQuery.
Как вы используете 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...
Наконец-то мне удалось найти правильное решение. Я написал для него три тест-кейса:
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% покрытия для этого метода.
но как насчет jquery.. Я пытался найти способ издеваться над ним..