mcp-advisors.test.ts102 lines · main
1import { beforeEach, describe, expect, it, vi } from 'vitest'
2
3import { DEFAULT_EXPOSED_SCHEMAS } from '@/lib/api/self-hosted/constants'
4import { getDebuggingOperations } from '@/lib/api/self-hosted/mcp'
5
6const mockGetLints = vi.fn()
7
8// Mock getLints to capture what arguments the MCP operations pass
9vi.mock('@/lib/api/self-hosted/lints', () => ({
10 getLints: (...args: unknown[]) => mockGetLints(...args),
11}))
12
13// Mock getProjectSettings to avoid assertSelfHosted() check
14vi.mock('@/lib/api/self-hosted/settings', () => ({
15 getProjectSettings: () => ({
16 app_config: {
17 db_schema: 'public',
18 endpoint: 'localhost',
19 protocol: 'http',
20 },
21 service_api_keys: [{ api_key: 'test', name: 'anon key', tags: 'anon' }],
22 }),
23}))
24
25describe('MCP advisor operations pass exposedSchemas to getLints', () => {
26 const headers = { Authorization: 'Bearer test' }
27
28 beforeEach(() => {
29 vi.clearAllMocks()
30 mockGetLints.mockResolvedValue({
31 data: [
32 {
33 name: 'rls_disabled_in_public',
34 title: 'RLS Disabled in Public',
35 level: 'ERROR',
36 categories: ['SECURITY'],
37 description: 'test',
38 detail: 'test',
39 remediation: 'test',
40 metadata: {},
41 cache_key: 'test',
42 },
43 {
44 name: 'unindexed_foreign_keys',
45 title: 'Unindexed foreign keys',
46 level: 'INFO',
47 categories: ['PERFORMANCE'],
48 description: 'test',
49 detail: 'test',
50 remediation: 'test',
51 metadata: {},
52 cache_key: 'test',
53 },
54 ],
55 error: undefined,
56 })
57 })
58
59 it('getSecurityAdvisors should pass exposedSchemas to getLints', async () => {
60 const ops = getDebuggingOperations({ headers })
61 await ops.getSecurityAdvisors('test-project')
62
63 expect(mockGetLints).toHaveBeenCalledOnce()
64 const callArgs = mockGetLints.mock.calls[0][0]
65 expect(callArgs).toHaveProperty('exposedSchemas')
66 expect(callArgs.exposedSchemas).toBeTruthy()
67 })
68
69 it('getPerformanceAdvisors should pass exposedSchemas to getLints', async () => {
70 const ops = getDebuggingOperations({ headers })
71 await ops.getPerformanceAdvisors('test-project')
72
73 expect(mockGetLints).toHaveBeenCalledOnce()
74 const callArgs = mockGetLints.mock.calls[0][0]
75 expect(callArgs).toHaveProperty('exposedSchemas')
76 expect(callArgs.exposedSchemas).toBeTruthy()
77 })
78
79 it('should use DEFAULT_EXPOSED_SCHEMAS constant', async () => {
80 const ops = getDebuggingOperations({ headers })
81 await ops.getSecurityAdvisors('test-project')
82
83 const callArgs = mockGetLints.mock.calls[0][0]
84 expect(callArgs.exposedSchemas).toBe(DEFAULT_EXPOSED_SCHEMAS)
85 })
86
87 it('getSecurityAdvisors should filter to SECURITY category', async () => {
88 const ops = getDebuggingOperations({ headers })
89 const result = await ops.getSecurityAdvisors('test-project')
90
91 expect(result).toHaveLength(1)
92 expect((result as Array<{ name: string }>)[0].name).toBe('rls_disabled_in_public')
93 })
94
95 it('getPerformanceAdvisors should filter to PERFORMANCE category', async () => {
96 const ops = getDebuggingOperations({ headers })
97 const result = await ops.getPerformanceAdvisors('test-project')
98
99 expect(result).toHaveLength(1)
100 expect((result as Array<{ name: string }>)[0].name).toBe('unindexed_foreign_keys')
101 })
102})