/**
* mysql-mcp - Resources Unit Tests
*
* Tests for resource definitions using centralized mocks.
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getMySQLResources } from '../index.js';
import type { MySQLAdapter } from '../../MySQLAdapter.js';
import { createMockMySQLAdapter, createMockRequestContext, createMockQueryResult } from '../../../../__tests__/mocks/index.js';
describe('getMySQLResources', () => {
let resources: ReturnType<typeof getMySQLResources>;
beforeEach(() => {
vi.clearAllMocks();
resources = getMySQLResources(createMockMySQLAdapter() as unknown as MySQLAdapter);
});
it('should return 18 resources', () => {
expect(resources).toHaveLength(18);
});
it('should have handler functions for all resources', () => {
for (const resource of resources) {
expect(typeof resource.handler).toBe('function');
}
});
it('should have descriptions for all resources', () => {
for (const resource of resources) {
expect(resource.description).toBeDefined();
expect(resource.description.length).toBeGreaterThan(0);
}
});
it('should have unique URIs for all resources', () => {
const uris = resources.map(r => r.uri);
const uniqueUris = new Set(uris);
expect(uniqueUris.size).toBe(uris.length);
});
it('should have URIs starting with mysql://', () => {
for (const resource of resources) {
expect(resource.uri.startsWith('mysql://')).toBe(true);
}
});
});
describe('Resource Handler Smoke Tests', () => {
let mockAdapter: ReturnType<typeof createMockMySQLAdapter>;
let mockContext: ReturnType<typeof createMockRequestContext>;
let resources: ReturnType<typeof getMySQLResources>;
beforeEach(() => {
vi.clearAllMocks();
mockAdapter = createMockMySQLAdapter();
mockContext = createMockRequestContext();
resources = getMySQLResources(mockAdapter as unknown as MySQLAdapter);
});
const findResource = (uri: string) => resources.find(r => r.uri === uri);
it('mysql://tables handler should call listTables', async () => {
const resource = findResource('mysql://tables');
expect(resource).toBeDefined();
const result = await resource!.handler('mysql://tables', mockContext);
expect(mockAdapter.listTables).toHaveBeenCalled();
expect(result).toHaveProperty('tables');
});
it('mysql://schema handler should call getSchema', async () => {
const resource = findResource('mysql://schema');
expect(resource).toBeDefined();
const result = await resource!.handler('mysql://schema', mockContext);
expect(mockAdapter.getSchema).toHaveBeenCalled();
expect(result).toHaveProperty('tables');
});
it('mysql://variables handler should execute query', async () => {
mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([
{ Variable_name: 'version', Value: '8.0.35' }
]));
const resource = findResource('mysql://variables');
expect(resource).toBeDefined();
await resource!.handler('mysql://variables', mockContext);
expect(mockAdapter.executeQuery).toHaveBeenCalledWith(expect.stringContaining('SHOW'));
});
it('mysql://status handler should execute query', async () => {
mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([
{ Variable_name: 'Uptime', Value: '86400' }
]));
const resource = findResource('mysql://status');
expect(resource).toBeDefined();
await resource!.handler('mysql://status', mockContext);
expect(mockAdapter.executeQuery).toHaveBeenCalledWith(expect.stringContaining('SHOW'));
});
it('mysql://processlist handler should execute processlist query', async () => {
mockAdapter.executeQuery.mockResolvedValue(createMockQueryResult([
{ Id: 1, User: 'root', Command: 'Query' }
]));
const resource = findResource('mysql://processlist');
expect(resource).toBeDefined();
await resource!.handler('mysql://processlist', mockContext);
expect(mockAdapter.executeQuery).toHaveBeenCalledWith(expect.stringContaining('PROCESSLIST'));
});
});