執筆時点で、Nuxt3 がリリースされてから約 2 ヶ月程度が立ちました。
Nuxt: The Intuitive Web Framework
Build your next Vue.js application with confidence using Nuxt. An open source framework under MIT li...
今回はタイトルの通り、以下の技術スタックで環境構築していきます。
- Nuxt3
- Vuetify3
- Vitest
- Vue Testing Library
インストール
まずは Nuxt3 のインストールから始めます。
npx nuxi init nuxt3-app
続いて、Vuetify3 のインストールを行います。
npm i -D vuetify@next vite-plugin-vuetify sass
その他、テストで利用する Vitest や Vue Testing Library 関連もインストールしてしまいましょう!
npm install -D vitest @testing-library/vue happy-dom
サンプルコンポーネントの作成
今回は、Vuetify のコンポーネントを利用してテストを行うため、サンプルコンポーネントを作成します。
// components/Button.vue
<template>
<v-app>
<v-btn @click="onClick">
{{ label }}
</v-btn>
</v-app>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
props: {
label: String,
},
name: "Sample",
setup() {
const onClick = () => {
console.log("clicked");
};
return { onClick };
},
});
</script>
nuxt.config.ts のセットアップ
nuxt.config.ts
を作成し、以下のように記述します。
import { defineNuxtConfig } from "nuxt/config";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
css: ["vuetify/lib/styles/main.sass"],
build: {
transpile: ["vuetify"],
},
vite: {
define: {
"process.env.DEBUG": false,
},
},
});
Vitest のセットアップ
vitest.config.ts
を作成し、以下のように記述します。
Vitest で Vuetify を利用するためには、vite-plugin-vuetify
も必要になります。
// vitest.config.ts
/// <reference types="vitest" />
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vuetify from "vite-plugin-vuetify";
import { fileURLToPath, URL } from "node:url";
export default defineConfig({
plugins: [
{
name: "vitest-plugin-beforeall",
config: () => ({
test: {
setupFiles: [
fileURLToPath(new URL("./vitest/beforeAll.ts", import.meta.url)),
],
},
}),
},
vue(),
vuetify({
autoImport: true,
// styles: { configFile: './src/styles/variables.scss' },
}),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./", import.meta.url)),
"~": fileURLToPath(new URL("./", import.meta.url)),
},
},
test: {
root: ".",
globals: true,
globalSetup: [fileURLToPath(new URL("./vitest/setup.ts", import.meta.url))],
environment: "happy-dom",
deps: {
inline: ["vuetify"],
},
},
});
plugins/vuetify.ts
も作成し、以下のように記述します。
// plugins/vuetify.ts
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";
export default defineNuxtPlugin(nuxtApp => {
const vuetify = createVuetify({
components,
directives,
});
nuxtApp.vueApp.use(vuetify);
});
続いて、/vitest/beforeAll.ts
と/vitest/setup.ts
を作成します。
これがないと、css.supports
でエラーが発生するためです。
// /vitest/beforeAll.ts
import { beforeAll } from "vitest";
(global as any).CSS = { supports: () => false };
beforeAll(() => {
global.CSS = {
supports: (str: string) => false,
escape: (str: string) => str,
};
});
// /vitest/setup.ts
export async function setup() {
global.CSS = {
supports: (str: string) => false,
escape: (str: string) => str,
};
}
テストコードの作成
テストコードを実装していきますが、Testing Library に Vuetify をマウントする必要があるため、まずはrenderWithVuetify
というカスタムラッパーの関数を用意します。
// renderWithVuetify.ts
import { render } from "@testing-library/vue";
import { createVuetify } from "vuetify";
const vuetify = createVuetify({
// vuetifyの設定を必要に応じて記述
});
const renderWithVuetify: typeof render = (component, options) => {
const root = document.createElement("div");
root.setAttribute("data-app", "true");
return render(component, {
container: document.body.appendChild(root),
global: {
plugins: [vuetify],
},
...options,
});
};
export default renderWithVuetify;
重要になるのはrender
関数のオプションで用意しているglobal.plugins
キーで、ここに Vuetify を読み込ませる必要があります。
global: {
plugins: [vuetify],
},
Vue2 の場合、以下 testing-library が用意していたコードサンプルを元に実装していましたが、Vue3 の場合は上記のようにglobal.plugins
キーを利用する必要があります。
自分が探す限り、どこにもそのようなサンプルコードがなかったので結構時間を取られてしまいました。。
vue-testing-library/vuetify.js at main · testing-library/vue-testing-library
🦎 Simple and complete Vue.js testing utilities that encourage good testing practices. - vue-testing...
そしてコンポーネントテスト用のファイルを作成します。
// components/Button.spec.ts
import { describe, it, expect } from "vitest";
import { fireEvent } from "@testing-library/vue";
import customRender from "@/customRender";
import Button from "./index.vue";
const props = {
label: "Test Text",
};
describe("Button", () => {
it("should render correctly", () => {
const { getByRole } = customRender(Button, {
props,
});
expect(getByRole("button")).toBeTruthy();
});
it("should emit click event", () => {
const { getByText } = customRender(Button, {
props,
});
fireEvent.click(getByText(props.label));
});
});
テストの実行
最後に、package.json
にテストコマンドを追加します。
{
"scripts": {
"test": "vitest"
}
}
以下実行して、テストが通ることを確認します。
npm run test
✓ components/Button.spec.ts (2)
Test Files 1 passed (1)
Tests 2 passed (2)
Start at 13:43:41
Duration 3.21s (transform 1.76s, setup 62ms, collect 1.30s, tests 47ms)
無事テストが通りました!
今回作成した環境をリポジトリにアップしましたので、参考にしてみてください。
GitHub - hsmon/nuxt3-vuetify-vitest-testing-library
Contribute to hsmon/nuxt3-vuetify-vitest-testing-library development by creating an account on GitHu...
参考させていただいたリンク集
https://codybontecou.com/how-to-use-vuetify-with-nuxt-3.html
https://future-architect.github.io/articles/20210614b/
https://github.com/logue/vite-vuetify-ts-starter
https://qiita.com/MS-0610/items/a16670713de929a5b9b1