Files
dbmole-mcp/test/unit/tools/schema.test.ts
T
2026-06-12 00:10:55 +05:00

91 lines
3.6 KiB
TypeScript

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { registerSchemaTools } from '../../../src/tools/schema.js'
import { callTool, connectClient, type FakeManager, fakeManager } from '../helpers.js'
describe('schema tools', () => {
let driver: {
listDatabases: ReturnType<typeof vi.fn>
listTables: ReturnType<typeof vi.fn>
describeTable: ReturnType<typeof vi.fn>
}
let manager: FakeManager
let client: Awaited<ReturnType<typeof connectClient>>
beforeEach(async () => {
driver = {
listDatabases: vi.fn(async () => [{ name: 'app', sizeBytes: 1024 }]),
listTables: vi.fn(async () => [{ schema: 'public', name: 'users', rowEstimate: 5 }]),
describeTable: vi.fn(async () => ({
columns: [{ name: 'id', type: 'integer', nullable: false, default: null }],
primaryKey: ['id'],
indexes: [],
foreignKeys: []
}))
}
manager = fakeManager()
manager.get.mockImplementation(async () => ({
driver,
config: { name: 'c', type: 'postgres', host: 'h', user: 'u', readonly: false },
source: 'store'
}))
const server = new McpServer({ name: 'test', version: '0.0.0' })
registerSchemaTools(server, manager)
client = await connectClient(server)
})
it('list_databases returns database info', async () => {
const response = await callTool(client, 'list_databases', { connection: 'c' })
expect(response.isError).toBe(false)
expect(response.json()).toEqual([{ name: 'app', sizeBytes: 1024 }])
})
it('list_tables forwards database and schema filters', async () => {
const response = await callTool(client, 'list_tables', {
connection: 'c',
database: 'db',
schema: 'public'
})
expect(response.isError).toBe(false)
expect(driver.listTables).toHaveBeenCalledWith({ database: 'db', schema: 'public' })
expect(response.json()).toEqual([{ schema: 'public', name: 'users', rowEstimate: 5 }])
})
it('describe_table forwards args and returns the description', async () => {
const response = await callTool(client, 'describe_table', {
connection: 'c',
table: 'users'
})
expect(response.isError).toBe(false)
expect(driver.describeTable).toHaveBeenCalledWith({
table: 'users',
database: undefined,
schema: undefined
})
expect((response.json() as { primaryKey: string[] }).primaryKey).toEqual(['id'])
})
it('formats driver errors', async () => {
driver.describeTable.mockRejectedValue(new Error("table 'public.ghost' not found"))
const response = await callTool(client, 'describe_table', {
connection: 'c',
table: 'ghost'
})
expect(response.isError).toBe(true)
expect(response.text).toContain('not found')
})
it('reports manager errors per tool', async () => {
manager.get.mockRejectedValue(new Error('no such connection'))
for (const [tool, args] of [
['list_databases', { connection: 'x' }],
['list_tables', { connection: 'x' }],
['describe_table', { connection: 'x', table: 't' }]
] as const) {
const response = await callTool(client, tool, args as Record<string, unknown>)
expect(response.isError).toBe(true)
expect(response.text).toContain('no such connection')
}
})
})