Generate tests for an existing source file using Bun test runner
Generate a test file for an existing source file in x4-mono using Bun's built-in test runner.
The user provides a source file path. If no path given, ask which file to generate tests for.
| Source | Test Location | Pattern |
|---|---|---|
apps/api/src/routers/*.ts | apps/api/src/__tests__/*.test.ts | tRPC caller |
apps/api/src/middleware/*.ts | apps/api/src/__tests__/*.test.ts | app.request() |
apps/api/src/lib/*.ts | apps/api/src/__tests__/*.test.ts | Direct function calls |
packages/shared/utils/*.ts | Co-located |
*.test.ts| Direct function calls |
packages/shared/types/*.ts | Co-located *.test.ts | Zod .safeParse() |
apps/web/src/components/*.tsx | Co-located *.test.tsx | @testing-library/react |
import { describe, test, expect } from 'bun:test';
import { createCallerFactory } from '../trpc';
import { appRouter } from '../routers';
import type { Context } from '../trpc';
import { createMockDb, createTestUser, TEST_USER_ID } from './helpers';
function createTestContext(overrides: Partial<Context> = {}): Context {
return {
db: createMockDb(),
user: null,
req: new Request('http://localhost:3002'),
...overrides,
};
}
const createCaller = createCallerFactory(appRouter);
describe('routerName', () => {
describe('list', () => {
test('returns items', async () => {
const caller = createCaller(createTestContext());
const result = await caller.routerName.list({ limit: 20, offset: 0 });
expect(result.items).toBeArray();
});
});
describe('create', () => {
test('throws UNAUTHORIZED for unauthenticated user', async () => {
const caller = createCaller(createTestContext({ user: null }));
await expect(caller.routerName.create({ name: 'test' })).rejects.toMatchObject({
code: 'UNAUTHORIZED',
});
});
});
});
For tRPC routers:
BAD_REQUESTUNAUTHORIZED (protected procedures)FORBIDDENNOT_FOUNDFor Zod schemas:
For utility functions:
Use createMockDb() from apps/api/src/__tests__/helpers.ts.
import { mock } from 'bun:test';
mock.module('@x4/database', () => ({ db: createMockDb() }));
CRITICAL: bun mock.module runs ALL test files in the same process. First call wins. Extract shared mocks into a single helper file.
env.ts validates eagerly at import time — set env vars BEFORE importing:
process.env.DATABASE_URL ??= 'postgres://test:test@localhost/test';
bun:test (never jest)describe blocks grouped by function/procedure nametoMatchObject for partial error matchingNOT_FOUND, UNAUTHORIZED, FORBIDDEN, BAD_REQUESTapps/api/src/__tests__/helpers.tsbun test <test-file-path> to verify tests pass