Testing Overview
CPR uses Vitest 4.x as its test runner along with @vue/test-utils 2.x for Vue component testing and happy-dom as the DOM environment. Code coverage is provided by @vitest/coverage-v8.
Test Stack
| Tool | Version | Purpose |
|---|---|---|
| Vitest | 4.x | Test runner and assertion library |
| @vue/test-utils | 2.x | Mounting and interacting with Vue components |
| happy-dom | 20.x | Lightweight DOM implementation for tests |
| @vitest/coverage-v8 | 4.x | Code coverage via V8's built-in instrumentation |
What to Test
High Priority
- Composables -- Business logic lives here (
useCreateInsurance,useListFilters,useFormValidation,useValidationRules). Every composable that transforms data or manages async state should have tests. - Utility functions -- Pure functions like date formatting, money formatting, and API request helpers are the easiest to test and the most valuable.
- Validation rules -- The
useValidationRulesmodule (required,numeric,email,minLength, etc.) guards patient data integrity and must be thoroughly tested.
Medium Priority
- Pinia stores -- Stores like
useAuthStore,useInsuranceStore, anduseSystemCategoryStorehold critical state. Testhydrate(),reset(), and computed properties. - UI components -- Shared components in
app/components/ui/(UiButton,UiInput,UiModal,UiTable) are used across the entire application. Test prop behavior, emits, and slots.
Lower Priority (but still valuable)
- Page components -- These are integration-heavy and better served by E2E tests.
- Layouts -- Rarely change and are hard to unit test meaningfully.
Test File Location
Place test files alongside the source file using the .spec.ts or .test.ts suffix:
app/
composables/
useValidationRules.ts
useValidationRules.spec.ts # <-- test file next to source
stores/
auth.store.ts
auth.store.spec.ts
components/
ui/
UiButton.vue
UiButton.spec.tsThis convention keeps tests discoverable and closely tied to the code they cover.
Vitest Configuration
CPR does not have a standalone vitest.config.ts. Vitest is configured through nuxt.config.ts and Nuxt's built-in Vitest integration. When you run tests, Nuxt automatically provides the correct Vite plugins, aliases (~/, #imports), and auto-imports.
If you need to customize Vitest settings, add them to nuxt.config.ts:
// nuxt.config.ts
export default defineNuxtConfig({
// ... existing config
// Vitest is auto-configured by Nuxt, but you can override:
vitest: {
environment: 'happy-dom',
},
});Running Tests
# Run all tests
npx vitest
# Run tests in watch mode (default)
npx vitest --watch
# Run tests once (CI mode)
npx vitest run
# Run tests with coverage
npx vitest run --coverage
# Run a specific test file
npx vitest app/composables/useValidationRules.spec.ts
# Run tests matching a pattern
npx vitest -t "required"Adding Test Scripts
Consider adding these scripts to package.json:
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage"
}
}Test Structure Convention
Follow the Arrange-Act-Assert pattern:
import { describe, it, expect } from 'vitest';
import { required } from '~/composables/useValidationRules';
describe('required', () => {
it('returns error message when value is empty', () => {
// Arrange
const validate = required('Name');
// Act
const result = validate('');
// Assert
expect(result).toBe('Name is required');
});
it('returns null when value is provided', () => {
const validate = required('Name');
const result = validate('John Doe');
expect(result).toBeNull();
});
});Next Steps
- Unit Testing -- Testing composables, utilities, and validation rules
- Component Testing -- Testing Vue components with Vue Test Utils
- E2E Testing -- Strategy for end-to-end testing
