Testing
Lacis routes are plain async functions — they’re easy to test. The recommended approach is to spin up a real server on a random port with your handlers passed inline, then hit it with supertest.
Install supertest:
npm install -D supertest @types/supertestTest helper
Section titled “Test helper”Create a small helper that wraps createServer with a random port:
// tests/helpers/server.tsimport supertest from 'supertest'import { createServer } from 'lacis'import type { ServerlessRoute, ServerConfig } from 'lacis'import type { Server } from 'http'
export async function createTestApp(options: { routes: ServerlessRoute[] middleware?: ServerConfig['middleware'] hooks?: ServerConfig['hooks']}) { const server = await createServer('', { platform: 'node', port: 0, // random available port cluster: { enabled: false }, routes: options.routes, middleware: options.middleware, hooks: options.hooks, }) as Server
const { port } = server.address() as { port: number }
return { request: supertest.agent(`http://localhost:${port}`), close: () => new Promise<void>((resolve, reject) => server.close(err => err ? reject(err) : resolve()) ), }}Writing tests
Section titled “Writing tests”Import your handlers directly and pass them as routes:
// tests/users.test.tsimport { createTestApp } from './helpers/server'import { GET, POST } from '../routes/users/index'
describe('GET /users', () => { it('returns a list of users', async () => { const { request, close } = await createTestApp({ routes: [{ path: '/users', handlers: { GET, POST } }], })
await request.get('/users') .expect(200) .expect(res => { expect(Array.isArray(res.body.users)).toBe(true) })
await close() })})Testing with params
Section titled “Testing with params”import { GET } from '../routes/users/[id]/index'
it('returns a user by id', async () => { const { request, close } = await createTestApp({ routes: [{ path: '/users/:id', handlers: { GET } }], })
await request.get('/users/123').expect(200).expect({ id: '123' }) await close()})Testing with body
Section titled “Testing with body”import { POST } from '../routes/users/index'
it('creates a user', async () => { const { request, close } = await createTestApp({ routes: [{ path: '/users', handlers: { POST } }], })
await request .post('/users') .expect(201)
await close()})Testing middleware
Section titled “Testing middleware”Pass middleware directly — no file loading needed:
import { createUnauthorizedError } from 'lacis'
it('rejects requests without a token', async () => { const { request, close } = await createTestApp({ routes: [{ path: '/protected', handlers: { GET: async (_req, res) => res.json({ ok: true }) } }], middleware: { beforeRequest: async (req, res) => { if (!req.getHeader('authorization')) { throw createUnauthorizedError() } }, }, })
await request.get('/protected').expect(401) await request.get('/protected').set('Authorization', 'Bearer token').expect(200)
await close()})Testing cookies
Section titled “Testing cookies”it('sets a session cookie on login', async () => { const { request, close } = await createTestApp({ routes: [{ path: '/login', handlers: { POST: async (_req, res) => { res.cookies.set('session', 'abc123', { httpOnly: true }) res.json({ ok: true }) }, }, }], })
const res = await request.post('/login').expect(200) expect(res.headers['set-cookie'][0]).toContain('session=abc123') expect(res.headers['set-cookie'][0]).toContain('HttpOnly')
await close()})