メインコンテンツへスキップ
Version: Next

DOM 操作

Another class of functions that is often considered difficult to test is code that directly manipulates the DOM. 以下の jQuery のコードスニペットをどうテストするのか見てみましょう。 displayUser.jsはクリックイベントをリッスンしてデータを非同期に取得し、 span のコンテンツにそのデータをセットします。

displayUser.js
'use strict';

const $ = require('jquery');
const fetchCurrentUser = require('./fetchCurrentUser.js');

$('#button').click(() => {
fetchCurrentUser(user => {
const loggedText = 'Logged ' + (user.loggedIn ? 'In' : 'Out');
$('#username').text(user.fullName + ' - ' + loggedText);
});
});

テストファイルは __tests__/ フォルダ以下に作成します。

__tests__/displayUser-test.js
'use strict';

jest.mock('../fetchCurrentUser');

test('displays a user after a click', () => {
// Set up our document body
document.body.innerHTML =
'<div>' +
' <span id="username" />' +
' <button id="button" />' +
'</div>';

// This module has a side-effect
require('../displayUser');

const $ = require('jquery');
const fetchCurrentUser = require('../fetchCurrentUser');

// Tell the fetchCurrentUser mock function to automatically invoke
// its callback with some data
fetchCurrentUser.mockImplementation(cb => {
cb({
fullName: 'Johnny Cash',
loggedIn: true,
});
});

// Use jquery to emulate a click on our button
$('#button').click();

// Assert that the fetchCurrentUser function was called, and that the
// #username span's inner text was updated as we'd expect it to.
expect(fetchCurrentUser).toHaveBeenCalled();
expect($('#username').text()).toBe('Johnny Cash - Logged In');
});

我々はテストコード上で実ネットワーク経由でリクエストが発行されることなく、その代わりにモックデータをローカルで取得して解決するように fetchCurrentUser.js をモックしています。 これは我々のテストが秒単位でなくミリ秒単位で完了し、素早くユニットテストが繰り返されることを保証してくれます。

テスト対象の関数は #button DOM 要素に対してイベントリスナーを追加しているので、テストにおいても DOM を正しく用意してあげる必要があります。 jsdomjest-environment-jsdom パッケージは、あたかもブラウザ内で実行しているような DOM 環境をシミュレートします。 これは我々が呼び出すあらゆる DOM API がブラウザで監視されているのと同じように監視されていることを意味します!

JSDOM テスト環境を使い始めるには、jest-environment-jsdom パッケージをインストールする必要があります。

npm install --save-dev jest-environment-jsdom

The code for this example is available at examples/jquery.