Web Apps Modernes 2020 : plein de nouveautés !
Par Delicious Insights • Publié le 8 janv. 2020

La formation Web Apps Modernes est notre best-seller. C’est la seule à notre catalogue à être proposée en inter-entreprises quasiment tous les mois, en plus des sessions intra !

Née en 2012, elle avait connu en 2015 une réécriture intégrale sur base de Webpack, React, Jest, Chai, Enzyme, Sinon et j’en passe. Mais le temps a passé et les meilleures pratiques ont évolué, sans parler de l’apparition de nouvelles disruptions importantes dans l’écosystème.

Il était temps de la revisiter largement, et janvier 2020 voit la première session de cette nouvelle mouture ! Voyons un peu ce qu’il en est.

Le plaisir des Hooks

Depuis React 16.8, les Hooks sont officiellement disponibles.

En nous permettant d’exploiter la quasi-totalité des fonctionnalités de React au sein de simples fonctions composants, ils simplifient considérablement le code, regroupent celui-ci par sujets (plutôt que de l’éparpiller dans des méthodes de cycle de vie qui mélangent les sujets), éliminent des catégories entières de bugs et d’une façon générale nous approchent davantage de l’essence de React.

L’application que nous développons en fil rouge pour Web Apps Modernes était entièrement réalisable avec les Hooks, éliminant complètement la nécessité des composants à base de classes : il aurait été bien dommage de ne pas en profiter !

Des tests plus parlants et plus robustes

Nous utilisions l’acteur historique incontournable des tests de composants React : Enzyme, de Airbnb.

Très orienté tests unitaires et encourageant des rendus shallow, qui restent du coup au niveau du DOM virtuel, Enzyme encourageait finalement l’écriture de tests trop couplés aux détails d’implémentation de nos composants, donc peu pérennes voire friables dès qu’un de ces détails changeait. Il était par ailleurs difficile d’avoir une pleine confiance dans le fonctionnement effectif d’un composant en termes d’interactions utilisateurs « réelles ».

Depuis un peu plus d’un an, un écosystème de tests avec une philosophie différente a émergé, sous le nom collectif de Testing Library. Il propose une API unifiée pour tout un tas de frameworks et substrats, dont React naturellement (avec React Testing Library, ou RTL).

RTL estime que seuls des tests simulant au plus près la réalité de l’utilisation de nos composants ont de la valeur, ils devraient donc opérer sur le DOM réel, fut-il simulé en mémoire (par exemple par JSDOM), avec des événements qui se propagent, etc.

RTL considère par ailleurs que nos tests ne devraient pas s'attacher aux détails d’implémentation (une balise spécifique, un choix de composant React plutôt qu’un autre, une classe CSS donnée…) mais s’attacher aux rôles fonctionnels des éléments (titre / en-tête, champ de saisie, bouton…) et à leurs libellés et textes, qui constituent des caractéristiques plus stables et aident à pérenniser nos tests.

Nous avons donc viré Enzyme et réécrit notre système de tests avec RTL ; en pratique, cela a considérablement simplifié voire éliminé certaines problématiques de tests (notamment liées aux HOC et enrobages divers), tout en rendant notre code de tests plus expressif. Par exemple, en testant la jauge :

const { getByRole } = render(<Gauge value={50} />)
const progressBar = getByRole('progressbar')
expect(progressBar).toHaveAttribute('aria-valuenow', '50')

Une stack de tests simplifiée

Notre stack de tests historique était assez lourde, avec de nombreux acteurs qui se partageaient les tâches :

  1. Jest pour le harnais
  2. Chai pour les assertions
  3. Enzyme pour le rendu de test des composants
  4. Sinon pour le mocking
  5. Et les plugins Chai pour des assertions métier sur Enzyme et Sinon

Les apprenant·e·s avaient du mal à percevoir quelle techno apportait quelle possibilité dans le code des tests, et le « branchement » ensemble de ces technos n’était pas trivial, nécessitant un jest/setup.js assez verbeux.

Nous avons choisi de dégraisser tout ça :

  • Les assertions natives de Jest ont progressé, même si elles ne sont toujours pas chaînables ; on peut retirer Chai et ses plugins.
  • Le mocking natif de Jest suffisait presque pour retirer Sinon, sauf que son useFakeTimers() n’est pas aussi complet que celui de Sinon, qui simule toute la couche « temps », dont new Date() et Date.now(), dont nous avions besoin. En améliorant la signature de notre fonction utilitaire formatDate pour permettre le passage optionnel de la date de référence, on a pu supprimer ce besoin et retirer Sinon.

On ne garde donc que deux technos aux rôles bien identifiés :

  1. Jest pour tout l'aspect générique : harnais, assertions, mocking, snapshots, couverture…
  2. React Testing Library pour l’aspect React : rendu virtuel, simulation d’événements, interrogation des résultats, etc.

Et en prime, plus besoin de jest/setup.js !

Moins de dépendances

On a pu retirer pas mal de modules, soit parce qu'ils n’étaient plus nécessaires, soit en les remplaçant par des alternatives plus modernes, légères et tree-shakeables :

  • Moment.js est ancien, lourd, pas pratique (mutatif) et nécessite un bundling Webpack spécifique pour éviter d’embarquer tous les locales :
    • On a remplacé les quelques aspects algos par des imports chirurgicaux depuis date-fns
    • On a remplacé les formatages par la classe native Intl.DateTimeFormat.
  • React-Document-Title est avantageusement remplacé par le recours au hook standard useEffect().
  • Le plugin Decorators et le décorateur autobind ne sont plus nécessaires, puisqu’on n’a plus de composants à base de classes!

Alors, vous venez ? 😁

N’attendez plus pour découvrir la nouvelle mouture de Web Apps Modernes !

Et si vous voulez vous inscrire en dernière minute à celle de janvier, dans 10 jours, elle est à -20% ! 😎 🎁

Découvrez nos cours vidéo ! 🖥

Nos cours vidéo sont un complément idéal et bon marché à nos articles techniques et formations présentielles. Autour de Git, de JavaScript et d’autres sujets, retrouvez des contenus de très grande qualité à des prix abordables, spécialement conçus pour lever vos plus gros points de blocage.