Cloudflare Workers+Remixでのサーバー側ユニットテスト
調べてみたら意外と少ないので、実際にやってみる。今回のテストはサーバー側に絞るので、client側はまた今度にする。
下記ドキュメントに沿ってやる。
TypeScriptを使うならこちらとのこと
上記リポジトリのsrcの部分をappに変えてやればとりあえず動いた。
module.exports = {
testEnvironment: "miniflare", // ✨
// Tell Jest to look for tests in .mjs files too
testMatch: [
"**/?(*.)+(test).?(m)[tj]s?(x)",
],
preset: "ts-jest/presets/default-esm",
globals: {
"ts-jest": {
tsconfig: "test/tsconfig.json",
useESM: true,
},
},
moduleNameMapper: {
"^~/(.+)$": "<rootDir>/app/$1"
},
transform: {
"^.+\\.(ts|tsx)$": "ts-jest"
},
};
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["@cloudflare/workers-types", "jest"]
},
"include": ["../app/**/*", "**/*"]
}
"module": "./dist/session.server.mjs",
"type": "module",
"scripts": {
...
"test": "npm run build && node --experimental-vm-modules node_modules/jest/bin/jest.js"
...
}
Remixに関係する話だと、この記事が勉強になりそう。
今度はremixのbuildが通らない。
サブフォルダにpackage.jsonをコピーしてそこで「"type": "module"」を指定すればどうだろう。
下のような構成でremixのbuildと両立できた。
"test": "npm test --prefix test"
{
"name": "test",
"private": true,
"type": "module",
"scripts": {
"test": "node --experimental-vm-modules ../node_modules/jest/bin/jest.js"
}
}
ルートのpackage.jsonのnpm scriptsにて、--prefix test指定してtestフォルダのnpm scriptsを呼び出している。
注意点として、wrangler.tomlをtestフォルダ下にも置かないとbindingsが使えない。
また、jestのconfigもrootDirを変更した。
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(path.dirname(__filename));
export default {
...
rootDir: __dirname,
...
};
actionやloaderのテストは実行時間が長くなりそうなので、とりあえずもっと細かい単位のテストからやることにした。
MSWによるAPIモックはminiflare v2.6.0からになりそう。対応したら試してみる。
validator.jsを使っている箇所で SyntaxError: Cannot use import statement outside a moduleが出る。
どうもnode_modules内のものはESMとして認識されないみたい。
たとえば、node_modules内のisJWT.jsをisJWT.mjsに変更すれば問題ないようだけど、それではちょっとな。
調べた限りだとここが1番詳しそう。
こんな感じにしたらSyntaxErrorはなくなった(Windows環境)。
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.18.0",
"@babel/preset-env": "^7.18.0",
"babel-jest": "^28.1.0",
"cross-env": "^7.0.3",
"jest": "^28.1.0",
"ts-jest": "^28.0.2"
},
module.exports = {
plugins: ["@babel/plugin-transform-modules-commonjs"]
};
transform: {
".*\\.js$": "babel-jest"
},
transformIgnorePatterns: [
"node_modules/?!(validator/es)",
],
babelのせいか実行速度が遅いのが気になる。
swc-jestを使うことで実行時間が半分くらいになった。
npm i -D jest @swc/core @swc/jest --prefix test
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(path.dirname(__filename));
export default {
testEnvironment: "miniflare", // ✨
rootDir: __dirname,
testMatch: [
"**/?(*.)+(spec).?(m)[tj]s?(x)",
],
transform: {
".*\\.(t|j)sx?$": "@swc/jest",
},
transformIgnorePatterns: [
"node_modules/?!(validator/es)",
],
moduleNameMapper: {
"^~/(.+)$": "<rootDir>/app/$1",
},
};
requestが絡んだテストをするときはURLを指定する感じかな。