test(core): cover the parseSchema contract

Assert add_connection advertises fullSchema as its inputSchema (never the
refined schema) and applies an optional parseSchema in the handler: a
refinement rejection surfaces as an error and skips registry.add, while a
passing config persists. Locks the wire/parse split at the core level.
This commit is contained in:
admin committed 2026-06-16 23:49:18 +05:00
1 parent 63bb2a5c99
commit 82d2392e31
1 file changed
+34 -2
@@ -98,7 +98,7 @@ describe('registerConnectionTools', () => {
let registry: FakeRegistry let registry: FakeRegistry
let manager: FakeManager let manager: FakeManager
let handlers: Map<string, Handler> let handlers: Map<string, Handler>
let configs: Map<string, { description?: string }> let configs: Map<string, { description?: string; inputSchema?: unknown }>
const invoke = (name: string, args: Record<string, unknown> = {}): Promise<CallToolResult> => { const invoke = (name: string, args: Record<string, unknown> = {}): Promise<CallToolResult> => {
const handler = handlers.get(name) const handler = handlers.get(name)
@@ -113,7 +113,11 @@ describe('registerConnectionTools', () => {
handlers = new Map() handlers = new Map()
configs = new Map() configs = new Map()
vi.spyOn(server, 'registerTool').mockImplementation( vi.spyOn(server, 'registerTool').mockImplementation(
(name: string, config: { description?: string }, handler: unknown) => { (
name: string,
config: { description?: string; inputSchema?: unknown },
handler: unknown
) => {
configs.set(name, config) configs.set(name, config)
handlers.set(name, handler as Handler) handlers.set(name, handler as Handler)
return { return {
@@ -212,6 +216,34 @@ describe('registerConnectionTools', () => {
expect(text(result)).toContain('already exists') expect(text(result)).toContain('already exists')
}) })
it('add_connection advertises fullSchema and applies parseSchema in the handler', async () => {
const parseSchema = schema.superRefine((c, ctx) => {
if (c.host === 'bad') {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'bad host' })
}
})
registry.add.mockImplementation((config: TestConfig) => resolved(config))
register({ parseSchema })
// The advertised wire schema is always fullSchema, never the refined one
// (a ZodEffects has no .shape and would publish an empty inputSchema).
expect(configs.get('add_connection')?.inputSchema).toBe(schema)
const rejected = await invoke('add_connection', { name: 'x', type: 'mysql', host: 'bad' })
expect(rejected.isError).toBe(true)
expect(text(rejected)).toContain('bad host')
expect(registry.add).not.toHaveBeenCalled()
const accepted = await invoke('add_connection', { name: 'y', type: 'mysql', host: 'good' })
expect(accepted.isError).toBeFalsy()
expect(registry.add).toHaveBeenCalledWith({
name: 'y',
type: 'mysql',
host: 'good',
readonly: false
})
})
it('update_connection patches, invalidates the cache and returns the public view', async () => { it('update_connection patches, invalidates the cache and returns the public view', async () => {
registry.update.mockReturnValue( registry.update.mockReturnValue(
resolved({ name: 'c', type: 'postgres', host: 'new', readonly: false }) resolved({ name: 'c', type: 'postgres', host: 'new', readonly: false })