Skip to content

Last updated:

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

ToolVersionPurpose
Vitest4.xTest runner and assertion library
@vue/test-utils2.xMounting and interacting with Vue components
happy-dom20.xLightweight DOM implementation for tests
@vitest/coverage-v84.xCode 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 useValidationRules module (required, numeric, email, minLength, etc.) guards patient data integrity and must be thoroughly tested.

Medium Priority

  • Pinia stores -- Stores like useAuthStore, useInsuranceStore, and useSystemCategoryStore hold critical state. Test hydrate(), 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.ts

This 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:

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

bash
# 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:

json
{
  "scripts": {
    "test": "vitest",
    "test:run": "vitest run",
    "test:coverage": "vitest run --coverage"
  }
}

Test Structure Convention

Follow the Arrange-Act-Assert pattern:

ts
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

CPR - Clinical Patient Records