unit-test-vue-pinia
Utilise ce skill pour créer ou examiner des tests unitaires pour les composants Vue, les composables et les stores Pinia. Garde les tests petits, déterministes et orientés comportement.
Workflow
- Identifie d'abord la limite comportementale : comportement UI du composant, comportement du composable, ou comportement du store.
- Choisis le style de test le plus étroit qui peut prouver ce comportement.
- Configure Pinia avec l'option la moins puissante qui couvre toujours le scénario.
- Guide le test à travers des entrées publiques comme les props, les mises à jour de formulaire, les clics de bouton, les événements enfant émis et les APIs de store.
- Affirme les sorties et effets secondaires observables avant de considérer toute assertion au niveau de l'instance.
- Retourne ou examine les tests avec des noms clairs orientés comportement et note les lacunes de couverture restantes.
Core Rules
- Teste un comportement par test.
- Affirme d'abord le comportement observable entrée/sortie (texte rendu, événements émis, appels de callback, changements d'état du store).
- Évite les assertions couplées à l'implémentation.
- Accède à
wrapper.vmuniquement dans les cas exceptionnels quand il n'existe aucune assertion raisonnable au niveau DOM, prop, emit ou store. - Préfère la configuration explicite dans
beforeEach()et réinitialise les mocks à chaque test. - Utilise le matériel de référence enregistré dans
references/pinia-patterns.mdcomme source locale de vérité pour les setups de test Pinia standard.
Pinia Testing Approach
Utilise references/pinia-patterns.md en premier, puis replie-toi sur le cookbook de test Pinia quand les exemples enregistrés ne couvrent pas le cas.
Motif par défaut pour les tests de composant
Utilise createTestingPinia comme plugin global lors du montage.
Préfère createSpy: vi.fn comme défaut pour la cohérence et les assertions d'espion d'action plus faciles.
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
}),
],
},
});
Par défaut, les actions sont stubifiées et espionnées.
Utilise stubActions: true (défaut) quand le test doit seulement vérifier si une action a été appelée (ou non appelée).
Setups Pinia minimaux acceptés
Les suivants sont aussi valides et ne doivent pas être signalés comme incorrects :
createTestingPinia({})quand le test n'affirme pas le comportement d'espion d'action Pinia.createTestingPinia({ initialState: ... })oucreateTestingPinia({ stubActions: ... })sanscreateSpy, quand le test a besoin seulement de comportement d'amorçage d'état ou de stubification d'action et n'inspecte pas les espions générés.setActivePinia(createTestingPinia(...))dans les tests focalisés sur store/composable (sans monter un composant) quand le mock/amorçage de stores dépendants est nécessaire.
Utilise createSpy: vi.fn quand les assertions d'espion d'action font partie de l'intention du test.
Exécute les actions réelles seulement quand nécessaire
Utilise stubActions: false seulement quand le test doit valider le comportement et les effets secondaires réels de l'action. Ne l'active pas par défaut pour les simples assertions "was called".
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
stubActions: false,
}),
],
},
});
Amorce l'état du store avec initialState
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
initialState: {
counter: { n: 20 },
user: { name: "Leia Organa" },
},
}),
],
},
});
Ajoute les plugins Pinia via createTestingPinia
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
plugins: [myPiniaPlugin],
}),
],
},
});
Motif d'override getter pour les cas limites
const pinia = createTestingPinia({ createSpy: vi.fn });
const store = useCounterStore(pinia);
store.double = 999;
// @ts-expect-error test-only reset of overridden getter
store.double = undefined;
Tests unitaires purs de store
Préfère les tests purs de store avec createPinia() quand l'objectif est de valider les transitions d'état du store et le comportement d'action sans rendu de composant. Utilise createTestingPinia() seulement quand tu as besoin de stores dépendants stubifiés, de test doubles amorcés, ou d'espions d'action.
beforeEach(() => {
setActivePinia(createPinia());
});
it("increments", () => {
const counter = useCounterStore();
counter.increment();
expect(counter.n).toBe(1);
});
Vue Test Utils Approach
Suis les directives de Vue Test Utils : https://test-utils.vuejs.org/guide/
- Monte shallow par défaut pour les tests unitaires focalisés.
- Monte les arbres de composants complets seulement quand le comportement d'intégration est le sujet.
- Guide le comportement à travers les props, les interactions de type utilisateur et les événements émis.
- Préfère
findComponent(...).vm.$emit(...)pour les événements enfant stub au lieu de toucher les internals du parent. - Utilise
nextTickseulement quand les mises à jour sont asynchrones. - Affirme les événements émis et les payloads avec
wrapper.emitted(...). - Accède à
wrapper.vmseulement quand aucune assertion DOM, assertion d'événement émis, assertion prop ou assertion au niveau du store ne peut exprimer le comportement. Traite cela comme une exception et garde l'assertion étroitement ciblée.
Key Testing Snippets
Émettre et affirmer le payload :
await wrapper.find("button").trigger("click");
expect(wrapper.emitted("submit")?.[0]?.[0]).toBe("Mango Mission");
Mettre à jour l'input et affirmer la sortie :
await wrapper.find("input").setValue("Agent Violet");
await wrapper.find("form").trigger("submit");
expect(wrapper.emitted("save")?.[0]?.[0]).toBe("Agent Violet");
Test Writing Workflow
- Identifie la limite comportementale à tester.
- Construis des données de fixture minimales (seulement les champs nécessaires à ce comportement).
- Configure Pinia et les test doubles nécessaires.
- Déclenche le comportement à travers les entrées publiques.
- Affirme les sorties publiques et les effets secondaires.
- Refactorise les noms de test pour décrire le comportement, pas l'implémentation.
Constraints and Safety
- Ne teste pas les détails privés/internes de l'implémentation.
- N'abuse pas des snapshots pour le comportement UI dynamique.
- N'affirme pas chaque champ dans les grands objets si un seul comportement importe.
- Garde les données fausses déterministes ; évite les valeurs aléatoires.
- Ne réclame pas qu'un setup Pinia est faux quand c'est l'un des setups minimaux acceptés ci-dessus.
- Ne réécris pas les tests qui fonctionnent vers un montage plus profond ou des actions réelles à moins que le comportement testé ne nécessite cette surface supplémentaire.
- Signale explicitement la couverture de test manquante, les sélecteurs fragiles et les assertions couplées à l'implémentation lors de l'examen.
Output Contract
- Pour
createouupdate, retourne le code de test fini plus une courte note décrivant la stratégie Pinia sélectionnée. - Pour
review, retourne d'abord les découvertes concrètes, puis la couverture manquante ou les risques de fragilité. - Quand le choix le plus sûr est ambigu, énonce l'hypothèse qui a guidé la configuration de test choisie.
References
references/pinia-patterns.md- Pinia testing cookbook: https://pinia.vuejs.org/cookbook/testing.html
- Vue Test Utils guide: https://test-utils.vuejs.org/guide/