更新日: 2024年12月30日
※Vitestのインストール手順に関しては以下を参照ください。
https://n-laboratory.jp/articles/nuxt3-vitest-unittest
・Nuxt 3.15.0
・Vitest 2.1.8
・puppeteer 23.7.1
・VeeValidate 4.15.0
1. Puppeteerをインストールします。
$ npm install puppeteer
1. VeeValidateをインストールします。
$ npm install --save-dev vee-validate @vee-validate/i18n @vee-validate/rules
2. pluginsディレクトリに vee-validate-plugin.ts を新規作成して以下の内容で保存します。
// src/plugins/vee-validate-plugin.ts
import { localize, setLocale } from '@vee-validate/i18n'
import ja from '@vee-validate/i18n/dist/locale/ja.json'
import { all } from '@vee-validate/rules'
import { defineRule, configure } from 'vee-validate'
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin((_nuxtApp) => {
configure({
generateMessage: localize({
// エラーメッセージの日本語化
ja,
}),
})
// すべてのルールをインポート
Object.entries(all).forEach(([name, rule]) => {
defineRule(name, rule)
})
// エラーメッセージの日本語化
setLocale('ja')
})
1. pages配下に form.vue を新規作成して以下の内容で保存します。
// src/pages/form.vue
<script lang="ts" setup>
import { Form, Field, ErrorMessage } from 'vee-validate'
const email = ref('')
const handleSubmit = (values: Record<string, string>) => {
email.value = values.email
}
</script>
<template>
<Form v-slot="{ meta }" data-testid="validation-form" @submit="handleSubmit">
<!-- バリデーション対象の項目 -->
<Field rules="required|email" name="email" as="input" type="text" data-testid="input-email" />
<!-- バリデーションエラーメッセージの表示 -->
<ErrorMessage name="email" data-testid="email-error-msg" />
<!-- meta.validは有効な値を入力された場合にtrueを返します -->
<button :disabled="!meta.valid" data-testid="submit-btn">
Submit
</button>
</Form>
<p>Result: {{ email }}</p>
</template>
2. Nuxt起動後に以下のURLにアクセスします。フォーム画面が表示されており、送信ボタンが非活性であることを確認します。
http://localhost:3000/form
3. 入力欄に「a」を入力します。エラーメッセージが表示されることを確認します。
4. 入力欄を空欄にします。エラーメッセージが表示されることを確認します。
5. 入力欄に「a@a.com」を入力します。送信ボタンが活性していることを確認します。
6. 送信ボタンをクリックします。Resultに「a@a.com」が表示されていることを確認します。
src
└── e2eTest
├── form.spec.ts ← テストファイル
└── xxx.png ← 各テストケースのスクリーンショット(エビデンス)
1. e2eTest配下に form.spec.ts を新規作成して以下の内容で保存します。
// src/e2eTest/form.spec.ts
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import { launch } from 'puppeteer'
import type { Browser, Page, PuppeteerLaunchOptions } from 'puppeteer'
// ブラウザの起動オプションの設定。使用できるパラメータに関しての詳細は以下を参照ください。
// https://pptr.dev/api/puppeteer.browserlaunchargumentoptions
const options: PuppeteerLaunchOptions = {
headless: false,
slowMo: 75,
defaultViewport: {
width: 1280,
height: 1024
},
devtools: true,
args: ['--window-size=1680,1024']
}
describe('form.vue', () => {
let browser: Browser
let page: Page
beforeAll(async () => {
browser = await launch(options)
page = await browser.newPage()
})
afterAll(async () => {
await browser.close()
})
describe('初期表示確認', () => {
test('1:フォーム画面が表示されること', async () => {
// Act
await page.goto('http://localhost:3000/form')
await page.waitForNavigation({ timeout: 5000, waitUntil: 'domcontentloaded' })
// スクリーンショット(エビデンス)の撮影
await page.screenshot({
path: './src/e2eTest/test1.png',
fullPage: true
})
// Assert
const existsPage = await page.$eval(
'[data-testid="validation-form"]',
element => !!element
)
expect(existsPage).toBe(true)
}, 20000)
})
describe('バリデーションチェック', () => {
test.each([
[
2,
'不正なメールアドレスを入力した',
'abcABC0123456789',
'emailは有効なメールアドレスではありません'
],
[
3,
'未入力の',
'',
'emailは必須項目です'
]
])(
'%s:メールアドレスの入力フィールドに[%s]場合、エラーメッセージが表示されること',
async (
testNo,
description,
inputValue,
expectedErrorMsg
) => {
// Act
await page.type('input[data-testid="input-email"]', inputValue)
await page.keyboard.press('Tab')
await page.screenshot({
path: `./src/e2eTest/test${testNo}.png`,
fullPage: true
})
// エラーメッセージの取得
const errorMsg = await page.$eval(
'[data-testid="email-error-msg"]',
element => element.textContent
)
// Assert
expect(errorMsg).toBe(expectedErrorMsg)
// 入力した値をリセット
await page.click('input[data-testid="input-email"]', {
clickCount: inputValue.length
})
await page.keyboard.press('Backspace')
},
200000
)
})
describe('Submitボタンの活性/非活性状態確認', () => {
test('4:初期状態では送信ボタンが非活性であること', async () => {
// Act
await page.goto('http://localhost:3000/form')
await page.waitForNavigation({ timeout: 5000, waitUntil: 'domcontentloaded' })
await page.screenshot({
path: './src/e2eTest/test4.png',
fullPage: true
})
// Assert
const disabled = await page.$eval(
'[data-testid="submit-btn"]',
element => (element as HTMLButtonElement).disabled
)
expect(disabled).toBe(true)
}, 10000)
test('5:有効なメールアドレスを入力した場合、送信ボタンが活性であること', async () => {
// Act
await page.type('input[data-testid="input-email"]', 'test@test.com')
await page.keyboard.press('Tab')
await page.screenshot({
path: './src/e2eTest/test5.png',
fullPage: true
})
// Assert
const disabled = await page.$eval(
'[data-testid="submit-btn"]',
element => (element as HTMLButtonElement).disabled
)
expect(disabled).toBeFalsy()
// 入力した値をリセット
await page.click('input[data-testid="input-email"]', { clickCount: 13 })
await page.keyboard.press('Backspace')
}, 10000)
test('6:Submitボタンを押下した場合、Result欄にメールアドレスが表示されること', async () => {
// Act
await page.type('input[data-testid="input-email"]', 'test@test.com')
await page.click('[data-testid="submit-btn"]')
await page.screenshot({
path: './src/e2eTest/test6.png',
fullPage: true
})
// Assert
const result = await page.$eval(
'[data-testid="result"]',
element => element.textContent
)
expect(result).toBe('Result: test@test.com')
}, 10000)
})
})
2. package.jsonの「scripts」に以下を追加します。
{
"scripts": {
"dev": "nuxt dev",
"test:e2e": "vitest ./src/e2eTest",
},
}
3. テストを実行します。
$ npm run dev
$ npm run test:e2e
4. ブラウザが自動で起動し、テストが実行されることを確認します。
5. テスト終了後はブラウザが自動で終了し、テストが全件passしていることを確認します。
$ npm run test:e2e
> test:e2e
> vitest ./src/e2eTest
✓ src/e2eTest/form.spec.ts (6) 22161ms
✓ form.vue (6) 22161ms
✓ 初期表示確認 (1) 2192ms
✓ 1:フォーム画面が表示されること 2192ms
✓ バリデーションチェック (2) 7735ms
✓ 2:メールアドレスの入力フィールドに[不正なメールアドレスを入力した]場合、エラーメッセージが表示されること 5232ms
✓ 3:メールアドレスの入力フィールドに[未入力の]場合、エラーメッセージが表示されること 2503ms
✓ Submitボタンの活性/非活性状態確認 (3) 10850ms
✓ 4:初期状態では送信ボタンが非活性であること 1674ms
✓ 5:有効なメールアドレスを入力した場合、送信ボタンが活性であること 4683ms
✓ 6:Submitボタンを押下した場合、Result欄にメールアドレスが表示されること 4492ms
Test Files 1 passed (1)
Tests 6 passed (6)
以上で全ての手順は完了になります