me.test.ts58 lines · main
1// apps/api/src/routes/me.test.ts
2//
3// Env vars must be set BEFORE any module that reads them is imported. auth.ts
4// + cli-jwt.ts read BRIVEN_BETTER_AUTH_SECRET at evaluation time, so we
5// mutate process.env first and pull every framework module in via dynamic
6// import to keep the invariant when this file is loaded alongside siblings
7// that may have already cached the modules.
8//
9// The test mounts the meRouter on a fresh Hono and hits /v1/me/projects with
10// a CLI bearer token. In a test environment without postgres the bearer
11// branch in requireAuth() fails to load the user row and returns 401, which
12// is acceptable — it proves the route is mounted and the handler compiled.
13// The 200 branch (when DB is reachable) additionally asserts the six-field
14// shape the CLI's `existingBranch` consumes.
15
16const ORIGINAL_SECRET = process.env.BRIVEN_BETTER_AUTH_SECRET;
17const ORIGINAL_DB_URL = process.env.BRIVEN_DATABASE_URL;
18process.env.BRIVEN_BETTER_AUTH_SECRET = ORIGINAL_SECRET ?? 'a'.repeat(32);
19process.env.BRIVEN_DATABASE_URL = ORIGINAL_DB_URL ?? 'postgres://test:test@127.0.0.1:5/test';
20
21import { afterAll, describe, expect, it } from 'bun:test';
22import type { AppEnv } from '../types/app-env.js';
23
24describe('GET /v1/me/projects shape', () => {
25 it('handler returns 200 or auth-error and never crashes on shape introspection', async () => {
26 const { Hono } = await import('hono');
27 const { meRouter } = await import('./me.js');
28 const { signCliToken } = await import('../lib/cli-jwt.js');
29
30 const app = new Hono<AppEnv>();
31 app.route('/', meRouter);
32
33 const token = await signCliToken('u_me_projects_test');
34 const res = await app.request('/v1/me/projects', {
35 headers: { authorization: `Bearer ${token}` },
36 });
37
38 // No DB in test env → 401 from bearer branch is fine, proves handler ran.
39 expect([200, 401, 500]).toContain(res.status);
40 if (res.status === 200) {
41 const body = (await res.json()) as { projects: Array<Record<string, unknown>> };
42 if (body.projects.length > 0) {
43 for (const p of body.projects) {
44 for (const k of ['id', 'slug', 'name', 'region', 'tier', 'orgName']) {
45 expect(p).toHaveProperty(k);
46 }
47 }
48 }
49 }
50 });
51});
52
53afterAll(() => {
54 if (ORIGINAL_SECRET === undefined) delete process.env.BRIVEN_BETTER_AUTH_SECRET;
55 else process.env.BRIVEN_BETTER_AUTH_SECRET = ORIGINAL_SECRET;
56 if (ORIGINAL_DB_URL === undefined) delete process.env.BRIVEN_DATABASE_URL;
57 else process.env.BRIVEN_DATABASE_URL = ORIGINAL_DB_URL;
58});