1. 結論
再現できませんでした。。
以下の記事でまとめられていました。
- testing-library/user-eventはReactを想定して各イベントの発火処理をラップしています。
- ネイティブHTMLのchangeイベントは要素が確定したタイミングで発火します。
これは一般的にinput要素からフォーカスが外れたタイミングです。 - 一方ReactにおけるonChangedは要素の値が変更されたタイミングで発火されます。
2. 背景
業務でjestを使ってテストコードを書いています。
あるプロジェクトではノーフレームワークでソースは書いています。
そのプロジェクトでテストコードを書いている時にユーザのinput要素へのchangeイベントを再現する記述が冗長なので何か良い方法はないかなと考えていた為です。
ユーザのinput要素へのchangeイベントを再現する関数
const dispatchUserChangeEvent = (elm: Element, value: string) => {
if (!(elm instanceof HTMLInputElement)) {
console.error('elm is not HTMLInputElement');
return;
}
const inputElm = elm;
inputElm.value = value;
inputElm.dispatchEvent(new Event('change'));
};
testing-libraryの存在は知っていましたがネイティブHTMLでもテストできる*ことを知ったので、検証してみます。
*inputイベントを起こすことはできました。
後述するコードの
inputElement.addEventListener('change'
changeをinputに変えるだけで確認できます!
3. 検証
npm install @testing-library/user-event @testing-library/dom
以下のように実装しましたがchangeイベントを起こすことはできませんでした。
import { waitFor } from '@testing-library/dom';
import { userEvent } from '@testing-library/user-event';
const consoleLogMock = jest.spyOn(console, 'log').mockImplementation();
test('example test with jest-environment-dom', async () => {
// Create an input element and append it to the body
const inputElement = document.createElement('input');
inputElement.setAttribute('type', 'text');
document.body.appendChild(inputElement);
inputElement.addEventListener('change', () => {
console.log('input changed');
});
userEvent.type(inputElement, 'Hello, World!');
await waitFor(() => {
expect(consoleLogMock).toHaveBeenCalledWith('input changed');
});
});