Next.js & jestのプロジェクトにvanilla-extract & esm形式のライブラリを採用しました。
その際にunit testで引っかかった問題の備忘録です。
環境
Next.js: 14.1.0
jest: 29.1.2
node: 21.4.0
environment: jest-environment-jsdom
esm対応
エラー内容
./node_modules/some-library/components/button/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { Button } from './button';
^^^^^^
SyntaxError: Unexpected token 'export'
https://jestjs.io/ja/docs/ecmascript-modules
jestはesmを実験的サポートしているものの、node_modules配下はトランスパイルされないので
transformIgnorePatternsに対象のライブラリ(foo-library)を追加する必要あり。
ただし普通に設定してもnext/jestはその設定を上書きしてしまうので、nextJest後に無理やり置き換える。
また、node_modulesに適用させるためbabelの設定ファイルを.babelrcではなく.babel.config.jsに変更する必要がある。
import nextJest from 'next/jest';
const createJestConfig = nextJest({
dir: './',
});
/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig: Config = {
// 省略
};
module.exports = async () => ({
...(await createJestConfig(customJestConfig)()),
transformIgnorePatterns: [
'node_modules/(?!(foo-library)/)',
],
});
vanilla-extract対応
エラー内容
Styles were unable to be assigned to a file. This is generally caused by one of the following:
- You may have created styles outside of a '.css.ts' context
- You may have incorrect configuration. See https://vanilla-extract.style/documentation/getting-started
at Object.getFileScope (node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.cjs.dev.js:35:11)
https://vanilla-extract.style/documentation/integrations/next/
公式の設定手順を試すも反映されず。
https://vanilla-extract.style/documentation/test-environments/#remove-style-mocking
追加でmoduleNameWrappersからcssへのstyleMock.jsの設定を削除。
ただし、こちらもesm同様にnext/jestに上書きされてしまったので最後に上書き。
また、その際に自プロジェクトのcss(my-css-folder)のみは従来通りのstyleMock.jsを適用するよう設定。
import nextJest from 'next/jest';
const createJestConfig = nextJest({
dir: './',
});
/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig: Config = {
// 省略
};
module.exports = async () => {
const config = await createJestConfig(customJestConfig)();
if (config.moduleNameMapper) {
const backupModuleNameMapper = config.moduleNameMapper['^.+\\.(css|sass|scss)$'];
delete config.moduleNameMapper['^.+\\.(css|sass|scss)$'];
config.moduleNameMapper['my-css-folder/.+\\.css$'] = backupModuleNameMapper;
}
config.transform = {
'\\.css\\.[tj]s$': '@vanilla-extract/jest-transform',
...config.transform
};
return config;
};
以上で動作は確認できました。
ただ何分強引なやり方なのでもう少しスマートな対応も模索していきたいと思います。