Wiki/bridge/tests/helpers/fixtures.ts
Corentin JOGUET c8e9b4d4ea
Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
feat(bridge): bloc 3 — routes REST Tier 1 + auth + repos Baserow (10 endpoints)
Wiring HTTP du bridge service. 10 endpoints livres (cf docs/19 §6.1-6.5) :
- GET /api/v1/personnes (+ /:id, + /:id/dashboard)
- GET /api/v1/formations (+ /:id avec rollups blocs/modules)
- GET /api/v1/projets (+ /:id avec rollups taches)
- POST /api/v1/modules/:id/attribuer (RG-01 -> 422, role/heures invalides -> 400)
- POST /api/v1/interventions (validation role developpeur + heures > 0)
- PATCH /api/v1/attributions/:id/heures-realisees (409 si annule/realise)

Layers ajoutees :
- src/middleware/auth.ts : Bearer brg_*, scopes JSON-encoded BRIDGE_API_TOKENS, admin:* wildcard
- src/middleware/error-handler.ts : BridgeError -> JSON shape standard
- src/lib/container.ts : DI singleton (Baserow + Redis + 9 repos), setContainer testable
- src/lib/http.ts : parseListQuery + parseBody zod helper
- src/repos/baserow-repo.ts : BaseRepo<T> abstrait + 9 sous-classes (mapping Row<->Domain)
- src/routes/{personnes,formations,projets,modules,interventions,attributions}.ts

src/index.ts reecrit : buildApp() + initContainer + auth sur /api/v1/* + ready check Baserow+Redis.

Tests : 163/163 verts (12 suites domain + 8 nouvelles : auth, repos, 6 routes).
Coverage src global : 70.77% (cible 60%). Domain 97.86%, routes 96%, middleware 86%.

Choix : BaseRepo abstrait (pas mega-generic, Ockham) ; FakeRepos in-memory pour tests routes
(pas de testcontainers ici, c'est Bloc 7) ; mapping erreurs domain -> HTTP par message texte
(fragile, sera refactor en DomainError typees au Bloc 3.2).

Hors scope (a venir) :
- Bloc 5 : rate limiting Redis
- Bloc 7 : webhook handlers Baserow + sync bidirec + cache invalidation
- Bloc 3.2 : routes /docmost/*, /sync/*, /rapports/*

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:01:36 +02:00

101 lines
2.6 KiB
TypeScript

/**
* Fixtures domain partagees par les tests routes.
*/
import { Decimal } from 'decimal.js';
import { Attribution } from '../../src/domain/attribution.js';
import { Bloc } from '../../src/domain/bloc.js';
import { Formation } from '../../src/domain/formation.js';
import { Intervention } from '../../src/domain/intervention.js';
import { Module } from '../../src/domain/module.js';
import { Personne } from '../../src/domain/personne.js';
import { Projet } from '../../src/domain/projet.js';
import { Tache } from '../../src/domain/tache.js';
import type { Role } from '../../src/domain/types.js';
export function makePersonne(over: Partial<{ id: number; roles: Role[] }> = {}): Personne {
return new Personne({
id: over.id ?? 1,
nom: 'Dupont',
prenom: 'Pierre',
email: 'pierre@acadenice.fr',
capaciteAnnuelle: new Decimal(1000),
splitFormationPct: new Decimal(60),
splitAgencePct: new Decimal(40),
roles: new Set<Role>(over.roles ?? ['formateur']),
statut: 'actif',
});
}
export function makeFormation(id = 10): Formation {
return new Formation({
id,
nom: 'Dev Fullstack',
heuresTotales: new Decimal(500),
statut: 'actif',
});
}
export function makeBloc(id = 100, formationId = 10): Bloc {
return new Bloc({
id,
formationId,
nom: 'Bloc JS',
heuresPrevues: new Decimal(100),
ordre: 1,
});
}
export function makeModule(id = 200, blocId = 100): Module {
return new Module({
id,
blocId,
nom: 'JS Fondamentaux',
heuresPrevues: new Decimal(30),
});
}
export function makeAttribution(
over: Partial<{ id: number; moduleId: number; personneId: number }> = {},
): Attribution {
return new Attribution({
id: over.id ?? 500,
moduleId: over.moduleId ?? 200,
personneId: over.personneId ?? 1,
heuresAttribuees: new Decimal(10),
statut: 'planifie',
});
}
export function makeProjet(id = 300, clientId = 50): Projet {
return new Projet({
id,
clientId,
nom: 'Site Acme',
chargeHeures: new Decimal(80),
statut: 'en_cours',
});
}
export function makeTache(id = 400, projetId = 300): Tache {
return new Tache({
id,
projetId,
titre: 'Setup repo',
chargeHeures: new Decimal(8),
statut: 'todo',
});
}
export function makeIntervention(
over: Partial<{ id: number; tacheId: number; personneId: number }> = {},
): Intervention {
return new Intervention({
id: over.id ?? 600,
tacheId: over.tacheId ?? 400,
personneId: over.personneId ?? 2,
heures: new Decimal(2),
date: new Date('2026-05-01'),
statut: 'realise',
});
}