238 lines
6.4 KiB
TypeScript
238 lines
6.4 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
import { POST } from '@/app/api/chat/route'
|
|
import { NextRequest } from 'next/server'
|
|
import { resetFlagsCache } from '@/lib/flags'
|
|
|
|
// Mock fetch globally
|
|
global.fetch = vi.fn()
|
|
|
|
describe('/api/chat', () => {
|
|
const originalEnv = { ...process.env }
|
|
|
|
beforeEach(() => {
|
|
resetFlagsCache()
|
|
vi.clearAllMocks()
|
|
|
|
// Set up default agent
|
|
process.env.AGENT_1_URL = 'https://example.com/webhook/test'
|
|
process.env.IMAGE_UPLOADS_ENABLED = 'true'
|
|
process.env.DIFF_TOOL_ENABLED = 'true'
|
|
})
|
|
|
|
afterEach(() => {
|
|
process.env = { ...originalEnv }
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('requires message field', async () => {
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(400)
|
|
expect(data.error).toBe('Message is required')
|
|
})
|
|
|
|
it('requires agentId field', async () => {
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Hello',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(400)
|
|
expect(data.error).toBe('Agent ID is required')
|
|
})
|
|
|
|
it('rejects images when IMAGE_UPLOADS_ENABLED is false', async () => {
|
|
process.env.IMAGE_UPLOADS_ENABLED = 'false'
|
|
resetFlagsCache()
|
|
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Hello',
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
images: ['data:image/png;base64,abc123'],
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(403)
|
|
expect(data.error).toBe('Image uploads are currently disabled')
|
|
})
|
|
|
|
it('forwards message to webhook successfully', async () => {
|
|
const mockResponse = JSON.stringify({ response: 'Hello back!' })
|
|
|
|
;(global.fetch as any).mockResolvedValueOnce({
|
|
ok: true,
|
|
status: 200,
|
|
text: async () => mockResponse,
|
|
})
|
|
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Hello',
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(data.response).toBe('Hello back!')
|
|
expect(global.fetch).toHaveBeenCalledWith(
|
|
'https://example.com/webhook/test',
|
|
expect.objectContaining({
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
)
|
|
})
|
|
|
|
it('handles streaming response with chunks', async () => {
|
|
const mockResponse = `{"type":"item","content":"Hello "}
|
|
{"type":"item","content":"World!"}`
|
|
|
|
;(global.fetch as any).mockResolvedValueOnce({
|
|
ok: true,
|
|
status: 200,
|
|
text: async () => mockResponse,
|
|
})
|
|
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Hi',
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(data.response).toBe('Hello World!')
|
|
})
|
|
|
|
it('converts diff tool calls to markdown when enabled', async () => {
|
|
const mockResponse = JSON.stringify({
|
|
type: 'tool_call',
|
|
name: 'show_diff',
|
|
args: {
|
|
oldCode: 'const x = 1',
|
|
newCode: 'const x = 2',
|
|
title: 'Update value',
|
|
language: 'javascript',
|
|
},
|
|
})
|
|
|
|
;(global.fetch as any).mockResolvedValueOnce({
|
|
ok: true,
|
|
status: 200,
|
|
text: async () => mockResponse,
|
|
})
|
|
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Show me diff',
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(data.response).toContain('```diff-tool')
|
|
expect(data.response).toContain('oldCode')
|
|
expect(data.response).toContain('newCode')
|
|
})
|
|
|
|
it('converts diff tool calls to plain markdown when disabled', async () => {
|
|
process.env.DIFF_TOOL_ENABLED = 'false'
|
|
resetFlagsCache()
|
|
|
|
const mockResponse = JSON.stringify({
|
|
type: 'tool_call',
|
|
name: 'show_diff',
|
|
args: {
|
|
oldCode: 'const x = 1',
|
|
newCode: 'const x = 2',
|
|
title: 'Update value',
|
|
language: 'javascript',
|
|
},
|
|
})
|
|
|
|
;(global.fetch as any).mockResolvedValueOnce({
|
|
ok: true,
|
|
status: 200,
|
|
text: async () => mockResponse,
|
|
})
|
|
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Show me diff',
|
|
agentId: 'agent-1',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(data.response).not.toContain('```diff-tool')
|
|
expect(data.response).toContain('**Before:**')
|
|
expect(data.response).toContain('**After:**')
|
|
})
|
|
|
|
it('returns error for unconfigured agent', async () => {
|
|
const request = new NextRequest('http://localhost:3000/api/chat', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
message: 'Hello',
|
|
agentId: 'agent-99',
|
|
sessionId: 'test-session',
|
|
timestamp: new Date().toISOString(),
|
|
}),
|
|
})
|
|
|
|
const response = await POST(request)
|
|
const data = await response.json()
|
|
|
|
expect(response.status).toBe(400)
|
|
expect(data.error).toContain('not properly configured')
|
|
})
|
|
})
|