Имитация клика по документу ReactJS/JSDom
Итак, я пишу несколько тестов для кода, который добавляет событие клика в документ. Я использую JSDom, ReactJS и Mocha/Chai. Я пробовал следующий код в тесте:
document.addEventListener('click', function() {
console.log('test');
});
React.addons.TestUtils.Simulate.click(document);
//also tried React.addons.TestUtils.Simulate.click(document.body);
однако этот код не вызывает ожидаемое эхо.
Есть ли способ имитировать щелчок, клавиатуру и т.д. в документе с помощью JSDom и ReactJS?
UPDATE
Ответ Ник, я попытался добавить этот код к тесту:
document.body.addEventListener('click', function() {
console.log('test');
});
document.body.click();
и я до тех пор, пока не получаю вывод журнала консоли. Я не уверен, есть ли какая-то проблема с JSDom и делаю такие вещи.
Если я не могу unit test этот код, это хорошо, уже есть код, который я не могу unit test прямо сейчас (код, для которого требуется реальная DOM, чтобы получить ширину, высоту и т.д...) но я хотел бы иметь возможность unit test большей части кода (и я не заинтересован в использовании PhantomJS для модульного тестирования). Мои интеграционные тесты будут охватывать этот тип кода.
UPDATE2
Другое дело, что при я console.log(document);
я вижу объект, привязанный к свойству _listeners
для click
, поэтому я знаю, что событие привязано, оно просто не выполняется.
Ответы
Ответ 1
Обновление: document.body.click
будет работать в браузере, но для jsdom вам нужно вручную создать событие:
document.body.addEventListener('click', function() {
console.log('test');
});
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, true);
document.body.dispatchEvent(evt)
Вышеприведенный код работает для меня в Jest и должен работать с "solo" jsdom.
Осень 2018 праздник обновления 🦃
Инструменты вокруг симуляции событий стали намного лучше. В настоящее время я переместил свой подход, чтобы использовать отличную библиотеку для тестирования реакции, чтобы отображать мои компоненты и события отправки:
import {render, fireEvent} from 'react-testing-library'
test('example', () => {
const handleClick = jest.fn()
const {getByText} = render(<div><button onClick={handleClick}>Click Me</button></div>)
fireEvent.click(getByText('Click Me'))
expect(handleClick).toHaveBeenCalled()
})
Хотя я все еще верю в тесты конца до конца с чем-то вроде кукловода или селена (или кипариса!), Обеспечивает наивысший уровень уверенности в том, что что-то действительно работает, это обеспечивает огромную ценность без загрязняющих тестов с ручным созданием события.
Ответ 2
React.addons.TestUtils.Simulate работает только с виртуальными событиями. Если вы хотите отправлять собственные события, вы можете сделать это непосредственно с помощью DOM api.
При имитации щелчка, если у вас есть компонент, который делает это:
<div>
<button onClick={alert}>click me</button>
</div>
И у вас есть ссылка на <button/>
в переменной с именем 'buttonEl' и запустите это:
React.addons.TestUtils.Simulate.click(buttonEl, 'hello world');
Вы получите предупреждение с "hello world" в нем. Все тестовые утилиты - это создание виртуального события, и пусть оно пузырится вверх по виртуальному дереву dom, вызывая обработчики событий на этом пути.
Ответ 3
Просто создайте Event
и отправьте его:
// Add an event listeners to the document
document.addEventListener('click', function() {
console.log('test');
});
// Create a new `click` event and `dispatch` it
var event = new MouseEvent('click')
document.dispatchEvent(event)
Ответ 4
Event.initEvent()
устарело, и вместо этого должен использоваться конструктор Event()
.
// Add a click event listener to the document
document.addEventListener('click', function() {
console.log('test');
});
// Create a click event with optional event initialisers: bubbles, cancelable and composed
var evt = new Event('click', { bubbles: false, cancelable: false, composed: false });
// Event can then be dispatched against any element, not only the document
document.dispatchEvent(evt);
myDiv.dispatchEvent(evt);
Поддержка браузера хороша, за исключением Internet Explorer.
Рекомендации: