Intégrations
Le canal, c’est votre framework de test
Sur ce marché, on n’intègre pas une API : on installe un paquet dans son framework. Nous en publions quatre, et cette page donne l’adresse de chacun, ce qui reste sous condition, et ce que nous ne publierons pas.
Aujourd’hui
Une API HTTP, et rien à installer
Les quatre paquets sont optionnels, et c’est le point : l’attente est faite côté serveur et l’extraction à la réception, donc un test appelle la recherche de messages sans rien installer. Voici un parcours de vérification par email complet, en Playwright, sans un seul paquet à nous.
import { expect, test } from '@playwright/test';
const KEY = process.env.FACTEUR_KEY!;
const INBOX = 'j3k9x2mq';
const DOMAIN = `${INBOX}.inbox.facteur.eu`;
const awaitMessage = (sentTo: string) =>
fetch('https://api.facteur.eu/v1/messages/search', {
method: 'POST',
headers: {
authorization: `Bearer ${KEY}`,
'content-type': 'application/json',
},
body: JSON.stringify({ inbox: INBOX, sentTo, wait: 30_000 }),
}).then((response) => response.json());
test('le lien de vérification active le compte', async ({ page }) => {
const tag = `run-${Date.now()}`;
// Lancée avant le clic : elle attend, et répond dès
// que le message arrive.
const arriving = awaitMessage(`signup+${tag}`);
await page.goto('/signup');
await page.getByLabel('Email').fill(`signup+${tag}@${DOMAIN}`);
await page.getByRole('button', { name: 'Créer mon compte' }).click();
const { messages } = await arriving;
const message = messages[0];
// Le status avant tout champ dérivé du corps.
expect(message.status).toBe('parsed');
await page.goto(message.links[0].href);
await expect(page.getByText('Compte vérifié')).toBeVisible();
});La requête part avant le clic
Elle attend, et répond à l’instant où le message arrive, pas à l’échéance. Lancée après, elle courrait après un message déjà là.
Le sous-adressage sépare les tests
Tout ce qui suit le « + » est à vous. C’est ce qui permet à deux tests de partager une inbox sans se voler leurs messages.
On lit status avant tout champ dérivé
Un message accepté existe avant d’être analysé : pendant quelques millisecondes il n’a ni sujet, ni code, ni liens. C’est ce qui sépare « pas de code dans ce message » de « le code n’est pas encore extrait ».
La clé se lit dans l’environnement
Jamais écrite dans le test, jamais passée en argument. C’est la convention que les greffons reprennent.
Ce que nous publions
Un greffon avant une bibliothèque, et JavaScript avant tout le reste
L’ordre n’est pas négociable en cours de route, et il n’est pas une préférence de goût : il suit une mesure, refaite avant chaque livraison.
| Livrable | État | Ce qui le débloque |
|---|---|---|
| Une bibliothèque Node minimale Ouvrir une boîte, attendre un message, le lire avec ce qui en a été extrait, purger. C’est tout, et c’est délibéré : le périmètre resserré du produit vaut aussi pour sa surface publique. Zéro dépendance : une suite de tests ne veut pas d’un arbre de dépendances. | Publié@facteur-eu/sdk | Le socle du greffon, et notre première traction publiquement mesurable. |
| Un greffon Playwright Une adresse dérivée du test lui-même, donc deux tests en parallèle ne lisent jamais le même courrier, et un test rejoué ne relit pas celui de sa première tentative. Les assertions sont rejouées par le moteur de Playwright, l’attente s’arrête dans le budget du test, et le message reçu est attaché au rapport : un échec montre le courrier arrivé, pas seulement une ligne rouge. | Publiéplaywright-facteur | Le canal le plus grand du marché, et personne n’y est. |
| Un greffon Cypress Une commande enregistrée qui rend une chaîne chaînable, plutôt qu’une fixture. Le travail est commun à 80 % avec le précédent. | Publiécypress-facteur | Le canal que la concurrence a déjà prouvé, et 80 % du travail partagé avec le greffon Playwright. |
| Un initialiseur npm create Du dépôt vide au premier test qui passe en une commande. | Publiécreate-facteur | La première minute d’un intégrateur, qui est celle qui décide. |
| Une bibliothèque Python Le seul second écosystème crédible. Nous ne le prenons pas par anticipation : le déclencheur est un chiffre, pas une impression. | Sous condition | Déclencheur : un usage mensuel stable du greffon Playwright, et une demande Python arrivée par les issues ou le support. |
| Les autres écosystèmes .NET · Ruby · PHP · Java · Go · Swift · Dart Pas au programme, et nous préférons l’écrire. La demande y est deux à trois ordres de grandeur plus faible que sur npm, et l’acteur de référence, qui en maintient dix, laisse son paquet le plus ancien trois générations majeures derrière sa bibliothèque principale. Neuf bibliothèques sans usage mesuré sont neuf dettes, pas une couverture. | Non prévu | Rien. Une case cochée à l’achat n’est pas une intégration. |
Pourquoi Playwright d’abord
Le plus grand canal du marché est inoccupé
Relevé sur npm, à la date indiquée, et rejouable par n’importe qui.
| Framework | Installations mensuelles | Greffon concurrent |
|---|---|---|
| @playwright/test | 201 269 570 | Aucun |
| cypress | 30 638 605 | Deux |
Relevé sur npm le 17 août 2026
Aucun de nos concurrents n’a de greffon Playwright ; deux en ont un pour Cypress. Leurs mots-clés npm portent encore « selenium », « webdriver » et « nightwatch » : leur référencement a une génération de retard sur les usages.
La réserve était écrite avant le code : personne n’y est, et il y avait peut-être une raison. Les fixtures de Playwright rendent un greffon moins indispensable qu’avec Cypress, donc le point de contrôle était qu’une fixture de dix lignes dans la documentation suffise. Elle ne suffisait pas : l’adresse dérivée du test, la reprise, le budget d’attente et le message attaché au rapport ne tiennent pas en dix lignes. C’est ce qui a décidé la publication.
Rien à installer pour un premier test
Une clé en lecture seule, une inbox, et l’exemple ci-dessus. Le plan gratuit ne demande pas de carte bancaire.