Aller au contenu

Recevoir un e-mail dans un test Cypress

Cypress exécute votre test dans le navigateur. Cela pose un problème pour lire un e-mail : une clé écrite dans une spec est servie à une page, et quiconque ouvre les outils de développement du navigateur la lit. Une tâche Node règle cela, parce qu’elle tourne dans le processus de Cypress et que la clé n’atteint jamais la page.

Cette page appelle l’API directement. Aucun plugin Facteur pour Cypress n’est encore publié : il n’y a pas de paquet à installer.

  1. Une clé d’API en lecture seule, gardée dans les secrets de votre intégration continue sous le nom FACTEUR_API_KEY. Le guide de démarrage montre comment la créer.
  2. L’identifiant de votre inbox : les huit caractères avant .inbox dans son adresse. C’est j3k9x2mq dans les exemples.
cypress.config.js
import { defineConfig } from 'cypress'
export default defineConfig({
e2e: {
setupNodeEvents(on) {
on('task', {
async waitForEmail({ sentTo }) {
const search = new URLSearchParams({ inbox: 'j3k9x2mq', sentTo, wait: '30000' })
const response = await fetch(`https://api.facteur.eu/messages?${search}`, {
headers: { authorization: `Bearer ${process.env.FACTEUR_API_KEY}` },
})
if (!response.ok) throw new Error(`Facteur answered ${response.status}`)
const { messages } = await response.json()
return messages[0] ?? null
},
})
},
},
})
it('the code arrives by email', () => {
const tag = `signup-a${Cypress.currentRetry ?? 0}-${Date.now()}`
// Le parcours d'inscription de votre propre application.
cy.visit('/signup')
cy.get('[name=email]').type(`${tag}@j3k9x2mq.inbox.facteur.eu`)
cy.contains('button', 'Create my account').click()
cy.task('waitForEmail', { sentTo: tag }, { timeout: 40000 }).should((message) => {
expect(message, 'an email arrived').to.not.be.null
expect(message.otp).to.match(/^[0-9]{6}$/)
})
})

L’attente se passe du côté de Facteur : la requête reste ouverte jusqu’à l’arrivée du message, pendant le temps que vous fixez. Une pause fixe est trop courte sur une machine chargée, et du temps perdu à chaque autre exécution.

Le timeout de cy.task doit rester au-dessus du wait envoyé à l’API : quarante secondes pour une attente de trente. Sinon Cypress abandonne la tâche avant l’arrivée de la réponse, et l’échec accuse la mauvaise cause.

Dans ce test, la recherche part après le clic, parce que Cypress exécute ses commandes l’une après l’autre. Rien n’est perdu : la recherche regarde une fois avant d’attendre, donc un message arrivé pendant le clic revient à ce premier regard.

Cypress.currentRetry vaut 0 à la première tentative. Sans lui dans l’adresse, un test relancé lit l’e-mail de sa première tentative et réussit à tort, justement quand quelque chose est déjà instable.

Toute adresse qui finit par le domaine de l’inbox arrive dedans, sans rien créer. Chaque test reçoit à sa propre adresse dans la même inbox : une offre qui n’a qu’une inbox suffit donc pour toute une suite.