projects.test.ts57 lines · main
| 1 | // apps/api/src/routes/projects.test.ts |
| 2 | // |
| 3 | // Probe test for Task A5: confirm `POST /v1/projects` is reachable under a |
| 4 | // CLI-minted Bearer JWT and is NOT shot down by the CSRF origin guard. |
| 5 | // |
| 6 | // Env vars must be set BEFORE any module that reads them is imported. The |
| 7 | // auth + db modules call into env at evaluation, so we mutate process.env |
| 8 | // first and pull every framework module in via dynamic import — mirroring |
| 9 | // the pattern in apps/api/src/routes/auth-cli.test.ts. |
| 10 | // |
| 11 | // We don't try to stand up postgres in unit tests. The KEY assertion is |
| 12 | // that the response status is NOT 403 csrf_origin_rejected. A 401 from |
| 13 | // the bearer user-lookup (missing row) or a 500 from the DB being |
| 14 | // unreachable are both acceptable — both prove the request made it past |
| 15 | // CSRF and reached the route handler / requireAuth bearer branch. |
| 16 | |
| 17 | const ORIGINAL_SECRET = process.env.BRIVEN_BETTER_AUTH_SECRET; |
| 18 | const ORIGINAL_DB_URL = process.env.BRIVEN_DATABASE_URL; |
| 19 | process.env.BRIVEN_BETTER_AUTH_SECRET = ORIGINAL_SECRET ?? 'a'.repeat(32); |
| 20 | process.env.BRIVEN_DATABASE_URL = ORIGINAL_DB_URL ?? 'postgres://test:test@127.0.0.1:5/test'; |
| 21 | |
| 22 | import { afterAll, describe, expect, it } from 'bun:test'; |
| 23 | import type { AppEnv } from '../types/app-env.js'; |
| 24 | |
| 25 | describe('POST /v1/projects via CLI JWT', () => { |
| 26 | it('accepts a Bearer cli token without rejecting on CSRF', async () => { |
| 27 | const { Hono } = await import('hono'); |
| 28 | const { signCliToken } = await import('../lib/cli-jwt.js'); |
| 29 | const { csrfOriginCheck } = await import('../middleware/csrf.js'); |
| 30 | const { projectsRouter } = await import('./projects.js'); |
| 31 | |
| 32 | const app = new Hono<AppEnv>(); |
| 33 | app.use('*', csrfOriginCheck()); |
| 34 | app.route('/', projectsRouter); |
| 35 | |
| 36 | const token = await signCliToken('u_proj_post_test'); |
| 37 | const res = await app.request('/v1/projects', { |
| 38 | method: 'POST', |
| 39 | headers: { |
| 40 | authorization: `Bearer ${token}`, |
| 41 | 'content-type': 'application/json', |
| 42 | }, |
| 43 | body: JSON.stringify({ name: 'cli-post-test', region: 'eu-west' }), |
| 44 | }); |
| 45 | |
| 46 | // No DB → 401 from bearer user-lookup or 500 from db acceptable. |
| 47 | // KEY assertion: status is NOT 403 csrf_origin_rejected. |
| 48 | expect(res.status).not.toBe(403); |
| 49 | }); |
| 50 | }); |
| 51 | |
| 52 | afterAll(() => { |
| 53 | if (ORIGINAL_SECRET === undefined) delete process.env.BRIVEN_BETTER_AUTH_SECRET; |
| 54 | else process.env.BRIVEN_BETTER_AUTH_SECRET = ORIGINAL_SECRET; |
| 55 | if (ORIGINAL_DB_URL === undefined) delete process.env.BRIVEN_DATABASE_URL; |
| 56 | else process.env.BRIVEN_DATABASE_URL = ORIGINAL_DB_URL; |
| 57 | }); |