Nuxt3 + Vuetify + vitest環境をDockerで構築する

# はじめに
前回書いた記事の続きのメモ[1]
Nuxt3のテスト環境をDockerで構築するのが最終目的。
その際にlocalで作ったテスト環境をGitHubにcommitして、
Dockerfileから`npm install`で`package.json`から作るのが早いのでは?
と思ったのでまずはlocalテスト環境構築のメモを残す。


# 内容

## Nuxt3プロジェクトの作成
Nuxtの公式に乗っているコマンド
```sh
// プロジェクト作成
npx nuxi@latest init <project-name>

// vitest関連のインストール
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
```

## Vuetify
Vuetiryのインストール
```sh
npm i -D vuetify vite-plugin-vuetify
npm i @mdi/font
```

`nuxt.config.ts`をプロジェクトのルートに作成

```typescript:nuxt.config.ts
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
export default defineNuxtConfig({
  //...
  build: {
    transpile: ['vuetify'],
  },
  modules: [
    (_options, nuxt) => {
      nuxt.hooks.hook('vite:extendConfig', (config) => {
        // @ts-expect-error
        config.plugins.push(vuetify({ autoImport: true }))
      })
    },
    //...
  ],
  vite: {
    vue: {
      template: {
        transformAssetUrls,
      },
    },
  },
})
```
`~/plugins/vuetify.ts`を作成
ここまでで、Vuetifyが使えるようになるはず。
```typescript:~/plugins/vuetify.ts
// import this after install `@mdi/font` package
import '@mdi/font/css/materialdesignicons.css'

import 'vuetify/styles'
import { createVuetify } from 'vuetify'

export default defineNuxtPlugin((app) => {
  const vuetify = createVuetify({
    // ... your configuration
  })
  app.vueApp.use(vuetify)
})

```

# vitest
`vitest.config.ts`を作成
必要なものは最初にインストール済み
```typescript:vitest.config.ts
/// <reference types="vitest" />

import { defineConfig } from "vite";
import Vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [Vue()],
  test: {
    globals: true,
    environment: "happy-dom",
  },
});
```

# テスト
以下のファイルをプロジェクトに追加して `npx vitest`
passedと出れば完成！

```vue:~/components/HelloMessage.vue
<template>
  <div>Hello, {{ name }}!</div>
</template>

<script lang="ts" setup>
    defineProps<{
      name: string;
    }>();
</script>
```
```vue:~/pages/index.vue
<template>
  <div>
    <HelloMessage :name="name" />
    <p>
      <input type="text" v-model="name" />
    </p>
  </div>
</template>

<script setup lang="ts">
    import { ref } from "vue";
    const name = ref("World");
</script>
```

```typescript:~/tests/components/HelloMessage.spec.ts
import { describe, test, expect } from "vitest";
import { mount } from "@vue/test-utils";
import HelloMessage from "../../components/HelloMessage.vue";

describe("HelloMessage", () => {
  test("メッセージが表示される", () => {
    const wrapper = mount(HelloMessage, {
      props: {
        name: "World",
      },
    });
    expect(wrapper.text()).toContain("Hello, World!");
  });
});
```

## package.json
```json:package.json
{
  "name": "nuxt-app",
  "private": true,
  "type": "module",
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare"
  },
  "dependencies": {
    "@mdi/font": "^7.4.47",
    "nuxt": "^3.11.2",
    "vue": "^3.4.21",
    "vue-router": "^4.3.0"
  },
  "devDependencies": {
    "@nuxt/test-utils": "^3.12.0",
    "@nuxtjs/vuetify": "^1.12.3",
    "@types/node": "^20.12.6",
    "@vue/test-utils": "^2.4.5",
    "happy-dom": "^13.10.1",
    "playwright-core": "^1.43.0",
    "vite-plugin-vuetify": "^2.0.3",
    "vitest": "^1.4.0",
    "vuetify": "^3.5.14"
  }
}
```

# Docker環境で構築追記 2024/04/10
```Dockerfile:Dockerfile
FROM node:20

WORKDIR /TestNuxt3 # ディレクトリに関しては作成したプロジェクトフォルダ名を記載

ENV PATH /TestNuxt3/node_modules/.bin:$PATH

COPY ./TestNuxt3/package*.json ./

# cleanしないとinstallするpackageが多すぎてタイムアウトする
RUN npm cache clean --force && \
    npm install -g npm@latest && \
    npm install
```

```docker:docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    volumes:
      - ./TestNuxt3:/TestNuxt3 # 環境に合わせて変更
      - /TestNuxt3/node_modules # 環境に合わせて変更
    working_dir: /TestNuxt3 # 環境に合わせて変更
    ports:
      - "127.0.0.1:3000:3000" # 環境に合わせて変更
```

```sh
# docker-compose.ymlがあるディレクリで以下実行
docker compose build 
docker compose up -d 

# コンテナ内で以下実行
npm run dev
```

フォルダ構成
```sh
|
├─TestNuxt3
├─docker-compose.yml
├─Dockerfile
└─.gitignore
```

# 最後に
Docker環境でも構築できたらこの記事に追記するか別記事で出します。
https://github.com/motoo1789/Nuxt3_vitest_Example

# 参考文献
1. [TypeScript + Jestをdocker環境で構築する](https://qiita.com/motoo1789/items/3a2dd746cc49fd431215)
1. [Nuxt Testing](https://nuxt.com/docs/getting-started/testing)
1. [Get started with Vuetify3](https://vuetifyjs.com/en/getting-started/installation/)