Points clés
- Une SPA génère mécaniquement plus d'états visuels qu'un site multi-pages traditionnel, et chaque état peut contenir une régression
- La navigation côté client, les transitions animées et le rendu conditionnel créent des combinaisons visuelles que les tests fonctionnels ne couvrent pas
- Le test visuel automatisé est la seule approche réaliste pour capturer et vérifier tous les états d'une SPA
- Ignorer le test visuel dans une SPA, c'est accepter que la plupart de vos états d'interface ne soient jamais vérifiés
Une Single Page Application, selon la définition du MDN Web Docs, est « une application web qui interagit avec l'utilisateur en réécrivant dynamiquement la page courante plutôt qu'en chargeant entièrement de nouvelles pages depuis le serveur, ce qui résulte en une expérience utilisateur plus fluide, similaire à une application native ».
Cette définition technique est élégante. La réalité QA qui en découle l'est beaucoup moins.
Parce qu'en réécrivant dynamiquement la page plutôt qu'en chargeant de nouvelles pages, une SPA concentre dans un seul document HTML un nombre d'états visuels qui dépasse de loin ce qu'un site traditionnel peut produire. Et chaque état est un endroit où quelque chose peut s'afficher incorrectement.
Les sites multi-pages avaient un avantage que personne ne reconnaissait
Avant l'ère des SPA, chaque URL correspondait à une page distincte, chargée entièrement depuis le serveur. C'était lent, parfois saccadé, mais ça avait un avantage considérable du point de vue QA : chaque page était un état discret et stable. Vous pouviez la capturer, la vérifier, et passer à la suivante.
Un site de vingt pages avait vingt états principaux. Vous pouviez littéralement les lister sur un tableau et les cocher un par un. C'était gérable.
Les SPA ont brisé cette simplicité. Une application React, Vue ou Angular de complexité moyenne ne peut pas être réduite à ses routes. Chaque route peut afficher des dizaines d'états différents selon les données chargées, les interactions, les permissions, les conditions d'erreur, les états de chargement.
Prenez une page dashboard. Elle peut afficher un état de chargement initial avec skeletons. Puis l'état avec données. Puis l'état données vides (premier lancement). Puis l'état erreur réseau. Puis l'état avec un filtre actif. Puis l'état avec une modale ouverte. Puis l'état avec un tooltip visible. Chaque état a une apparence visuelle distincte que vos utilisateurs vont voir.
Multipliez par le nombre de routes, et vous comprenez pourquoi tester manuellement une SPA est une illusion.
Défis visuels spécifiques aux SPA
Navigation sans rechargement
Dans un site traditionnel, la navigation déclenche un rechargement complet. Le navigateur détruit le DOM existant, charge le nouveau HTML, applique le CSS, exécute le JS. Chaque page démarre d'un état propre.
Dans une SPA, la navigation modifie le DOM existant sans recharger. Les composants sont montés et démontés. L'état global persiste entre les vues. Les effets de bord s'accumulent.
Cela crée un problème subtil mais réel : l'apparence d'une vue peut dépendre du chemin de navigation pris pour y arriver. Un composant qui se monte correctement quand vous accédez directement à la route peut s'afficher différemment quand vous y arrivez après navigation depuis une autre vue.
Les tests fonctionnels qui accèdent à chaque route directement par URL passent complètement à côté de ces régressions liées à la navigation séquentielle. Seul un test qui reproduit le parcours utilisateur réel et capture visuellement le résultat peut les détecter.
Transitions et animations
Les SPA utilisent abondamment des transitions pour fluidifier la navigation. Un composant ne disparaît pas instantanément : il s'anime en sortie pendant que le suivant s'anime en entrée.
Et c'est une source prolifique de bugs visuels. Une animation CSS interrompue peut laisser deux composants superposés. Un timing mal calibré peut créer un flash de contenu. Une animation qui ne se termine pas proprement peut laisser un élément dans un état intermédiaire indéfiniment.
Le test visuel automatisé peut capturer les états intermédiaires de transition en prenant des captures à des moments précis du cycle d'animation.
Rendu conditionnel
Les SPA adorent le rendu conditionnel. Afficher ce composant si l'utilisateur est connecté. Afficher cette bannière si la feature est en beta. Changer ce bouton si le panier a des items. Cacher cette section si l'abonnement a expiré.
Chaque condition crée une fork dans l'arbre des états visuels possibles. Avec cinq conditions indépendantes, théoriquement trente-deux combinaisons visuelles différentes. Avec dix, plus de mille.
Personne ne teste mille combinaisons manuellement. Personne ne les liste exhaustivement. Pourtant elles existent et vos utilisateurs les rencontrent.
États de chargement asynchrones
Dans un site multi-pages, le chargement est binaire : la page est chargée ou pas. Dans une SPA, le chargement est continu et partiel. Un composant peut être chargé pendant qu'un autre attend ses données.
Ces états de chargement partiels sont visuellement significatifs. Vos skeletons, spinners et placeholders sont des éléments d'interface à part entière. Un skeleton mal dimensionné qui ne correspond pas à la taille du contenu final crée un saut visuel désagréable.
La gestion d'état est un multiplicateur d'états visuels
L'architecture moderne d'une SPA repose sur la gestion d'état centralisée (Redux, Vuex, Pinia, NgRx, Zustand). L'état de l'application est stocké dans un store global qui détermine ce qui apparaît à l'écran.
Ce pattern architectural est excellent pour la maintenabilité. Il est terrible pour la testabilité visuelle, parce qu'il multiplie exponentiellement les combinaisons d'états possibles.
Un utilisateur connecté avec un panier vide, des notifications non lues et le mode sombre activé ne voit pas la même chose qu'un visiteur anonyme en mode clair. Et les deux doivent être testés visuellement.
Le routing client et ses pièges visuels
Le scroll position. Dans un site multi-pages, chaque navigation reset le scroll en haut. Dans une SPA, la position de scroll est conservée entre les vues sauf si le router est configuré pour la reset. Résultat : un utilisateur qui navigue d'une longue page vers une courte peut se retrouver avec un écran blanc, scrollé au-delà du contenu.
Le deep linking. Les utilisateurs peuvent arriver directement sur n'importe quelle route via un lien partagé. Le rendu doit être correct même sans le contexte de navigation normal.
La navigation arrière. Le bouton "back" du navigateur dans une SPA ne recharge pas la page : il restaure un état d'historique. Si la restauration est incomplète, la vue affichée peut être visuellement différente de l'originale.
Une approche structurée du test visuel pour SPA
Couverture des routes — chaque route doit avoir au moins une capture de référence dans son état par défaut.
Couverture des états — pour chaque route, identifiez les états visuellement distincts (vide, chargé, erreur, chargement) et créez une référence pour chacun.
Couverture des interactions — modales, dropdowns, tooltips, panneaux latéraux qui s'ouvrent à l'interaction sont des états visuels à part entière.
Couverture des parcours — certains bugs visuels n'apparaissent que dans un contexte de navigation spécifique.
Les SPA méritent plus de test visuel, pas moins
Tentation compréhensible : face à la complexité, certaines équipes réduisent leur effort de test visuel. « Trop d'états, on ne peut pas tout couvrir, concentrons-nous sur le fonctionnel. »
Cette réaction est l'inverse de ce qu'il faut. Plus votre application a d'états visuels, plus le test visuel est nécessaire. C'est précisément parce que les SPA sont visuellement complexes que le test manuel est insuffisant et que l'automatisation visuelle devient essentielle.
Chaque état visuellement non testé est un état qui peut régresser silencieusement. Et dans une SPA, le nombre d'états non testés dépasse rapidement les états testés, sauf si vous utilisez un outil capable de les capturer automatiquement.
FAQ
Le test visuel fonctionne-t-il avec tous les frameworks SPA ?
Oui. Le test visuel est agnostique au framework. Il capture l'apparence finale rendue par le navigateur, peu importe React, Vue, Angular, Svelte ou autre.
Comment gérer les animations et transitions dans les tests visuels SPA ?
La meilleure approche est de désactiver les animations CSS et JS lors des captures pour obtenir des comparaisons stables. Certains outils offrent cette option nativement.
Comment tester visuellement des états dépendant de données dynamiques ?
La solution standard est le mocking d'API. Vous configurez les tests pour intercepter les appels réseau et retourner des données déterministes.
Combien d'états visuels tester pour une SPA moyenne ?
Au minimum trois par route : nominal, vide, erreur. Pour une SPA de 20 routes, ça représente un minimum de 60 captures de référence. Avec les états d'interaction, vous atteignez 100-150 facilement.
Le test visuel remplace-t-il les tests unitaires et e2e dans une SPA ?
Non, et ce n'est pas son but. Les tests unitaires vérifient la logique. Les tests e2e vérifient les parcours fonctionnels. Le test visuel vérifie l'apparence. Les trois sont complémentaires.
Les tests visuels d'une SPA ne sont-ils pas trop lents ?
Une SPA moderne se rend en quelques centaines de millisecondes. La capture en ajoute quelques dizaines. La comparaison est quasi instantanée. Pour 100 captures, comptez 2-5 minutes au total.
Pour aller plus loin
- Test visuel pour Gatsby : les sites statiques sont les plus faciles à tester — voici comment
- Test visuel Remix : pourquoi un framework full-stack rend le test visuel encore plus critique
- Test visuel Next.js : le guide complet pour sécuriser vos applications React SSR
- Test Visuel React Native : Le Mobile, Parent Pauvre du Test Visuel
- Test Visuel Ruby on Rails : Pourquoi les View Specs Ne Suffisent Pas et Comment le Test Visuel Comble la Lacune
Votre SPA a des dizaines d'états visuels que personne ne teste ? Il est temps de changer ça.