React v16、Enzyme v3
昨日から日本に来てます。
さて、炎上の末にライセンスがMITになったReactのv16がリリースされたと同時期に、Enzymeもv3がリリース。v3からsetupに変化がありました。
Working with React 16.x · Enzyme
説明とおりにしたけど動かねー。CSSセレクターで引っ掛けてたパターンが全滅。@types/enzymeはエラー、さらにはReact本体も警告だしている。
Warning: React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers. http://fb.me/react-polyfills
React 16 JavaScript Environment.md · GitHub
いろいろ読んで解決しました。
requestAnimationFrameの対処
// package.json部分 "jest": { "moduleFileExtensions": [ "ts", "tsx", "js" ], "setupFiles": [ "raf/polyfill", "./tools/enzyme.setup.js" ], "transform": { "^.+\\.(ts|tsx)$": "./node_modules/ts-jest/preprocessor.js" }, "testMatch": [ "**/__tests__/*((Test|Spec)\\.(ts|tsx))" ] },
yarn add raf -D をしたあとで、package.jsonのjest.setupFilesに、raf/polyfillを追加すると警告は消える。rafはレガシーブラウザでrequestAnimationFrameを埋めるライブラリ。JsDOMがEnzymeの依存で入ってくる古いものだったので、試みに最新に上げてもみましたが、このrequestAnimationFrameは手当しないとダメだった。
@types/enzymeの対処
node_modulesの中の@types/enzymeを見ると、自身の腹にnode_modules/@types/reactを抱え込んでいた。これが悪影響するので抱え込んでるnode_modulesを削除で、問題解決。デプロイのミスかな?
Enzyme v3へのマイグレーション
Migration from 2.x to 3.x · Enzyme
まず説明されてることとして、Jest起動時に走らせるsetupでEnzymeのアダプターなるものを導入する。
// ./tools/enzyme.setup.js // Enzyme v3かつJsDOM v11 var Enzyme = require('enzyme'); var Adapter = require('enzyme-adapter-react-16'); Enzyme.configure({ adapter: new Adapter() }); const { JSDOM } = require('jsdom'); const jsdom = new JSDOM('<!doctype html><html><body></body></html>'); const { window } = jsdom; function copyProps(src, target) { const props = Object.getOwnPropertyNames(src) .filter(prop => typeof target[prop] === 'undefined') .map(prop => Object.getOwnPropertyDescriptor(src, prop)); Object.defineProperties(target, props); } global.window = window; global.document = window.document; global.navigator = { userAgent: 'node.js', }; copyProps(window, global);
「the internal implementation of enzyme has been almost completely rewritten.」とのことですが説明されていたことは私の問題には関係なく、調べて見ると次と同じ現象?
テスト対象のノードを取りやすくするために、id="0"、id="1"、...、id="7"とidに数字を使ってたのですが、form.find('#0')とすると爆発。これはidをid="zero"、id="one"、...、id="seven"と文字で振り直して、form.find('#zero')とすればOK。その後にIDは数字で始まっちゃダメなルールだということをスレッドで教わりました。v2まで通ってたほうがバグでv3で修正されたとの結論。
Reactライクライブラリ
EnzymeのアダプターはReactの各バージョンの挙動の違いに対応するものを整理したと同時に、将来はReactライクライブラリの対応もしたいとのことが書いてありました。PreactやInfernoってこのマイグレーションガイドで初めてしりましたが面白そう。material-uiやreact-routerなどエコシステムのこともあるので近日の現実解ではないけど、JSX変換や基本的なAPIのところをカバーして差し替え可能にするというのはこのEnzymeだけでなく、TypescriptやBabelにもすでにあるので将来無謀なことではないように思います。