🍣
Next.js+TypeScript環境でJestを設定してテストをする
Next.js+TypeScript環境でのJestを使ったテスト設定です。
テストユーティリティーはreact-domに同封されているものだけを使用します。
DOMイベントに反応するだけの簡単なコンポーネントのテストをしてみます。
インストール
npm install --save-dev jest @types/jest ts-jest
設定
jest.config.js
module.exports = {
preset: 'ts-jest',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/spec/tsconfig.json'
}
}
}
spec/tsconfig.json
{
"extends": "../tsconfig.json",
"include": ["./**/*"],
"compilerOptions": {
"jsx": "react-jsx"
}
}
Next.jsのjsx
コンパイラオプションはpreserve
となっています。
これをテスト用はreact-jsx
に設定します。
react-jsx
React17から入った新しいJSX変換です。
TypeScriptは4.1からjsx
コンパイラオプション
react-jsx
react-jsx-dev
の追加で対応されています。
これによりいつものimport文が必要なくなりました。
Next.js環境でjsx
がpreserve
であっても、テスト用にBabelを使用しなくても良いのです。
// さよなら
import React from 'react'
イベントのテストとスナップショットテスト
このようなコンポーネントをテストしたいと思います。
import { useState } from 'react'
export const Ababababa = () => {
const [title, setTitle] = useState<string>('Stay Calm')
const onMouseEnter = () => setTitle('あばばばば')
const onMouseLeave = () => setTitle('あばっ')
return (
<h1 {...{onMouseEnter,onMouseLeave}}>
{title}
</h1>
)
}
スナップショットテストにします。
import { render } from 'react-dom'
import { act } from 'react-dom/test-utils'
import { Ababababa } from '../../components/Ababababa'
describe('あばばばば', () => {
let container: HTMLDivElement
beforeEach(() => {
document.body.appendChild(container = document.createElement('div'))
})
afterEach(() => {
document.body.removeChild(container)
})
it('should Stay Calm', () => {
render(<Ababababa />, container)
expect(container.innerHTML).toMatchSnapshot()
})
it('should あばばばば', () => {
act(() => {
render(<Ababababa />, container)
})
act(() => {
container.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }))
container.children[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true, cancelable: true }))
})
expect(container.innerHTML).toMatchSnapshot()
})
it('should あばっ', () => {
act(() => {
render(<Ababababa />, container)
})
act(() => {
container.children[0].dispatchEvent(new MouseEvent('mouseout', { bubbles: true }))
container.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }))
})
expect(container.innerHTML).toMatchSnapshot()
})
})
Reactのイベントハンドリングの仕様の関係で onMouseEnter
, onMouseLeave
, に対して mouseover
, mouseout
イベントを発火しています。(ここではまりました)
テストを実行するとスナップショットが作成されるので確認してみます。
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`あばばばば should Stay Calm 1`] = `"<h1>Stay Calm</h1>"`;
exports[`あばばばば should あばっ 1`] = `"<h1>あばっ</h1>"`;
exports[`あばばばば should あばばばば 1`] = `"<h1>あばばばば</h1>"`;
期待通りの出力なので、次回のテストからマウスイベントに対する出力がスナップショットと比較され正しいことを確認できます。
Next.jsにおけるテスト
pages以下のコンポーネントはテストが難しくなりがちなので、部品単位で単体テストを作成し、なるべく機能を保証していく形になりそうです。
Discussion
jest.config.jsonはjest.config.jsではないでしょうか?
ありがとうございます!
修正致しました。