ordinarthur fc66d80f56 test(api): setup Japa + tests fonctionnels auth (signup/login/logout/onboarding)
Setup :
- .env.test étoffé : DRIVE_DISK=fs, MAIL_DRIVER=smtp local, OCR_PROVIDER=mock. Réutilise la DB rubis_dev avec global transactions par test (rollback auto, isolation parfaite).
- Schedulers (relance + checkin) détectent NODE_ENV=test et skippent BullMQ.add. Les tasks DB sont quand même créées (utiles pour assertions) mais aucun job orphelin n'arrive en Redis après rollback de tx.
- helpers/auth.ts : factory createTestUser() qui crée org + user + 4 plans pré-fournis dans une tx, retourne user/org/accessToken/bearer header. createTwoOrgs() pour les tests cross-org à venir.

Tests fonctionnels auth (tests/functional/auth.spec.ts) :
- Signup : crée user + org + 4 plans pré-fournis (vérifie les slugs), refuse email mal formé / password court / email déjà pris
- Login : émet AuthSession avec credentials valides, rejette mauvais password / email inconnu
- Bearer auth : 401 sans token, 401 avec token bidon, 200 avec token valide
- Logout : révoque le token courant, requêtes suivantes en 401
- Onboarding : PATCH /organizations/me pose onboardingCompletedAt à la 1re mise du nom, idempotent ensuite

Pour lancer : `pnpm -F api test`
2026-05-06 15:45:11 +02:00

58 lines
1.9 KiB
TypeScript

import User from '#models/user'
import Organization from '#models/organization'
import { provisionDefaultPlans } from '#services/default_plans'
import db from '@adonisjs/lucid/services/db'
let counter = 0
/**
* Helper : crée une organisation + un user + provisionne les 4 plans
* pré-fournis, dans une transaction. Retourne le user, l'org et un
* access token Bearer prêt à être passé en header.
*
* `counter` rend les emails uniques entre les tests d'une même suite —
* sans ça, les tests qui ne tombent pas dans une global tx risquent un
* email_taken.
*/
export async function createTestUser(overrides: {
email?: string
password?: string
fullName?: string
orgName?: string
} = {}) {
counter += 1
const email = overrides.email ?? `test-${counter}-${Date.now()}@rubis.test`
const password = overrides.password ?? 'password123'
const fullName = overrides.fullName ?? `Test User ${counter}`
const orgName = overrides.orgName ?? ''
const { user, org } = await db.transaction(async (trx) => {
const o = await Organization.create({ name: orgName }, { client: trx })
await provisionDefaultPlans(o.id, trx)
const u = await User.create({ email, password, fullName, organizationId: o.id }, { client: trx })
return { user: u, org: o }
})
const token = await User.accessTokens.create(user)
// .release() consomme la valeur — on capture une seule fois.
const accessToken = token.value!.release()
return {
user,
org,
plainPassword: password,
accessToken,
bearer: { Authorization: `Bearer ${accessToken}` },
}
}
/**
* Variante : crée juste 2 users dans 2 orgs distinctes (pour les tests
* cross-org : user A ne peut pas voir/modifier les ressources de B).
*/
export async function createTwoOrgs() {
const a = await createTestUser({ orgName: 'Org A' })
const b = await createTestUser({ orgName: 'Org B' })
return { a, b }
}