Aller au contenu

Tests

NiveauOutilCouverture cible
ComposablesVitest90%
Stores (Pinia)Vitest90%
ComposantsVitest + @vue/test-utils70%
VuesVitest + @vue/test-utils60%
E2EPlaywrightFlux critiques

Couverture globale minimum : 80%

OutilRôle
VitestTest runner (compatible Vite)
@vue/test-utilsMontage et interaction composants Vue
fake-indexeddbMock IndexedDB pour Dexie.js
@vitest/coverage-v8Mesure de couverture
PlaywrightTests end-to-end navigateur

Les tests sont colocalisés : chaque fichier a ses tests dans __tests__/ à côté.

composables/
├── useVitalSigns.ts
├── __tests__/
│ └── useVitalSigns.spec.ts
components/
├── ui/
│ ├── BaseButton.vue
│ ├── __tests__/
│ │ └── BaseButton.spec.ts
Fenêtre de terminal
npm test # Tests unitaires et composants
npm run test:watch # Mode watch
npm run test:coverage # Couverture de code
npm run test:e2e # Tests end-to-end (Playwright)
import { describe, it, expect } from 'vitest'
import { useVitalSigns } from '../useVitalSigns'
describe('useVitalSigns', () => {
it('should initialize with default values', () => {
const { vitals } = useVitalSigns()
expect(vitals.value.hr).toBe(0)
expect(vitals.value.spo2).toBe(0)
})
it('should trigger alarm when HR is too high', () => {
const { setVital, isAlarming } = useVitalSigns()
setVital('hr', 150)
expect(isAlarming.value).toBe(true)
})
})
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import BaseButton from '../BaseButton.vue'
describe('BaseButton', () => {
it('should render slot content', () => {
const wrapper = mount(BaseButton, {
slots: { default: 'Click me' },
})
expect(wrapper.text()).toContain('Click me')
})
it('should emit click event', async () => {
const wrapper = mount(BaseButton)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toHaveLength(1)
})
})

Flux critiques testés :

  1. Démarrer une simulation depuis l’accueil
  2. Naviguer entre les vues pendant une simulation
  3. Modifier les paramètres vitaux en cours de simulation
  4. Exporter une session depuis le débriefing