Écriture d’un test Jest
Objectifs de formation
Une fois cette unité terminée, vous pourrez :
- Écrire un test pour vérifier votre configuration
- Écrire un test qui échoue et le corriger en modifiant votre composant
- Identifier les commandes Jest de base
- Présenter les points d’ancrage de cycle de vie
Partir d’un composant Web Lightning
Pour tester un composant Web Lightning, nous devons d’abord avoir un composant à tester.
Création d’un composant Web Lightning
- Dans Visual Studio Code, ouvrez la palette de commandes en appuyant sur Ctrl+Maj+P (Windows) ou sur Cmd+Maj+P (macOS).
- Saisissez
lightning web
. - Sélectionnez SFDX :. création d’un composant Web Lightning.
- Saisissez
unitTest
pour nommer le nouveau composant. - Appuyez sur Entrée.
- Appuyez de nouveau sur Entrée pour accepter l’emplacement par défaut
force-app/main/default/lwc
.
Cette action crée le répertoire unitTest dans le répertoire lwc comprenant les fichiers de base initiaux.
Écriture d’un test de base
Les tests Jest sont écrits, enregistrés et exécutés différemment des tests Jasmine ou Mocha destinés à Lightning Testing Service pour les composants Aura. Les tests Jest sont uniquement locaux, et sont enregistrés et exécutés indépendamment de Salesforce. Vous obtiendrez d’ailleurs une erreur si vous essayez de déployer des tests Jest dans votre organisation Salesforce. Bien que les tests Jest pour les composants Web Lightning ne soient pas déployés dans votre organisation Salesforce, veillez à les valider dans le système de contrôle de version avec le composant lui-même.
Le dossier __tests__
Les fichiers test doivent être séparés des autres fichiers de composant. Si un dossier n’a pas été créé automatiquement, créez un dossier nommé __tests__ au niveau supérieur du dossier du paquet de votre composant. Enregistrez tous les tests relatifs à ce composant dans le dossier __tests__.
- Dans Visual Studio Code, cliquez avec le bouton droit de la souris sur le répertoire
unitTest
et sélectionnez Nouveau dossier. - Saisissez
__tests__
. - Appuyez sur Entrée.
Configuration de .forceignore
Partagez les tests avec d’autres membres de l’équipe ou systèmes en validant le dossier __tests__ dans le système de contrôle de version. Ils constituent un élément essentiel de votre projet et de votre processus d’intégration continue. Pour les empêcher d’être déployés sur Salesforce, le fichier .forceignore est associé à une exclusion.
- Assurez-vous que le fichier
.forceignore
de votre projet contient les exclusions suivantes. Si ce n’est pas le cas, ajoutez-les et enregistrez le fichier.# LWC configuration files **/jsconfig.json **/.eslintrc.json # LWC Jest **/__tests__/**
Création d’un fichier test Jest
Notre premier test est simple. Nous disposons d’une fonction sum()
censée ajouter deux nombres qui lui sont transmis en tant qu’arguments.
- Dans Visual Studio Code, cliquez avec le bouton droit de la souris sur le répertoire
__tests__
et sélectionnez Nouveau fichier. - Saisissez
sum.test.js
. - Appuyez sur Entrée.
- Saisissez le code suivant dans le nouveau fichier test :
import { sum } from '../sum'; describe('sum()', () => { it('should add 1 and 2 returning 3', () => { expect(sum(1, 2)).toBe(3); }); });
- Enregistrez le fichier.
Exécution du test
- Dans Visual Studio Code, sélectionnez Afficher, puis sélectionnez Terminal. Cette action ouvre un terminal dans Visual Studio Code. Le terminal utilise par défaut le répertoire de niveau supérieur du projet en cours.
- Dans le terminal, exécutez la commande suivante utilisée dans l’unité précédente :
npm run test:unit
- Le test échoue en raison de la fonction de somme manquante.
Observons comment y remédier.
- Dans Visual Studio Code, cliquez avec le bouton droit de la souris sur le répertoire
unitTest
et sélectionnez Nouveau fichier. - Saisissez
sum.js
. - Appuyez sur Entrée.
- Saisissez le bloc de code suivant dans le nouveau fichier :
export function sum(x, y) { return x + y; }
- Enregistrez le fichier.
- Dans le terminal, exécutez à nouveau le test :
npm run test:unit
- Le test réussit.
Félicitations ! Vous venez de vérifier que Jest est installé et fonctionne correctement.
Examinons le code test pour observer ce qui se passe.
import { sum } from '../sum'; describe('sum()', () => { it('should add 1 and 2 returning 3', () => { expect(sum(1, 2)).toBe(3); }); });
- La ligne 1 importe la fonction
sum
exportée à partir du fichier JavaScript de somme. - La ligne 3 déclenche la suite de tests Jest. La fonction ou le bloc
describe
est une suite de tests et accepte deux arguments. Le premier est la description de l’unité que nous testons, qui se présente généralement sous la forme d’un nom. Le deuxième est une fonction de rappel qui contient un ou plusieurs tests. Vous pouvez également imbriquer les suites de testsdescribe
les unes dans les autres pour plus de clarté. - La ligne 4 correspond au test (
it
est un alias detest
). La fonction ou le blocit
accepte également deux arguments. Le premier est une autre description de nos attentes, qui commence généralement par un verbe. Le deuxième est une fonction de rappel qui crée le test et contient les assertions ou les attentes relatives au test. - La ligne 5 indique l’instruction
expect
, affirmant la condition de succès, c’est-à-dire que la fonctionsum
ajoute les deux arguments, 1 et 2, et renvoie 3.toBe
est l’un des nombreux matchers Jest.
Ajoutez une autre assertion avec la ligne suivante juste après la ligne 5 :expect(sum(1, 2)).not.toBeGreaterThan(3);
- L’ajout de
.not
et.toBeGreaterThan
permet de s’assurer que le nombre ne dépasse pas 3. Vous pouvez ajouter une autre instruction expect avec.not.toBeLessThan(3)
.
Passons maintenant au test du composant Web Lightning.
Les tests Jest pour un composant Web Lightning doivent tester le comportement d’un seul composant de manière isolée, avec un minimum de dépendances aux composants ou services externes.
Répétez le processus avec un fichier test unitTest
.
Ce test permet de vérifier qu’une propriété est définie et, une fois ajoutée au DOM, qu’elle affichera le texte correct. Le fichier unitTest.test.js
a été créé en même temps que le dossier __tests__
lors de l’exécution de la commande SFDX : créer un composant Web Lightning.
- Remplacez le code dans
unitTest.test.js
par le code suivant :import { createElement } from 'lwc'; import UnitTest from 'c/unitTest'; describe('c-unit-test', () => { afterEach(() => { // The jsdom instance is shared across test cases in a single file so reset the DOM while(document.body.firstChild) { document.body.removeChild(document.body.firstChild); } }); it('displays unit status with default unitNumber', () => { const element = createElement('c-unit-test', { is: UnitTest }); expect(element.unitNumber).toBe(5); // Add the element to the jsdom instance document.body.appendChild(element); // Verify displayed greeting const div = element.shadowRoot.querySelector('div'); expect(div.textContent).toBe('Unit 5 alive!'); }); });
- Enregistrez le fichier.
- Dans le terminal, exécutez à nouveau les tests :
npm run test:unit
- Les tests échouent comme suit :
Test Suites: 1 failed, 1 passed, 2 total Tests: 1 failed, 1 passed, 2 total
Examinons ce code test pour déterminer les modifications à apporter avant de mettre à jour le code pour obtenir la réussite du test.
- La ligne 1 est nouvelle. Elle importe la méthode
createElement
à partir de l’infrastructurelwc
. Elle n’est disponible que dans les tests. - La ligne 2 importe la classe
UnitTest
à partir du contrôleur JavaScript du composant. - La ligne 4 démarre le bloc de suite de tests
describe
. - La ligne 5 est une méthode de nettoyage Jest.
afterEach()
est l’une des méthodes de configuration et de nettoyage de Jest. La méthodeafterEach()
s’exécute après chaque test dans le bloc describe dans lequel elle se trouve. Cette méthodeafterEach()
réinitialise le DOM à la fin du test. Jest n’exécute pas de navigateur lors de l’exécution des tests. Jest utilise jsdom pour fournir un environnement qui se comporte de manière semblable au DOM ou au document d’un navigateur. Chaque fichier test reçoit une seule instance de jsdom et les modifications ne sont pas réinitialisées entre les tests à l’intérieur du fichier. Il est recommandé de nettoyer les données entre les tests afin que la sortie d’un test n’ait d’effets sur aucun autre test. Il existe d’autres méthodes de configuration et de nettoyage. Pour en savoir plus, consultez la section Ressources. - La ligne 12 démarre le bloc test
it
. - La ligne 13 indique l’utilisation de la méthode
createElement
importée. Elle crée une instance du composant et l’attribue à l’élément de constante,element
. - À la ligne 16, l’instruction
expect
affirme que la variableunitNumber
est définie sur 5. Nous vérifions queunitNumber
est tout d’abord définie sur 5 ; il s’agit de la première exigence du test. - La ligne 18 permet d’ajouter
element
à la version jsdom dedocument.body
en utilisant la méthodeappendChild
. L’appel joint le composant Web Lightning au DOM et le restitue, ce qui signifie également que les points d’ancrage de cycle de vie connectedCallback() et renderedCallback() sont appelés (nous en parlerons plus tard). - La ligne 20 utilise
querySelector
(une méthode de requête DOM standard) pour rechercher une balisediv
dans le DOM. Utilisezelement.shadowRoot
comme parent de la requête. Il s’agit d’une API de test uniquement qui vous permet d’examiner la frontière fantôme pour inspecter l’arbre fantôme d’un composant. - Enfin, à la ligne 21, l’instruction
expect
affirme que « Unit 5 alive! » se trouve bien dans l’élémenttextContent
de la balisediv
. Il s’agit de la dernière exigence : affirmer que le texte est correct.
Pour que le test réussisse, vous devez ajouter du code aux fichiers HTML et JavaScript unitTest. Nous allons ajouter du code pour répondre aux exigences.
- Cliquez sur le fichier
unitTest.html
pour l’ouvrir. - Remplacez
unitTest.html
par :<template> <lightning-card title="Unit Status" icon-name="standard:bot"> <div class="slds-m-around_medium"> Unit {unitNumber} alive! </div> </lightning-card> </template>
- Enregistrez le fichier.
- Cliquez sur le fichier
unitTest.js
pour l’ouvrir et remplacez-le par :import { LightningElement, api } from 'lwc'; import { sum } from './sum'; export default class UnitTest extends LightningElement { @api unitNumber = sum(2,3); }
- Enregistrez le fichier et exécutez les tests :
npm run test:unit
- Tous les tests réussissent.
Test des mises à jour asynchrones du DOM
Lorsque l’état d’un composant Web Lightning change, le DOM se met à jour de manière asynchrone. Pour vous assurer que votre test attend la fin des mises à jour avant d’évaluer le résultat, renvoyez une promesse résolue. Pour ce faire, reliez le reste de votre code test à la promesse résolue. Jest attend que la chaîne promesse se termine avant de mettre fin au test. Si la promesse se termine avec l’état rejeté, Jest indique l’échec du test.
- Ouvrez
unitTest.test.js
. - Ajoutez ce deuxième test après le dernier test.
Dans ce test, nous souhaitons vérifier qu’une modification de propriété actualise le texte dans le DOM.it('displays unit status with updated unitNumber', () => { const element = createElement('c-unit-test', { is: UnitTest }); // Add the element to the jsdom instance document.body.appendChild(element); // Update unitNumber after element is appended element.unitNumber = 6 const div = element.shadowRoot.querySelector('div'); // Verify displayed unit status expect(div.textContent).toBe('Unit 6 alive!'); });
- Enregistrez le fichier et exécutez les tests.
npm run test:unit
- Vous obtenez ce message d’échec :
Expected: "Unit 6 alive!" Received: "Unit 5 alive!"
Que se passe-t-il ? L’instruction expect
affirme que div.textContext
reçoit toujours « Unit 5 alive! » au lieu de « Unit 6 alive! ». Afin d’appliquer la modification, nous devons l’attendre en renvoyant une promesse Promise
résolue.
- Remplacez l’instruction
expect
qui a échoué par ce qui suit, juste après le commentaire// Verify display unit status
:expect(div.textContent).not.toBe('Unit 6 alive!'); // Return a promise to wait for any asynchronous DOM updates. Jest // will automatically wait for the Promise chain to complete before // ending the test and fail the test if the promise rejects. return Promise.resolve().then(() => { expect(div.textContent).toBe('Unit 6 alive!'); });
- Exécutez le test en utilisant la même commande que la dernière fois, ou en mettant en pratique l’une des autres possibilités présentées dans la section Exécution de tests Jest de l’unité précédente.
- Le test réussit.
Jusqu’ici, tout va bien. Trois tests ont réussi dans deux suites de tests. Vous allez maintenant ajouter un quatrième test afin de pouvoir vérifier que l’état de l’unité est mis à jour lors de la mise à jour d’un champ d’entrée. Pour ce faire, utilisez un événement de modification dans le champ d’entrée.
- Si ce n’est pas déjà fait, ouvrez
unitTest.test.js
. - Ajoutez une ligne après le dernier test que vous avez intégré et ajoutez ce troisième test à la suite :
it('displays unit status with input change event', () => { const element = createElement('c-unit-test', { is: UnitTest }); document.body.appendChild(element); const div = element.shadowRoot.querySelector('div'); // Trigger unit status input change const inputElement = element.shadowRoot.querySelector('lightning-input'); inputElement.value = 7; inputElement.dispatchEvent(new CustomEvent('change')); return Promise.resolve().then(() => { expect(div.textContent).toBe('Unit 7 alive!'); }); });
- Enregistrez le fichier et exécutez le test. Le message d’échec suivant s’affiche :
Vous pouvez observer qu’un seul test a été exécuté et que les deux autres ont été ignorés.
Observons ce qui est testé :
- Vous devriez reconnaître les premières lignes. Vous ajoutez la classe UnitTest à
document.body
, puis vous créez une référence à l’élémentdiv
. - La constante
inputElement
est définie avec une référence à un champ lightning-input. - Ensuite, la valeur de ce champ d’entrée est définie sur 7.
- Nous utilisons ensuite
dispatchEvent
pour déclencher un événement comportant unCustomEvent
en utilisant un type d’événement « change ». - Vous reconnaissez l’élément
Promise
, car il n’a été modifié que selon la valeur du champ d’entrée modifié.
Mettons à jour le code pour qu’il réussisse. Pour ce faire, ajoutez lightning-input
au fichier HTML et la méthode handleChange
au contrôleur JavaScript.
- Ouvrez
unitTest.html
. - Ajoutez le code suivant à l’intérieur de
lightning,-card
et avantdiv
:<lightning-input label="Unit Number" value={unitNumber} onchange={handleChange} > </lightning-input>
- Enregistrez le fichier.
- Ouvrez
unitTest.js
. - Ajoutez le code suivant après l’instruction
@api unitNumber
:handleChange(event) { this.unitNumber = event.target.value; }
- Enregistrez le fichier et exécutez les tests.
- Les tests réussissent en raison de l’élément d’entrée supplémentaire et du gestionnaire JavaScript.
Test des points d’ancrage de cycle de vie
Le cycle de vie des composants Web Lightning est géré par l’infrastructure. L’infrastructure crée des composants, les ajoute au DOM, les supprime du DOM et effectue les mises à jour du DOM chaque fois que l’état d’un composant change. Il existe plusieurs méthodes pour interagir avec le cycle de vie.
Le point d’ancrage de cycle de vie connectedCallback()
se déclenche lorsqu’un composant est inséré dans le DOM. Le point d’ancrage de cycle de vie disconnectedCallback()
se déclenche lorsqu’un composant est supprimé du DOM. Ces points d’ancrage permettent notamment d’enregistrer et de supprimer des écouteurs d’événements.
Consultez le code de lmsSubscriberWebComponent dans le référentiel d’exemples de lwc-recipes pour en découvrir un bon exemple.
Nous allons maintenant nous pencher sur l’écriture de tests Jest pour les services Wire.
Ressources
- Article de blog Salesforce : Test unitaire des composants Web Lightning avec Jest
- Guides pour développeurs : Écriture de tests Jest pour les composants Web Lightning
- Guides pour développeurs : Cycle de vie des composants Web Lightning
- Site externe : Jest : Getting Started
- Site externe : Jest : référence de l’instruction expect
- Site externe : Jest : configuration et désactivation
- Site externe : GitHub : salesforce/sfdx-lwc-jest
- Site externe : GitHub : trailheadapps/lwc-recipes
- Site externe : Wikipédia : Développement piloté par les tests