agentsclimarketplace

Testing patterns

Skill chawkitariq/fidely/.claude/skills/testing-patterns

Patterns de tests Fidely : Vitest + @nuxt/test-utils + fake-indexeddb + happy-dom. Déclencher quand : écriture de test, ajout composable (useDB, useClient), nouveau composant Vue, modification d'une fonction dans utils/, isolation IndexedDB, mock Nuxt (useToast, navigateTo). Mots-clés : describe, it, expect, beforeEach, IDBFactory, resetDB, mountSuspended, mockNuxtImport, fake-indexeddb, useDB.test.ts, CardItem.test.ts, CardForm.test.ts, updatePoints, consumeReward, addCard, getOrCreateClientId.From its SKILL.md

Install
npx -y skills add chawkitariq/fidely --skill testing-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.8 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Skill : Écrire et exécuter des tests pour Fidely

Ressources disponibles

Règles obligatoires

Toujours lancer les tests après toute modification de code

pnpm vitest run          # lancer tous les tests
pnpm vitest run app/composables/useDB.test.ts   # lancer un fichier spécifique

Toute nouvelle feature doit être accompagnée de tests :

  • Nouveau composable ou nouvelle fonction → fichier .test.ts co-localisé dans app/composables/
  • Nouveau composant avec logique → fichier .test.ts co-localisé dans app/components/
  • Nouvelle règle métier → test du cas nominal + cas limite

Quand lancer les tests :

  • Après chaque modification d'un composable (useDB.ts, useClient.ts)
  • Après chaque modification d'un composant (CardItem.vue, CardForm.vue)
  • Après chaque ajout ou modification d'une fonction dans utils/
  • Avant de marquer une tâche comme ✅ dans TASKS.md

Seuil d'acceptation :

  • 0 test en échec — jamais valider une tâche avec des tests rouges
  • Si un test échoue suite à un changement intentionnel, mettre à jour le test en même temps que le code

Setup (déjà configuré)

pnpm add -D @nuxt/test-utils vitest @vue/test-utils fake-indexeddb happy-dom

vitest.config.ts à la racine :

import { defineVitestConfig } from '@nuxt/test-utils/config'

export default defineVitestConfig({
  test: {
    environment: 'nuxt',
    setupFiles: ['./app/setup.ts']   // ← app/setup.ts (pas setup.test.ts)
  }
})

app/setup.ts :

import 'fake-indexeddb/auto'

Structure des fichiers de test

Les tests sont co-localisés avec les sources — même dossier que le fichier testé, suffixe .test.ts :

app/
├── composables/
│   ├── useDB.ts
│   ├── useDB.test.ts        ← test co-localisé
│   ├── useClient.ts
│   └── useClient.test.ts
├── components/
│   ├── CardItem.vue
│   ├── CardItem.test.ts     ← test co-localisé
│   ├── CardForm.vue
│   └── CardForm.test.ts
└── utils/
    ├── uuid.ts
    └── uuid.test.ts

Ne jamais créer de dossier tests/ séparé — les tests vivent à côté du code qu'ils testent.


Isolation IndexedDB entre les tests

Obligatoire : créer une nouvelle instance IDBFactory dans beforeEach pour que chaque test parte d'une DB vide :

import { IDBFactory } from 'fake-indexeddb'
import { resetDB } from '~/composables/useDB'

beforeEach(() => {
  globalThis.indexedDB = new IDBFactory()
  resetDB() // reset le cache de connexion dans useDB.ts
})

Ne jamais appeler indexedDB.deleteDatabase() — cette API est asynchrone et peut provoquer des timeouts si non attendue correctement.


Pattern pour tester les composables (useDB, useClient)

import { describe, it, expect, beforeEach } from 'vitest'
import { IDBFactory } from 'fake-indexeddb'
import { resetDB, useDB } from '~/composables/useDB'

beforeEach(() => {
  globalThis.indexedDB = new IDBFactory()
  resetDB()
})

describe('getAllCards', () => {
  it('retourne un tableau vide par défaut', async () => {
    const { getAllCards } = useDB()
    const cards = await getAllCards()
    expect(cards).toEqual([])
  })
})

describe('updatePoints', () => {
  it('ne descend jamais en dessous de 0', async () => {
    const { addCard, updatePoints } = useDB()
    const card = await addCard({ title: 'T', reward_points: 5, reward: 'R' })
    const points = await updatePoints('client-1', card.id, -99)
    expect(points).toBe(0)
  })
})

Pattern pour tester les composants Vue

import { describe, it, expect } from 'vitest'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import CardItem from '~/components/CardItem.vue'
import type { Card } from '~/composables/useDB'

const card: Card = {
  id: 'card-1',
  title: 'Carte café',
  reward_points: 10,
  reward: '1 café offert',
  created_at: Date.now()
}

describe('CardItem — merchant mode', () => {
  it('affiche le titre', async () => {
    const wrapper = await mountSuspended(CardItem, {
      props: { card, merchantMode: true }
    })
    expect(wrapper.text()).toContain('Carte café')
  })

  it('émet deleted avec le cardId au clic supprimer', async () => {
    const wrapper = await mountSuspended(CardItem, {
      props: { card, merchantMode: true }
    })
    await wrapper.find('[aria-label="Supprimer"]').trigger('click')
    expect(wrapper.emitted('deleted')?.[0]).toEqual(['card-1'])
  })
})

Structure describe / it standardisée

describe('NomDuSujet')
  describe('nomDeLaFonction ou contexte')
    it('fait X dans le cas normal')
    it('gère le cas limite Y')
    it('lance une erreur si Z')

Phrases it : toujours en anglais, décrivent le comportement attendu (pas l'implémentation).


Cas à toujours couvrir

Composables :

  • Happy path (cas nominal)
  • Valeurs limites (0 points, tableau vide, client inexistant)
  • Comportement idempotent (appels multiples retournent le même résultat)
  • Erreurs attendues (rejects.toThrow(...))

Composants :

  • Rendu avec les props minimales
  • Chaque emit déclenché par l'action utilisateur correspondante
  • États désactivés / conditionnels (:disabled, v-if)
  • Props optionnelles non fournies (comportement par défaut)

Mocking des APIs Nuxt

// useToast et navigateTo sont auto-mockés par @nuxt/test-utils dans l'environment 'nuxt'
// Pas besoin de mock manuel dans la plupart des cas

// Si besoin de vérifier un appel toast ou navigateTo :
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

const toastMock = vi.fn()
mockNuxtImport('useToast', () => () => ({ add: toastMock }))

Confirmation en fin de tâche

testing-patterns appliqués

  • Isolation : [beforeEach IDBFactory + resetDB en place]
  • Couverture : [happy path + cas limite + erreurs attendues]
  • Structure : [describe/it en anglais, comportemental]
  • Résultat : [pnpm vitest run → 0 test en échec]

What ships with it: 3 files

10.4 KB alongside SKILL.md, 2 of them executable

reference/

templates/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.