/** * Tests for miscellaneous tools * * Tools tested: * - get_project_url * - verify_jwt_secret * - generate_typescript_types * - list_realtime_publications * - list_cron_jobs * - list_vector_indexes */ import { describe, test, expect, mock } from 'bun:test'; import { getProjectUrlTool } from '../../tools/get_project_url.js'; import { verifyJwtSecretTool } from '../../tools/verify_jwt_secret.js'; import { generateTypesTool } from '../../tools/generate_typescript_types.js'; import { createMockClient, createMockContext, } from '../helpers/mocks.js'; describe('getProjectUrlTool', () => { describe('metadata', () => { test('has correct name', () => { expect(getProjectUrlTool.name).toBe('get_project_url'); }); test('has description', () => { expect(getProjectUrlTool.description).toContain('URL'); }); }); describe('input validation', () => { test('accepts empty input', () => { const result = getProjectUrlTool.inputSchema.safeParse({}); expect(result.success).toBe(true); }); }); describe('execute', () => { test('returns project URL', async () => { const mockClient = createMockClient({ supabaseUrl: 'https://my-project.supabase.co', }); const context = createMockContext(mockClient); const result = await getProjectUrlTool.execute({}, context); expect(result.project_url).toBe('https://my-project.supabase.co'); }); test('returns configured URL from client', async () => { const customUrl = 'https://custom.supabase.example.com'; const mockClient = createMockClient({ supabaseUrl: customUrl }); const context = createMockContext(mockClient); const result = await getProjectUrlTool.execute({}, context); expect(result.project_url).toBe(customUrl); }); }); describe('output validation', () => { test('validates URL format', () => { const result = getProjectUrlTool.outputSchema.safeParse({ project_url: 'https://example.com', }); expect(result.success).toBe(true); }); test('rejects invalid URL', () => { const result = getProjectUrlTool.outputSchema.safeParse({ project_url: 'not-a-url', }); expect(result.success).toBe(false); }); }); }); describe('verifyJwtSecretTool', () => { describe('metadata', () => { test('has correct name', () => { expect(verifyJwtSecretTool.name).toBe('verify_jwt_secret'); }); test('has description about JWT', () => { expect(verifyJwtSecretTool.description).toContain('JWT'); }); }); describe('execute', () => { test('returns found status when JWT secret is configured (no preview for security)', async () => { const mockClient = createMockClient({ jwtSecret: 'my-secret-jwt-key-12345' }); const context = createMockContext(mockClient); const result = await verifyJwtSecretTool.execute({}, context); expect(result.jwt_secret_status).toBe('found'); // SECURITY: jwt_secret_preview was removed to avoid leaking secret info expect('jwt_secret_preview' in result).toBe(false); }); test('returns not_configured status when JWT secret is missing', async () => { const mockClient = createMockClient({ jwtSecret: undefined }); mockClient.getJwtSecret = () => undefined; const context = createMockContext(mockClient); const result = await verifyJwtSecretTool.execute({}, context); expect(result.jwt_secret_status).toBe('not_configured'); }); }); describe('output validation', () => { test('validates found status', () => { const result = verifyJwtSecretTool.outputSchema.safeParse({ jwt_secret_status: 'found', }); expect(result.success).toBe(true); }); test('validates not_configured status', () => { const result = verifyJwtSecretTool.outputSchema.safeParse({ jwt_secret_status: 'not_configured', }); expect(result.success).toBe(true); }); test('rejects invalid status', () => { const result = verifyJwtSecretTool.outputSchema.safeParse({ jwt_secret_status: 'invalid', }); expect(result.success).toBe(false); }); }); }); describe('generateTypesTool', () => { describe('metadata', () => { test('has correct name', () => { expect(generateTypesTool.name).toBe('generate_typescript_types'); }); test('has description about TypeScript types', () => { expect(generateTypesTool.description).toContain('TypeScript'); }); }); describe('input validation', () => { test('requires output_path', () => { const result = generateTypesTool.inputSchema.safeParse({}); expect(result.success).toBe(false); }); test('accepts valid input', () => { const result = generateTypesTool.inputSchema.safeParse({ output_path: '/path/to/types.ts', }); expect(result.success).toBe(true); }); test('defaults included_schemas to public', () => { const result = generateTypesTool.inputSchema.safeParse({ output_path: '/path/to/types.ts', }); expect(result.success).toBe(true); if (result.success) { expect(result.data.included_schemas).toEqual(['public']); } }); test('accepts custom schemas', () => { const result = generateTypesTool.inputSchema.safeParse({ output_path: '/path/to/types.ts', included_schemas: ['public', 'auth', 'storage'], }); expect(result.success).toBe(true); if (result.success) { expect(result.data.included_schemas).toEqual(['public', 'auth', 'storage']); } }); test('defaults output_filename', () => { const result = generateTypesTool.inputSchema.safeParse({ output_path: '/path/to/types.ts', }); expect(result.success).toBe(true); if (result.success) { expect(result.data.output_filename).toBe('database.types.ts'); } }); }); describe('execute', () => { test('returns error when DATABASE_URL is not configured', async () => { const mockClient = createMockClient({ dbUrl: undefined }); mockClient.getDbUrl = () => undefined; const context = createMockContext(mockClient); const result = await generateTypesTool.execute( { output_path: '/tmp/types.ts' }, context ); expect(result.success).toBe(false); expect(result.message).toContain('DATABASE_URL'); }); test('includes platform in response', async () => { const mockClient = createMockClient({ dbUrl: undefined }); mockClient.getDbUrl = () => undefined; const context = createMockContext(mockClient); const result = await generateTypesTool.execute( { output_path: '/tmp/types.ts' }, context ); expect(result.platform).toBeDefined(); expect(['win32', 'darwin', 'linux', 'freebsd', 'openbsd']).toContain(result.platform); }); }); describe('output validation', () => { test('validates success response', () => { const result = generateTypesTool.outputSchema.safeParse({ success: true, message: 'Types generated', types: 'export type User = {...}', file_path: '/path/to/types.ts', platform: 'linux', }); expect(result.success).toBe(true); }); test('validates failure response', () => { const result = generateTypesTool.outputSchema.safeParse({ success: false, message: 'Failed to generate types', platform: 'darwin', }); expect(result.success).toBe(true); }); test('requires platform field', () => { const result = generateTypesTool.outputSchema.safeParse({ success: false, message: 'Error', }); expect(result.success).toBe(false); }); }); });