import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { Hono } from 'hono' describe('global error handler', () => { it('returns 500 with sanitized error in production mode', async () => { const originalEnv = process.env.NODE_ENV process.env.NODE_ENV = 'production' const app = new Hono() app.onError((_err, c) => { const msg = process.env.NODE_ENV === 'production' ? 'Internal server error' : _err.message return c.json({ error: msg }, 500) }) app.get('/test', () => { throw new Error('DB connection failed at /path/to/file.ts:42') }) const res = await app.request('/test') expect(res.status).toBe(500) const body = await res.json() as { error: string } expect(body.error).toBe('Internal server error') // Must NOT contain stack trace or file paths expect(body.error).not.toContain('.ts') expect(body.error).not.toContain('Error') expect(body.error).not.toContain('DB connection') process.env.NODE_ENV = originalEnv }) it('returns error message in development mode', async () => { const app = new Hono() app.onError((_err, c) => { const msg = process.env.NODE_ENV === 'production' ? 'Internal server error' : _err.message return c.json({ error: msg }, 500) }) app.get('/test', () => { throw new Error('Something broke') }) const res = await app.request('/test') expect(res.status).toBe(500) const body = await res.json() as { error: string } expect(body.error).toBe('Something broke') }) it('async route handler errors are caught', async () => { const app = new Hono() app.onError((_err, c) => c.json({ error: 'Internal server error' }, 500)) app.get('/test', async () => { throw new Error('async failure') }) const res = await app.request('/test') expect(res.status).toBe(500) }) })