/** * Tests for MCP SSE events endpoint * * @vitest-environment node */ import { authMockFns, permissionsMock, permissionsMockFns } from '@sim/testing' import { NextRequest } from 'next/server' import { beforeEach, describe, expect, it, vi } from 'vitest' function createNextRequest(url: string): NextRequest { return new NextRequest(new URL(url)) } const mockGetUserEntityPermissions = permissionsMockFns.mockGetUserEntityPermissions vi.mock('@/lib/workspaces/permissions/utils', () => permissionsMock) vi.mock('@/lib/events/sse-endpoint', () => ({ createWorkspaceSSE: (_config: any) => { return async (request: any) => { const session = await authMockFns.mockGetSession() if (!session?.user?.id) { return new Response('Unauthorized', { status: 401 }) } const url = new URL(request.url) const workspaceId = url.searchParams.get('workspaceId') if (!workspaceId) { return new Response('Missing workspaceId query parameter', { status: 400 }) } const permissions = await mockGetUserEntityPermissions( session.user.id, 'workspace', workspaceId ) if (!permissions) { return new Response('Access denied to workspace', { status: 403 }) } return new Response(new ReadableStream({ start() {} }), { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', }, }) } }, })) vi.mock('@/lib/mcp/connection-manager', () => ({ mcpConnectionManager: null, })) vi.mock('@/lib/mcp/pubsub', () => ({ mcpPubSub: null, })) import { GET } from './route' const defaultMockUser = { id: 'user-123', email: 'test@example.com', name: 'Test User', } describe('MCP Events SSE Endpoint', () => { beforeEach(() => { vi.clearAllMocks() }) it('returns 401 when session is missing', async () => { authMockFns.mockGetSession.mockResolvedValue(null) const request = createNextRequest('http://localhost:3000/api/mcp/events?workspaceId=ws-123') const response = await GET(request) expect(response.status).toBe(401) const text = await response.text() expect(text).toBe('Unauthorized') }) it('returns 400 when workspaceId is missing', async () => { authMockFns.mockGetSession.mockResolvedValue({ user: defaultMockUser }) const request = createNextRequest('http://localhost:3000/api/mcp/events') const response = await GET(request) expect(response.status).toBe(400) const text = await response.text() expect(text).toBe('Missing workspaceId query parameter') }) it('returns 403 when user lacks workspace access', async () => { authMockFns.mockGetSession.mockResolvedValue({ user: defaultMockUser }) mockGetUserEntityPermissions.mockResolvedValue(null) const request = createNextRequest('http://localhost:3000/api/mcp/events?workspaceId=ws-123') const response = await GET(request) expect(response.status).toBe(403) const text = await response.text() expect(text).toBe('Access denied to workspace') expect(mockGetUserEntityPermissions).toHaveBeenCalledWith('user-123', 'workspace', 'ws-123') }) it('returns SSE stream when authorized', async () => { authMockFns.mockGetSession.mockResolvedValue({ user: defaultMockUser }) mockGetUserEntityPermissions.mockResolvedValue({ read: true }) const request = createNextRequest('http://localhost:3000/api/mcp/events?workspaceId=ws-123') const response = await GET(request) expect(response.status).toBe(200) expect(response.headers.get('Content-Type')).toBe('text/event-stream') expect(response.headers.get('Cache-Control')).toBe('no-cache') expect(response.headers.get('Connection')).toBe('keep-alive') }) })