import { mkdtempSync, rmSync, mkdirSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; import { initDb } from '../../src/db/schema.ts'; import { createServer } from '../../src/server.ts'; import type { Config } from '../../src/config.ts'; import type Database from 'better-sqlite3'; import type { FastifyInstance } from 'fastify'; export async function loginAs(app: FastifyInstance, username: string, password: string): Promise { const res = await app.inject({ method: 'POST', url: '/api/v1/auth/login', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username, password }), }); const cookie = res.headers['set-cookie'] as string; return cookie.split(';')[0].replace('token=', ''); } interface MultipartFile { filename: string; contentType: string; data: Buffer; } export function buildMultipart(files: Record): { payload: Buffer; headers: Record } { const boundary = '----TestBoundary' + Math.random().toString(36).slice(2); const parts: Buffer[] = []; for (const [fieldname, file] of Object.entries(files)) { parts.push(Buffer.from( `--${boundary}\r\n` + `Content-Disposition: form-data; name="${fieldname}"; filename="${file.filename}"\r\n` + `Content-Type: ${file.contentType}\r\n\r\n`, )); parts.push(file.data); parts.push(Buffer.from('\r\n')); } parts.push(Buffer.from(`--${boundary}--\r\n`)); return { payload: Buffer.concat(parts), headers: { 'content-type': `multipart/form-data; boundary=${boundary}` }, }; } export interface TestContext { app: FastifyInstance; db: Database.Database; uploadDir: string; logFile: string; cleanup: () => void; } export function createTestApp(): TestContext { const tmpDir = mkdtempSync(join(tmpdir(), 'nanodrop-int-')); const uploadDir = join(tmpDir, 'uploads'); const logFile = join(tmpDir, 'test.log'); mkdirSync(uploadDir, { recursive: true }); const db = initDb(':memory:'); const config: Config = { port: 0, host: '127.0.0.1', jwtSecret: 'test-secret-key', jwtExpiry: '1h', dbPath: ':memory:', uploadDir, logFile, maxFileSize: 10 * 1024 * 1024, baseUrl: 'http://localhost:3000', cookieSecure: false, trustProxy: false, }; const app = createServer({ config, db }); return { app, db, uploadDir, logFile, cleanup: () => rmSync(tmpDir, { recursive: true, force: true }), }; }