0
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?

[Vue×Jest]Vue 3 に Jest を導入してテスト環境を構築する

Posted at

Vue 3 に Jest を導入してテスト環境を構築する

はじめに

最近、業務で Vue.js を使う機会が増えてきたため、Vue 3 関連の記事も書いていこうと思います。今回は、Vue 3 で Jest を導入し、テスト環境を構築する方法をまとめます。

Vue の公式ドキュメントでは Vitest を推奨していますが、Jest との比較のために Jest を導入しようとしたところ、思いのほかハマってしまいました。これから Vue でテストを始める方の参考になれば幸いです。

対象

  • Vue でテストを導入したい方
  • Jest を使った Vue 3 のテスト環境構築方法を知りたい方

環境

  • Docker (image: node:22-bullseye)
  • MacOS (M3)

Jest の導入と設定

必要なライブラリをインストール

Jest を Vue 3 で使うために、以下のライブラリをインストールします。

npm install --save-dev jest ts-jest @vue/test-utils @vue/vue3-jest jest-environment-jsdom
パッケージ 役割
@vue/test-utils Vue コンポーネントのテストを行うためのライブラリ
jest JavaScript のテストランナー(v29)
ts-jest TypeScript を Jest で直接実行できるようにする
@vue/vue3-jest Vue 3 の .vue ファイルを Jest で実行できるようにする
jest-environment-jsdom Jest の実行環境を jsdom(ブラウザ風の環境)にする

Jest の設定詳細

以下の jest.config.js を作成し、Jest の設定を行います。

const config = {
  preset: "ts-jest", // TypeScript を Jest で実行するためのプリセット
  testEnvironment: "jsdom", // ブラウザ環境をエミュレートするために jsdom を使用
  moduleFileExtensions: ["vue", "js", "ts", "json"], // テスト対象のファイル拡張子
  transform: {
    "^.+\\.vue$": "@vue/vue3-jest", // .vue ファイルを変換するための設定
    "^.+\\.(js|ts)$": ["ts-jest", { isolatedModules: true }], // TypeScript/JavaScript を Jest で実行できるように変換
  },
  collectCoverage: false, // カバレッジ収集を無効化(必要に応じて true に変更)
  collectCoverageFrom: [
    "src/**/*.{js,ts,vue}",
    "!src/main.ts",
    "!src/router/**",
    "!node_modules/**",
  ],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1", // エイリアス `@` を `src/` にマッピング
  },
  testEnvironmentOptions: {
    customExportConditions: ["node", "node-addons"], // Node.js 環境向けの設定
  },
};

export default config;

Jest の動作を確認する

Jest は CommonJS で動作するため、Vue の .vue ファイルをテストする際には ① Vue → ② JavaScript (ESM) → ③ JavaScript (CommonJS) の 3 段階の変換 が必要になります。

① Vue ファイルを JavaScript (ESM) に変換

Vue の .vue ファイルは、HTML のテンプレート <template>、スクリプト <script>、スタイル <style> を含んだ特殊な形式です。
そのままでは JavaScript として実行できないため、@vue/vue3-jest を使って .vue ファイルを JavaScript に変換します。

変換前(Vue ファイル)
<template>
  <button @click="count++">{{ count }}</button>
</template>

<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
変換後(JavaScript / ESM)
import { ref } from 'vue';
export default {
  setup() {
    const count = ref(0);
    return { count };
  }
};

② JavaScript (ESM) を CommonJS に変換

Jest は CommonJS 形式で動作するため、JavaScript (ESM) の import / export を require / module.exports に変換する必要があります。これを ts-jest が担当します。

変換後(CommonJS)
const vue = require('vue');
module.exports = {
  setup() {
    const count = vue.ref(0);
    return { count };
  }
};

③ Jest が変換後のファイルを実行してテストを実行

ここまでの変換を経て、Jest は .vue ファイルを適切に解釈し、テストを実行できるようになります。

よくあるエラーと解決策

1. Cannot find module '../components/TestVueJest.vue' エラー

TypeScript を使っている場合、.vue ファイルを import しようとすると、
TypeScript も 「こんな拡張子のファイル知らないよ!」 となります。
その結果、次のようなエラーが出ます。

error TS2307: Cannot find module '../components/TestVueJest.vue' or its corresponding type declarations.

jest.config.jstransform 設定にisolatedModules: trueを追加し「単独の JavaScript ファイルとして変換すれば OK!」 と解釈してもらいエラーを回避します。

transform: {
  "^.+\\.vue$": "@vue/vue3-jest",
  "^.+\\.(js|ts)$": ["ts-jest", { isolatedModules: true }],
},

参考:GitHub Issue #4081

2. ReferenceError: Vue is not defined エラー

Vue 3 は ESM(ECMAScript Modules) で書かれていますが、Jest はデフォルトで CommonJS(CJS) 形式で動作します。そのため、Jest は Vue の import 文を適切に解釈できず、
「Vue って何?」 となってしまい、ReferenceError: Vue is not defined というエラーが発生することがあります。

jest.config.js に以下を追加して、Jest が Vue のエクスポートを解釈できるようにします。

testEnvironmentOptions: {
  customExportConditions: ["node", "node-addons"],
},

参考:Stack Overflow

終わりに

Vue の公式推奨は Vitest ですが、Jest を使いたい場合でもいくつk設定を行えば動作させることができそうです。
実際にテストを書いて行く中で、他にもエラーが出てくるかもしれないので、どうしても必要ということでなければVitestの方が良さそうという印象でした。

0
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
0
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?