Passer au contenu principal

Comment ajouter et utiliser une étape JavaScript

Écrit par Ines

Qu'est-ce qu'une étape JavaScript ?

Une étape JavaScript vous permet d'exécuter votre propre code JavaScript à un moment précis d'un test. Utilisez-la lorsqu'une étape en langage naturel ou une étape Web ne permet pas d'exprimer ce dont vous avez besoin : lire une valeur calculée, combiner deux lectures du DOM, appeler une API pour vérifier l'état du backend ou générer des données de test dynamiques.

Vous écrivez le corps d’une fonction Step(). Celle-ci vous fournit un contexte prêt à l’emploi (vos variables, la page, un client API, la console, le réseau et les étapes précédentes), et vous renvoyez un résultat : l’étape réussit ou échoue.

Quand l’utiliser

  • Capturer une valeur : lire une valeur sur la page (ou en calculer une) et la stocker dans une variable pour les étapes suivantes.

  • Valider l’état du backend : appeler une API interne ou externe en cours de test et comparer le résultat à ce qu’affiche l’interface utilisateur.

  • Vérifier le trafic réseau : s’assurer que la page a envoyé la bonne requête avec la bonne charge utile.

  • Générer des données dynamiques : générer des dates, des références ou des valeurs composites afin que les tests ne reposent pas sur des données codées en dur.

  • Débloquer la page : fermer une bannière de cookies ou définir une valeur dans localStorage dont dépend une étape ultérieure.

Quand utiliser une étape dédiée à la place

Pour les actions courantes, les étapes pré-conçues sont plus simples. Optez pour une étape JavaScript lorsque vous avez besoin d’une véritable logique.

Si vous souhaitez…

Préférez

Cliquer, taper, sélectionner, survoler, attendre un élément

Une étape en langage naturel ou uneétape Web

Appeler une API et vérifier sa réponse en tant qu’étape à part entière

Une étape d’appel d’API

Dériver ou arrêter l'exécution en fonction d'une condition simple

Une étape conditionnelle (IF)

Exécuter une logique personnalisée qu'aucune des étapes ci-dessus ne permet d'exprimer

Une étape JavaScript

Comment ajouter une étape JavaScript

  1. Ouvrez votre scénario de test.

  2. Cliquez sur « Ajouter une nouvelle étape ».

  3. Dans le champ « Type d’étape », sélectionnez « Étape JavaScript ».

  4. Ajoutez une description: un résumé concis et compréhensible par l'utilisateur expliquant ce que fait l'étape. Ce champ est obligatoire et permet d'identifier l'étape dans la vue d'exécution.

  5. Écrivez votre code dans l'éditeur.

La fonction Step()

L'éditeur s'ouvre avec un squelette. Vous écrivez le corps de la fonction ; la signature et l'accolade de fermeture restent en place.

function Step(response, variables, DOM, api_client, console, network, test_steps) {
// Write your logic here.
return response.Success();
}

Chaque étape renvoie un résultat: response.Success() en cas de réussite, ou response.Fail('motif') en cas d'échec.

Les objets de contexte

Votre fonction Step() reçoit sept objets. Ils sont prêts à l'emploi, sans qu'il soit nécessaire de les importer ou de les configurer.

Objet

Ce qu’il vous apporte

response

Le générateur de résultat. Renvoyez response.Success() ou response.Fail('reason') pour indiquer au programme d'exécution ce qui s'est passé.

variables

Lire et écrire les variables Thunders. variables['MY_VAR'] renvoie la valeur actuelle ; lui attribuer une valeur met à jour la variable pour le reste du test. Fonctionne avec les variables d’environnement, de projet et de lot CSV.

DOM

Le document de la page en temps réel. Utilisez les API DOM standard telles que DOM.querySelector(...), .textContent, .getAttribute(...), etc.

api_client

Un client HTTP permettant d'appeler des API depuis l'étape. Voir Appel d'API.

console

console.log, console.info, console.warn, console.error. Les messages s'affichent dans le résultat de l'étape dans la vue d'exécution. Il s'agit de votre principal outil de débogage.

network

Une vue en lecture seule des requêtes effectuées par la page. network.requests est une liste de { url, method, status, headers, body }. Voir Lecture des requêtes réseau.

test_steps

Une liste en lecture seule des étapes déjà exécutées. Chacune comporte un nom (le texte de l’étape), un résultat (réussite, échec ou ignorée) et une durée en ms, ce qui permet à votre étape de réagir à ce qui s’est passé précédemment.

Méthodes de réponse

Renvoyez exactement l’une de ces méthodes.

Méthode

Comportement

response.Success()

L'étape est réussie et l'exécution passe à l'étape suivante.

response.Success(value)

Réussit et associe la valeur au résultat de l'étape, ce qui est pratique pour afficher une réponse API ou un objet calculé dans la vue d'exécution.

response.Fail('motif')

L'étape échoue. La chaîne de caractères indiquant la raison s'affiche dans le récapitulatif de l'exécution, et celle-ci s'arrête (comme pour les autres échecs d'étape).

Utilisation des variables

Il existe deux façons d’utiliser les variables, qui se complètent :

  • Interpolation avec [VARIABLE]: Thunders remplace tout token [MY_VAR] dans votre code par la valeur de la variable avant l'exécution du script, comme dans les autres étapes.

  • L’objet variables: variables['MY_VAR'] lit la valeur actuelle au moment de l’exécution, et une affectation (variables['MY_VAR'] = 'nouvelle valeur') met à jour la variable pour le reste du test.

Appel d’API avec api_client

api_client vous permet d’appeler une API depuis l’étape et de vérifier le résultat, par exemple pour confirmer que le backend correspond bien à ce qu’affiche l’interface utilisateur.

Méthode

Description

api_client.get(url, opts)

Envoie une requête GET.

api_client.post(url, body, opts)

Envoie une requête POST avec un corps JSON.

api_client.put(url, body, opts)

Envoie une requête PUT avec un corps JSON.

api_client.patch(url, body, opts)

Envoie une requête PATCH avec un corps JSON.

api_client.delete(url, opts)

Envoie une requête DELETE.

Chaque appel est asynchrone, il faut donc l'attendre. Transmettez des en-têtes personnalisés via opts, par exemple { headers: { 'X-Env': 'staging' } }. Chaque appel vous renvoie une réponse que vous pouvez lire :

{
status, // HTTP status code, e.g. 200
ok, // true when status is 2xx
data, // the parsed response body
headers // response headers
}
function Step(response, variables, DOM, api_client, console, network, test_steps) {
const res = await api_client.get(`/api/carts/${variables['CART_ID']}`);
if (!res.ok) {
return response.Fail(`Cart lookup failed with status ${res.status}`);
}
return response.Success(res.data);
}

Lecture des requêtes réseau

network.requests est une liste en lecture seule des requêtes effectuées par la page pendant l’exécution de l’étape, chacune contenant { url, method, status, headers, body } (les corps JSON sont analysés pour vous). Utilisez-la pour confirmer qu’une requête a bien été envoyée, vérifier un code d’état ou lire le contenu d’une réponse.

function Step(response, variables, DOM, api_client, console, network, test_steps) {
const analytics = network.requests.find(r => r.url.includes('/analytics/event'));
if (!analytics) {
return response.Fail('No analytics event was fired');
}
if (analytics.body.event_name !== 'checkout_completed') {
return response.Fail(`Wrong event name: ${analytics.body.event_name}`);
}
return response.Success();
}

Boucles et attente

Votre code s'exécute comme une fonction asynchrone : await fonctionne partout dans le corps de la fonction, et les structures de contrôle JavaScript habituelles, for, while, try/catch, se comportent comme prévu. Le squelette affiche function Step(...) pour plus de lisibilité, mais l'exécution est bien asynchrone.

Cela rend possibles deux usages courants.

Répéter une action plusieurs fois :

function Step(response, variables, DOM, api_client, console, network, test_steps) {
for (let i = 1; i <= 10; i++) {
DOM.querySelector('#add-item').click();
await new Promise(r => setTimeout(r, 100));
}
return response.Success();
}

Attendre qu'une condition soit remplie (polling) :

function Step(response, variables, DOM, api_client, console, network, test_steps) {
let rows = 0;
for (let i = 0; i < 10; i++) {
rows = DOM.querySelectorAll('.result-row').length;
if (rows >= 5) break;
await new Promise(r => setTimeout(r, 500));
}
console.log('rows found:', rows);
if (rows < 5) return response.Fail(`Only ${rows} rows after 5 seconds`);
return response.Success({ rows });
}

Une boucle répète du travail à l'intérieur d'une seule étape. Répéter des étapes Thunders elles-mêmes — réexécuter les étapes 3 à 7 jusqu'à ce qu'une condition soit remplie — n'est pas possible aujourd'hui. Une étape conditionnelle peut sauter vers une étape ultérieure ou arrêter l'exécution, mais elle ne peut pas revenir en arrière.

Bon à savoir

  • Limite de 90 secondes : Une étape JavaScript est interrompue au bout de 90 secondes et signalée comme un dépassement de délai : gardez le temps d'attente total d'une boucle bien en dessous de cette limite.

  • Renvoyez toujours une réponse : Une étape qui se termine sans renvoyer response.Success() ou response.Fail('motif') est signalée comme un échec.

  • Les variables secrètes ne sont pas exposées : Les variables marquées comme secrètes ne peuvent pas être lues via variables[...], et leurs valeurs sont masquées dans le script comme dans la sortie console affichée dans la vue d'exécution.

  • Ni import ni paquets npm :Il n'y a pas de système de modules dans l'étape. Vous disposez de tout l'environnement du navigateur (fetch, JSON, Date, localStorage, etc.) ainsi que des bibliothèques que votre propre application charge déjà sur la page.

  • Les URL relatives dans api_client sont résolues par rapport à l'origine de la page courante : /api/carts/123 fonctionne. Les URL absolues sont utilisées telles quelles.

  • Les itérations d'une boucle ne sont pas détaillées : L'étape entière constitue un seul succès ou échec dans la vue d'exécution ; utilisez console.log pour voir ce qui s'y est passé.

Exemples

1. Capturer une valeur de la page dans une variable

function Step(response, variables, DOM, api_client, console, network, test_steps) {
const orderId = DOM.querySelector('[data-order-id]').textContent;
variables['ORDER_ID'] = orderId;
return response.Success();
}

Après avoir validé une commande, l’ID de commande s’affiche sur la page de confirmation. Enregistrez-le afin que les étapes suivantes puissent accéder à /orders/[ORDER_ID] ou appeler une API avec cette valeur.

2. Valider l’interface utilisateur par rapport au backend

function Step(response, variables, DOM, api_client, console, network, test_steps) {
const uiTotal = parseFloat(DOM.querySelector('.cart-total').textContent.replace('$', ''));
const res = await api_client.get(`/api/carts/${variables['CART_ID']}`);
if (res.data.total !== uiTotal) {
return response.Fail(`Cart mismatch: UI ${uiTotal}, API ${res.data.total}`);
}
return response.Success();
}

Détecte les bogues d’intégrité des données que les tests d’interface utilisateur purs ne repèrent pas. La page s’affiche correctement, mais le backend ne valide pas les données.

3. Créer des données de test dynamiques

function Step(response, variables, DOM, api_client, console, network, test_steps) {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
variables['BILLING_PERIOD'] = `${year}-${month}`;
variables['INVOICE_REF'] = `INV-${variables['CUSTOMER_ID']}-${year}${month}`;
return response.Success();
}

Évitez les dates codées en dur qui ne fonctionneront plus le mois prochain, et générez des valeurs composites à partir de variables existantes.

4. Débloquer la page

function Step(response, variables, DOM, api_client, console, network, test_steps) {
// A cookie banner intercepts the login button on staging, so dismiss it.
const banner = DOM.querySelector('.cookie-banner');
if (banner) banner.remove();
return response.Success();
}

5. Réagir à une étape précédente

function Step(response, variables, DOM, api_client, console, network, test_steps) {
const login = test_steps.find(s => s.name.includes('Log in'));
if (login && login.duration > 5000) {
variables['USE_RECOVERY_FLOW'] = 'true';
console.warn('Login was slow, switching to the recovery flow');
}
return response.Success();
}

Enregistrez un indicateur dans une variable, puis effectuez une branche en fonction de celui-ci à l’aide d’une étape conditionnelle suivante.

Affichage des résultats dans une exécution de test

Dans la vue d'exécution, sélectionnez l'étape JavaScript pour ouvrir son onglet JavaScript. Celui-ci affiche :

  • Un bloc « Résultat », la valeur renvoyée par votre étape (le cas échéant) et la sortie de votre console. Si le code a rencontré une erreur, vous verrez également le message et le numéro de ligne; cliquez dessus pour ouvrir l'éditeur à cette ligne.

Résultat

Signification

Succès

L'étape a renvoyé response.Success(). Elle est marquée en vert et l'exécution se poursuit.

Échec

L'étape a renvoyé response.Fail('reason'). La raison est affichée et l'exécution s'arrête.

Erreur

Une erreur s'est produite dans votre code (par exemple, une faute de frappe ou un élément manquant). Le message d'erreur et le numéro de ligne s'affichent pour vous permettre de corriger l'erreur.

Avez-vous trouvé la réponse à votre question ?