0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[vitest]Vuetify を Vitest(Vue 3)でテストする

Last updated at Posted at 2025-03-23

この記事でやること

  • Vitest で Vuetify のコンポーネントを使ったテストが動くようにする
  • vitest-setup.ts を作って、共通のテスト設定をまとめる

はじめに

Vue 3 のアプリで Vuetify を使っているコンポーネントをテストしようとした時、何にも考えずテストを書いたところ、こんなエラーが出てきたところが始まりでした。

TypeError: Unknown file extension ".css" for /usr/src/node_modules/vuetify/lib/directives/ripple/VRipple.css

ふむふむ.cssなんて知らないぞと・・・
そこから少し手間取ってしまったので奮闘記として残します!

まずは全体

テスト全体でVuetifyが使えるようにvitest-setup.tsを作成

vitest-setup.ts(Vuetify用セットアップファイル)
import { config } from "@vue/test-utils";
import ResizeObserver from "resize-observer-polyfill";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";

// Vuetifyインスタンスを作成
const vuetify = createVuetify({
	components,
	directives,
});

// Vue Test Utilsのglobal設定にプラグインとして追加
config.global.plugins = (config.global.plugins || []).concat([vuetify]);

// ResizeObserverのpolyfill
window.ResizeObserver = ResizeObserver;

vitest.config.tssetupFilesinlineの項目を追加し作成ファイルを指定

vitest.config.ts(vitest用セットアップファイル)
import { fileURLToPath } from "node:url";
import { configDefaults, defineConfig, mergeConfig } from "vitest/config";
import viteConfig from "./vite.config";

export default mergeConfig(
	viteConfig,
	defineConfig({
		test: {
			environment: "jsdom",
			exclude: [...configDefaults.exclude, "e2e/**"],
			root: fileURLToPath(new URL("./", import.meta.url)),
			globals: true,
			setupFiles: ["./vitest-setup.ts"], // 追加
			server: { // 追加
				deps: {
					inline: ["vuetify"],
				},
			},
		},
	}),
);

このようなレイアウト用コンポーネントのテストを想定

TestPage.vue(対象コンポーネント)
<script setup lang="ts">
const props = defineProps({
  testText: {
    type: String,
    default: "test1234",
  },
});
</script>

<template>
  <v-app-bar> hogehoge </v-app-bar>
  <v-main>
    <v-container>
      <h1>{{ testText }}</h1>
    </v-container>
  </v-main>
  <v-footer app color="primary"> fugafuga </v-footer>
</template>
TestPage.spec.ts(テストファイル)
import { mount } from "@vue/test-utils";
import { describe, expect, it } from "vitest";
import TestPage from "../TestPage.vue";

describe("testComponent", async () => {
	it("should render", async () => {
		const wrapper = mount({
			template: "<v-layout><TestPage :test-text='testText'/></v-layout>",
			components: {
				TestPage,
			},
			props: {
				testText: "test123",
			},
		});
		expect(wrapper.html()).toContain("test123");
	});
});

1. configファイルに追記

公式を見てみたところvuetifyの依存関係をインライン化しなきゃということで、テスト用のconfigファイルvitest.config.tsに設定を追加する模様。

vitest.config.ts
  test: {
    globals: true,
    environment: 'jsdom',
    server: {
      deps: {
        inline: ['vuetify'],
      },
    },
  },
})

2. ResizeObserverパッケージ追加

公式ドキュメントにも書かれていますが、jsdom では ResizeObserver がサポートされていないため、別途パッケージを追加します。

npm install resize-observer-polyfill --save-dev

3. いざテスト

テストの対象はVuetifyのレイアウト用のコンポーネントなども使っているものです。

<script setup lang="ts">
const props = defineProps({
  testText: {
    type: String,
    default: "test1234",
  },
});
</script>

<template>
  <v-app-bar> hogehoge </v-app-bar>
  <v-main>
    <v-container>
      <h1>{{ testText }}</h1>
    </v-container>
  </v-main>
  <v-footer app color="primary"> fugafuga </v-footer>
</template>

こんな感じでテスト!
JSDOM 環境でvite-plugin-vuetifyautoImport: true 設定は動かないようなので、componentsdirectivesを全てインポートします。

import { mount } from "@vue/test-utils";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
const vuetify = createVuetify({
	components,
	directives,
});
global.ResizeObserver = require("resize-observer-polyfill");

describe("testComponent", async () => {
	it("should render", async () => {
		const wrapper = mount(testComponent, {
			props: {
				testText: "test123",
			},
			global: {
				plugins: [vuetify],
			},
		});
		expect(wrapper.html()).toContain("test123");

残念ながらこのままではエラーとなりました。
レイアウト用コンポーネントなどは公式サイトに記載通りv-layoutでラップする必要がありました。

Error: [Vuetify] Could not find injected layout

ということで、v-layoutでラップします。

const wrapper = mount(
    {
        template: "<v-layout><TestPage :test-text='testText'/></v-layout>",
        components: {
            TestPage,
        },
        props: {
            testText: "test123",
        },
    },
    {
        global: {
            plugins: [vuetify],
        },
    },
);
expect(wrapper.html()).toContain("test123");

これで無事テスト成功しました👏👏👏

image.png

4. vitest-setup.ts を作成

テストが作成出来るようになりましたが、毎回createVuetifyplugins: [vuetify]を記述するのは少々面倒。
そこで、以下の内容をvitest-setup.tsに切り出します。

  • Vuetify のコンポーネント・ディレクティブを読み込み
  • Vue Test Utils の config.global.plugins に vuetify を追加
  • ResizeObserverにresize-observer-polyfillを設定
vitest-setup.ts
import { config } from "@vue/test-utils";
import ResizeObserver from "resize-observer-polyfill";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";

// Vuetifyインスタンスを作成
const vuetify = createVuetify({
	components,
	directives,
});

// Vue Test Utilsのglobal設定にプラグインとして追加
config.global.plugins = (config.global.plugins || []).concat([vuetify]);

// ResizeObserverのpolyfill
window.ResizeObserver = ResizeObserver;

作成したファイルをvitest.config.tssetupFilesとして設定します。

vitest.config.ts
import { fileURLToPath } from "node:url";
import { configDefaults, defineConfig, mergeConfig } from "vitest/config";
import viteConfig from "./vite.config";

export default mergeConfig(
	viteConfig,
	defineConfig({
		test: {
			environment: "jsdom",
			exclude: [...configDefaults.exclude, "e2e/**"],
			root: fileURLToPath(new URL("./", import.meta.url)),
			globals: true,
			setupFiles: ["./vitest-setup.ts"], // 追加
			server: {    // 追加
				deps: {
					inline: ["vuetify"],
				},
			},
		},
	}),
);

これで、Vuetifyを使ったコンポーネントも簡単にテスト出来るようになりました。

終わりに

  • やっと少しずつVueに慣れてきました
  • 今後もテストなど少しずつ残していきます
0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?