4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DOM操作するライブラリの非公開関数もrewireとJestでユニットテストしたいよ〜

Posted at

問題

JS/TSで公開されてない関数(non-exported function)のテストはrewireを使えばできるんですが、その関数内でDOM操作をしてるとき、documentundefinedcreateElement()なんてないぞ!と怒られるんですよね。

解決

はい! jest-environment-jsdom-global〜〜!!

端的に言うと、これを使えばJestが提供するJSDOMインスタンスにアクセスできるので、それをライブラリへ伝えることができるんですよね。

もうちょっと詳しく言うと、jest-environment-jsdom-globalはJestが標準で使っているjest-environment-jsdomを継承してJSDOMインスタンスを露出させただけのものです。

次の例はnodeToDOM()というDOM操作する非公開関数をテストしたものです。

myModule.spec.tsx
import rewire from 'rewire'
import { JSDOM } from 'jsdom'
declare var jsdom: JSDOM

describe('myModule', (): void => {
  const myModule = rewire('../dist')
  myModule.__set__('document', jsdom.window.document.defaultView.document)
  const nodeToDOM = myModule.__get__('nodeToDOM')

  it('nodeToDOM()', (): void => {
    const node = <meta name="description">Meta</meta>

    const el = document.createElement('meta')
    el.setAttribute('name', 'description')
    el.textContent = 'Meta'

    expect(nodeToDOM(node)).toStrictEqual(el)
  })
})

ポイントはmyModule.__set__()ですね。ここでライブラリ内グローバル変数documentにJSDOMの提供するものを当てています。

windowが必要ならばjsdom.window.document.defaultViewを、というように必要なものを適宜割り当ててください。

import { JSDOM } from 'jsdom'declare var jsdom: JSDOMはJavaScriptのときは要りません。TypeScriptに「jsdomなんていうグローバル変数なんて無いぞ!」と怒られないように付けています。

おまけ

サンプルコードはTypeScriptですが、rewire@types/rewireをインストールして、TS→JS変換後のモジュール(dist/index.js)をrewire()するだけで動きました!

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?