Add standalone API test runner with accounts and members suites
Custom test framework that starts the backend, creates a test DB, runs migrations, and hits real HTTP endpoints. Supports --suite and --tag filtering. 24 tests covering account CRUD, member inheritance, state normalization, move, search, and auto-generated numbers. Run with bun run api-test.
This commit is contained in:
46
packages/backend/api-tests/lib/client.ts
Normal file
46
packages/backend/api-tests/lib/client.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
export interface ApiResponse<T = unknown> {
|
||||
status: number
|
||||
data: T
|
||||
ok: boolean
|
||||
}
|
||||
|
||||
export interface ApiClient {
|
||||
get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>
|
||||
post<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>
|
||||
patch<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>
|
||||
del<T = unknown>(path: string): Promise<ApiResponse<T>>
|
||||
}
|
||||
|
||||
function buildQueryString(params?: Record<string, unknown>): string {
|
||||
if (!params) return ''
|
||||
const sp = new URLSearchParams()
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
if (v !== undefined && v !== null && v !== '') sp.set(k, String(v))
|
||||
}
|
||||
const qs = sp.toString()
|
||||
return qs ? `?${qs}` : ''
|
||||
}
|
||||
|
||||
export function createClient(baseUrl: string, token?: string): ApiClient {
|
||||
async function request<T>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>> {
|
||||
const headers: Record<string, string> = {}
|
||||
if (body !== undefined) headers['Content-Type'] = 'application/json'
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`
|
||||
|
||||
const res = await fetch(`${baseUrl}${path}`, {
|
||||
method,
|
||||
headers,
|
||||
body: body !== undefined ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
|
||||
const data = await res.json() as T
|
||||
return { status: res.status, data, ok: res.ok }
|
||||
}
|
||||
|
||||
return {
|
||||
get: <T>(path: string, params?: Record<string, unknown>) => request<T>('GET', `${path}${buildQueryString(params)}`),
|
||||
post: <T>(path: string, body?: unknown) => request<T>('POST', path, body),
|
||||
patch: <T>(path: string, body?: unknown) => request<T>('PATCH', path, body),
|
||||
del: <T>(path: string) => request<T>('DELETE', path),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user