Files
auth-portal/apps/api/test/error-handler.test.ts

78 lines
2.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<ReturnType<typeof buildTestApp>> | 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'), '<html>spa</html>')
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')
}
})
})