Tester les transitions sans navigateur
Objectif : Vérifier les résultats des transitions d’état avec des tests ciblés sur les fonctions pures.
Une transition peut sembler correcte dans la console tout en supprimant une tâche inattendue ou en modifiant l’état précédent. Pour détecter ces erreurs, vous pouvez tester la fonction réductrice séparément de l’interface. Vous vérifiez ainsi les résultats des actions sans ouvrir de page ni simuler de clic.
Dans la leçon précédente, vous avez défini des actions et les transitions immuables de `reduireEtat` ; vous allez maintenant en vérifier le comportement. Une fonction est dite pure lorsqu’elle produit le même résultat pour les mêmes entrées et ne modifie pas les données reçues. Cette propriété permet de lui fournir un état et une action, puis de comparer le résultat à ce que vous attendez.
Préparer des cas de test précis
Un test ciblé part d’un état connu, applique une action et vérifie le nouvel état. Par exemple, après l’ajout d’une tâche, vous pouvez vérifier son identifiant, son libellé et son statut initial. Pour la suppression, vérifiez que seule la tâche désignée disparaît. Ces cas simples isolent les erreurs et rendent leur cause facile à repérer.
Les tests ci-dessous supposent la forme de l’état et des actions utilisées dans les leçons précédentes : l’état contient `taches`, une tâche contient `id`, `libelle` et `terminee`, et les actions transportent leurs données dans les propriétés montrées. Exécutez la commande à la racine du projet avec une version récente de Node prenant en charge `--experimental-default-type=module`. Les imports utilisent directement les fichiers du projet, sans ajouter de fichier ni de dépendance.
node --experimental-default-type=module --input-type=module <<'EOF'
import assert from 'node:assert/strict';
import { etatInitial } from './js/etat.js';
import { reduireEtat } from './js/reducteur.js';
function testerAjout() {
const avant = etatInitial();
const action = {
type: 'tache/ajouter',
tache: { id: 't1', libelle: 'Préparer le compte rendu', terminee: false }
};
const apres = reduireEtat(avant, action);
assert.equal(apres.taches.length, 1);
assert.deepEqual(apres.taches[0], action.tache);
assert.notStrictEqual(apres, avant);
assert.equal(avant.taches.length, 0);
}
function testerBascule() {
const avant = {
taches: [{ id: 't1', libelle: 'Préparer le compte rendu', terminee: false }]
};
const apres = reduireEtat(avant, { type: 'tache/basculer', id: 't1' });
assert.equal(apres.taches[0].terminee, true);
assert.equal(avant.taches[0].terminee, false);
assert.notStrictEqual(apres.taches, avant.taches);
}
function testerSuppression() {
const avant = {
taches: [
{ id: 't1', libelle: 'Rédiger le compte rendu', terminee: false },
{ id: 't2', libelle: 'Envoyer le compte rendu', terminee: false }
]
};
const apres = reduireEtat(avant, { type: 'tache/supprimer', id: 't1' });
assert.deepEqual(apres.taches.map(function extraireIdentifiant(tache) {
return tache.id;
}), ['t2']);
assert.equal(avant.taches.length, 2);
}
testerAjout();
testerBascule();
testerSuppression();
console.log('3 tests réussis');
EOF3 tests réussisLe module `node:assert/strict` arrête le script dès qu’une vérification échoue : le message d’erreur indique alors la comparaison concernée. `deepEqual` compare le contenu des objets, tandis que `equal` vérifie ici une valeur simple. `notStrictEqual` contrôle que le résultat est une nouvelle référence, ce qui complète la vérification des valeurs sans se limiter à l’affichage final.
Tester aussi les cas limites
Les exemples couvrent les trois transitions principales et vérifient que l’entrée reste intacte. Vous pouvez compléter cette base avec des cas correspondant aux règles déjà prises en charge par votre réducteur : identifiant inconnu, action inconnue ou ajout d’un libellé que `nettoyerLibelle` refuse. N’attendez pas d’un test qu’il décide d’une règle qui n’existe pas encore ; commencez par fixer le comportement attendu, puis écrivez l’assertion correspondante.
Ces tests sont exécutés hors navigateur parce qu’ils n’accèdent ni au DOM ni aux API de la page. Ils vérifient uniquement les fonctions et données importées. Lorsque vous ajouterez des adaptateurs pour les interactions, vous pourrez conserver ces tests de transitions indépendamment de l’interface.
À retenir
- Donnez à chaque test un état d’entrée et une action explicites.
- Vérifiez le résultat attendu avec des assertions ciblées.
- Contrôlez que les transitions ne modifient pas l’état précédent.
- Exécutez les tests hors navigateur pour isoler le réducteur de l’interface.