Testing
Vitest setup, test patterns, and mocking strategy
Testing
What's Included
- Vitest with jsdom environment
- Vue Test Utils for component testing
- Global mocks for Nuxt composables, components, and stores
- Unit tests for components and composables
- Integration tests for full page flows
Setup
Vitest Config (vitest.config.ts)
export default defineConfig({
test: {
environment: 'jsdom',
globals: true,
setupFiles: ['tests/setup.ts'],
alias: {
'@/': fileURLToPath(new URL('./', import.meta.url)),
'~/': fileURLToPath(new URL('./', import.meta.url))
}
}
})
Test Setup (tests/setup.ts)
The setup file provides global mocks for:
- Nuxt components —
NuxtLink,NuxtPage(rendered as simple HTML elements) - Composables —
useAuth,useProfile,useSubscription,useCheckout,usePlans,useScrollspy - Stores —
useAuthStore(with mock token, user, isAuthenticated) - Vue composables —
ref,computed,watch,onMounted, etc. - Runtime config —
useRuntimeConfigwith test API URL - Fetch —
$fetchanduseFetchmocked globally - Firebase —
$firebaseAuth,$firebaseAppmocked
Running Tests
# All tests
docker compose exec app npm run test
# Watch mode
docker compose exec app npm run test:watch
# Coverage
docker compose exec app npm run test:coverage
Test Structure
tests/
├── setup.ts # Global mocks
├── unit/
│ ├── components/ # Component unit tests
│ └── composables/ # Composable unit tests
└── integration/ # Full page integration tests
├── landing/
├── auth/
├── payments/
└── navigation/
Writing Component Tests
import { mount } from '@vue/test-utils'
import LoginForm from '~/components/auth/LoginForm.vue'
describe('LoginForm', () => {
it('renders login form fields', () => {
const wrapper = mount(LoginForm)
expect(wrapper.find('input[type="email"]').exists()).toBe(true)
expect(wrapper.find('input[type="password"]').exists()).toBe(true)
expect(wrapper.find('button[type="submit"]').exists()).toBe(true)
})
it('calls login on form submit', async () => {
const wrapper = mount(LoginForm)
// ... set input values and submit
})
})
Mocking Strategy
The project uses global mocks defined in tests/setup.ts rather than per-test mocking. This ensures consistency and avoids boilerplate. Composables return mock functions that can be spied on in individual tests.