Helper response.ts : `body<T>()` pour caster Tuyau strict response shapes (Tuyau type chaque code de statut comme une union, assertStatus ne narrow pas → on cast explicitement vers ApiOk<T>/ApiError/ApiConflict<T>). clients.spec.ts (16 cas) : - POST /clients : refus sans email (422 + field=email), refus SIRET ≠ 14 chiffres, création OK avec UUID + association org, doublon nom case-insensitive (409 + payload existing) - GET /clients : isolation cross-org (user A ne voit pas les clients de B), withStats=1 enrichit (zéros sans factures), recherche q ILIKE - Perms cross-org : user B → 404 sur GET/PATCH d'un client de A, l'objet ne bouge pas plans.spec.ts (7 cas) : - GET /plans : 4 plans pré-fournis avec steps préchargés, isolation cross-org (UUIDs disjoints entre A et B) - GET /plans/:slug : steps ordonnés, 404 si inconnu - PATCH /plans/:slug : remplace les steps en bloc dans une tx, rejette tone invalide, cross-org (B édite SA copie sans toucher celle de A)
19 lines
682 B
TypeScript
19 lines
682 B
TypeScript
/**
|
|
* Tuyau type strictement chaque code de statut possible d'une route. Quand
|
|
* on `assertStatus(...)` puis on lit `.body()`, TS ne narrow pas — il garde
|
|
* l'union.
|
|
*
|
|
* Ce helper sert juste à caster `.body()` vers la forme attendue dans le
|
|
* contexte du test, sans perdre la lisibilité du `.data` / `.errors`.
|
|
*/
|
|
export function body<T>(response: { body(): unknown }): T {
|
|
return response.body() as T
|
|
}
|
|
|
|
export type ApiOk<T> = { data: T }
|
|
export type ApiOkPaged<T> = { data: T; meta: { total: number; page: number } }
|
|
export type ApiError = {
|
|
errors: Array<{ code: string; message: string; field?: string }>
|
|
}
|
|
export type ApiConflict<T> = ApiError & { existing: T }
|