LitでつくったWebComponentをJestでテストする
Lit(+TypeScript)でつくったWebComponentをJestでテストしたくなったので、行ったことをまとめておきます。
前提
- テストやコンポーネントはTypeScriptで記述
- ts-jestが導入済み
- Lit 2.0.0 / Jest 26系で動作確認
テストを書いてみる
以下のようなコンポーネントを定義したとします。
import { LitElement, html, css } from 'lit' import { property, customElement } from 'lit/decorators.js' @customElement('test-component') export class TestComponent extends LitElement { @property({type: String}) title = '' render() { return html` <div> <span>${title}</span> </div> `; } }
まずは JestのDOM操作に関するドキュメント を参考にテストを書いてみます。雰囲気はこんなかんじ。
// 以下のように読み込むことで @customElement decoratorによってコンポーネントが定義される import '~/src/TestComponent' // 型情報がほしいので別途TestComponentを読み込む import { TestComponent } from '~/src/TestComponent' test('Content should include a title', async () => { document.body.innerHTML = ` <test-component title="タイトル"></test-component> ` const component = document.getElementsByTagName('test-component')[0] as TestComponent // コンテンツが描画されるまで待つ await component.updateComplete // たとえばtitle attribute が正しくコンテンツに反映されていることを確認する expect(component.shadowRoot?.innerHTML.match(/タイトル/g)?.length).toEqual(1) })
Lit ドキュメントの Lifecycleの項 をみると、コンテンツの更新が完了すると updateComplete
PromiseがResolvedになるとあるので、コンテンツが更新されてからテスト項目を確認していきます(更新される前にテスト項目を確認すると、変更が反映されていない可能性があり、思うような実行結果が得られません)。
DOMの操作・取得の関数(たとえば Element.innerHTML
など)がテストでも使えるので、これを用いて actual な状態を確認していきます。
もし、 @customElement
decoratorを使わずにコンポーネントを定義している場合は、以下のようにテスト内で customElements.define()
を呼ぶことで同様にCustomElementを定義できます。
import { TestComponent } from '~/src/TestComponent' customElements.define('test-component', TestComponent) // 以下同じ
テスト中の document.getElementsByTagName
で取得した component
は TestComponent
をインスタンス化したものなので、メソッドやプロパティにアクセスすることもできます。TestComponent内の何かをモックしたい~みたいなこともできます。
テストを実行できるようにする
テストを実行してみると、以下のようなエラーが出てしまいます。
FAIL tests/TestComponent.test.ts ● Test suite failed to run Jest encountered an unexpected token This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript. By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules". Here's what you can do: • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it. • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config. • If you need a custom transformation specify a "transform" option in your config. • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option. You'll find more details and examples of these config options in the docs: https://jestjs.io/docs/en/configuration.html Details: /path/to/test-project/node_modules/lit/index.js:1 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import"@lit/reactive-element";import"lit-html";export*from"lit-element/lit-element.js"; ^^^^^^ SyntaxError: Cannot use import statement outside a module > 1 | import { LitElement, html, css } from 'lit' | ^
Lit ライブラリ内に import
文があるので、これをJestが解釈できずにエラーになっているようです。Jestはデフォルトでは node_modules
配下のファイルをトランスパイルしないので、
エラーメッセージにある通り transformIgnorePatterns
に手を加え、Lit関連ライブラリがトランスパイルされるようにします。
トランスパイルの対象はエラーメッセージのとおりjsファイルなので、 babel-jest
を使ってトランスパイルされるようにします。(必要に応じて @babel/preset-env
をインストールします)
JestのGetting Started を参考に、babel.config.js
を以下のように記述します。
module.exports = { presets: [ [ '@babel/preset-env', { targets: { node: 'current', }, } ] ] }
続いて、jest.config.js
を以下のように設定します。
- Jestドキュメントの例を参考に、
transformIgnorePatterns
を以下のように記述します- transformIgnorePatterns は「指定した正規表現にマッチするファイルはトランスパイルされないようにする」プロパティ
- tsファイルの場合は ts-jest、jsファイルの場合は babel-jest を使いたいので、ts-node Presets を参考に、presetに
ts-jest/presets/js-with-babel
を設定します
module.exports = { preset: 'ts-jest/presets/js-with-babel', transformIgnorePatterns: [ "/node_modules/(?!(@lit|lit|lit-element|lit-html)/)" ] }
これでテストを実行できるようになりました。めでたしめでたし。
(おまけ)Canvas要素を含むコンポーネントのテスト実行
CustomElementにCanvasに関する処理が含まれていた場合は、テストの実行に失敗することがあります。JestのDOM周りには jsdom が用いられていますが、READMEをみると Cavnas Support の項があります。 これによると、 node-canvs をインストールすればよいとのことなので試してみると、インストールして特に設定を変えることなく実行することができました。
LitのTestingの項 によると、Web Test Runner を使うのがおすすめだよ!と書いてあるので、これもおいおいさわってみよう~となっていました。ではでは~