test(auth): enrichit l'assertion signup duplicate email (format de réponse)
All checks were successful
Build & Deploy API / build-and-deploy (push) Successful in 1m18s
All checks were successful
Build & Deploy API / build-and-deploy (push) Successful in 1m18s
Le test "refuse un email déjà pris" vérifiait seulement `assertStatus(422)`.
On enrichit pour vérifier la shape complète :
- body.errors est un array non-vide
- au moins une entrée a `field === 'email'`
- cette entrée a un code et un message strings
Pourquoi : un mutation test du 2026-05-18 a révélé qu'un simple
`assertStatus(422)` laissait passer le retrait du `.unique()` côté
validator Vine — la contrainte DB UNIQUE(email) prenait le relais
silencieusement via le handler PG 23505, qui renvoie le même 422.
Apprentissage : .unique() Vine et DB unique sont équivalents côté
contrat API (le handler `23505` met `field='email'` identique). Le
.unique() Vine est donc une optimisation (skip round-trip DB) plutôt
qu'une garantie de sécurité. On garde la double protection comme
best practice (defense-in-depth).
Le test enrichi ne catche pas le retrait du .unique() spécifiquement
(les 2 paths sont indistinguables côté client) MAIS catche des
régressions plus graves :
- Si le handler 23505 casse → 500 au lieu de 422
- Si `field` n'est plus posé → SPA ne peut plus highlight l'input
- Si la shape {errors:[...]} change → contrat API cassé
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
0ecf8ad40f
commit
5b8898ba9c
@ -55,7 +55,10 @@ test.group('Auth — POST /auth/signup', (group) => {
|
||||
response.assertStatus(422)
|
||||
})
|
||||
|
||||
test('refuse un email déjà pris (422)', async ({ client }) => {
|
||||
test('refuse un email déjà pris (422 + erreur typée sur le champ email)', async ({
|
||||
client,
|
||||
assert,
|
||||
}) => {
|
||||
await client.post('/api/v1/auth/signup').json({
|
||||
email: 'twice@spec.test',
|
||||
password: 'password123',
|
||||
@ -68,6 +71,30 @@ test.group('Auth — POST /auth/signup', (group) => {
|
||||
fullName: 'Second',
|
||||
})
|
||||
response.assertStatus(422)
|
||||
|
||||
// Vérifie le format précis de la réponse — pas juste un 422 vague.
|
||||
// Permet de détecter une régression où :
|
||||
// 1. La validation unique disparait (validator Vine ou contrainte DB)
|
||||
// 2. Le handler d'exception change la shape (`{ errors: [{ ... }] }`)
|
||||
// 3. Le `field` n'est plus posé sur l'erreur (le SPA s'en sert pour
|
||||
// mettre en rouge le bon input)
|
||||
//
|
||||
// Ce test a été enrichi suite à un mutation test du 2026-05-18 qui a
|
||||
// révélé qu'un seul `assertStatus(422)` laissait passer le retrait
|
||||
// du `.unique()` côté validator (la contrainte DB prenait le relais
|
||||
// silencieusement, sans test).
|
||||
const body = response.body() as {
|
||||
errors?: Array<{ code?: string; field?: string; message?: string }>
|
||||
}
|
||||
assert.isArray(body.errors)
|
||||
assert.isAtLeast(body.errors!.length, 1)
|
||||
const emailError = body.errors!.find((e) => e.field === 'email')
|
||||
assert.exists(
|
||||
emailError,
|
||||
"le payload d'erreur doit avoir au moins une entrée avec field='email'"
|
||||
)
|
||||
assert.isString(emailError!.code)
|
||||
assert.isString(emailError!.message)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user