import { mkdtempSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import { z } from 'zod' import { buildTestApp } from './helpers.js' let app: Awaited> | undefined afterEach(async () => { await app?.close() app = undefined }) describe('error handler', () => { it('необработанная ошибка → 500 без деталей', async () => { app = await buildTestApp() app.get('/__boom', async () => { throw new Error('secret internals') }) const res = await app.inject({ method: 'GET', url: '/__boom' }) expect(res.statusCode).toBe(500) expect(res.json()).toEqual({ error: { code: 'INTERNAL', message: 'Internal server error' }, }) expect(res.body).not.toContain('secret internals') }) it('ZodError → 400 BAD_REQUEST', async () => { app = await buildTestApp() app.get('/__zod', async () => z.object({ a: z.string() }).parse({})) const res = await app.inject({ method: 'GET', url: '/__zod' }) expect(res.statusCode).toBe(400) expect(res.json().error.code).toBe('BAD_REQUEST') }) it('ошибка с statusCode 4xx сохраняет статус', async () => { app = await buildTestApp() app.get('/__teapot', async () => { throw Object.assign(new Error('nope'), { statusCode: 418 }) }) const res = await app.inject({ method: 'GET', url: '/__teapot' }) expect(res.statusCode).toBe(418) }) }) describe('not found', () => { it.each(['/oauth/nope', '/.well-known/nope', '/api/v1/nope'])( '%s → 404 JSON', async (url) => { app = await buildTestApp() const res = await app.inject({ method: 'GET', url }) expect(res.statusCode).toBe(404) expect(res.json().error.code).toBe('NOT_FOUND') }, ) it('без STATIC_DIR неизвестный путь → 404 JSON', async () => { app = await buildTestApp() const res = await app.inject({ method: 'GET', url: '/some/spa/route' }) expect(res.statusCode).toBe(404) }) it('со STATIC_DIR: SPA-путь → index.html, /oauth и /.well-known → 404', async () => { const dir = mkdtempSync(join(tmpdir(), 'ap-static-')) writeFileSync(join(dir, 'index.html'), 'spa') app = await buildTestApp({ STATIC_DIR: dir }) const spa = await app.inject({ method: 'GET', url: '/some/spa/route' }) expect(spa.statusCode).toBe(200) expect(spa.body).toContain('spa') for (const url of ['/oauth/nope', '/.well-known/nope']) { const res = await app.inject({ method: 'GET', url }) expect(res.statusCode).toBe(404) expect(res.json().error.code).toBe('NOT_FOUND') } }) })