diff --git a/web/package.json b/web/package.json index a43e4c9..e7f0a91 100644 --- a/web/package.json +++ b/web/package.json @@ -6,13 +6,22 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "preview": "vite preview" + "preview": "vite preview", + "test": "vitest", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage" }, "devDependencies": { + "@testing-library/vue": "^8.1.0", "@vitejs/plugin-vue": "^5.2.4", + "@vitest/coverage-v8": "^2.1.8", + "@vue/test-utils": "^2.4.6", + "jsdom": "^25.0.1", + "msw": "^2.7.0", "sass": "^1.94.1", "typescript": "~5.9.3", - "vite": "^5.4.21" + "vite": "^5.4.21", + "vitest": "^2.1.8" }, "dependencies": { "@vueuse/core": "^14.0.0", diff --git a/web/src/__tests__/setup.ts b/web/src/__tests__/setup.ts new file mode 100644 index 0000000..77ee821 --- /dev/null +++ b/web/src/__tests__/setup.ts @@ -0,0 +1,15 @@ +import { vi, beforeEach, afterEach, beforeAll, afterAll } from 'vitest' +import { createPinia, setActivePinia } from 'pinia' + +// Use fake timers globally for consistent async testing. +vi.useFakeTimers() + +// Setup fresh Pinia instance for each test. +beforeEach(() => { + setActivePinia(createPinia()) +}) + +// Cleanup after each test. +afterEach(() => { + vi.clearAllMocks() +}) diff --git a/web/vitest.config.ts b/web/vitest.config.ts new file mode 100644 index 0000000..7b0f5e8 --- /dev/null +++ b/web/vitest.config.ts @@ -0,0 +1,27 @@ +import { defineConfig } from 'vitest/config' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + test: { + environment: 'jsdom', + globals: true, + setupFiles: ['./src/__tests__/setup.ts'], + include: ['src/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html'], + exclude: [ + 'node_modules/', + 'src/__tests__/', + '**/*.d.ts', + ], + }, + }, + resolve: { + alias: { + '@': resolve(__dirname, 'src'), + }, + }, +})