test_connection.test.ts•6.45 kB
import { TestConnectionTool } from '../../tools/test_connection';
import { QuickbaseClient } from '../../client/quickbase';
import { QuickbaseConfig } from '../../types/config';
import { ApiResponse } from '../../types/api';
// Mock the QuickbaseClient
jest.mock('../../client/quickbase');
jest.mock('../../utils/logger', () => ({
createLogger: jest.fn().mockReturnValue({
error: jest.fn(),
warn: jest.fn(),
info: jest.fn(),
debug: jest.fn()
})
}));
describe('TestConnectionTool', () => {
let tool: TestConnectionTool;
let mockClient: jest.Mocked<QuickbaseClient>;
beforeEach(() => {
const config: QuickbaseConfig = {
realmHost: 'test.quickbase.com',
userToken: 'test-token',
appId: 'test-app-id'
};
mockClient = new QuickbaseClient(config) as jest.Mocked<QuickbaseClient>;
mockClient.getConfig = jest.fn().mockReturnValue(config);
tool = new TestConnectionTool(mockClient);
});
describe('tool properties', () => {
it('should have correct name', () => {
expect(tool.name).toBe('test_connection');
});
it('should have description', () => {
expect(tool.description).toBeTruthy();
expect(typeof tool.description).toBe('string');
});
it('should have parameter schema', () => {
expect(tool.paramSchema).toBeDefined();
expect(typeof tool.paramSchema).toBe('object');
});
});
describe('execute', () => {
it('should execute successfully with valid connection and app ID', async () => {
const mockResponse: ApiResponse<any> = {
success: true,
data: {
id: 'test-app-id',
name: 'Test App',
created: '2024-01-01T00:00:00Z'
}
};
mockClient.request = jest.fn().mockResolvedValue(mockResponse);
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(true);
expect(result.data?.realmInfo?.hostname).toBe('test.quickbase.com');
expect(result.data?.realmInfo?.appName).toBe('Test App');
});
it('should execute successfully without app ID', async () => {
const config: QuickbaseConfig = {
realmHost: 'test.quickbase.com',
userToken: 'test-token'
// No appId
};
mockClient.getConfig = jest.fn().mockReturnValue(config);
const mockResponse: ApiResponse<any> = {
success: true,
data: [
{ id: 'app1', name: 'App 1' },
{ id: 'app2', name: 'App 2' }
]
};
mockClient.request = jest.fn().mockResolvedValue(mockResponse);
const result = await tool.execute({});
expect(mockClient.request).toHaveBeenCalledWith({
method: 'GET',
path: '/apps'
});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(true);
expect(result.data?.realmInfo?.id).toBe('no-app-specified');
});
it('should handle connection errors gracefully', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('Unauthorized'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('Unauthorized');
});
it('should handle network errors', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('Failed to connect to Quickbase'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('Failed to connect to Quickbase');
});
it('should provide specific error for 401', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('401 Unauthorized'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('Authentication failed');
});
it('should provide specific error for 404', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('404 Not Found'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('App not found');
});
it('should provide specific error for 403', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('403 Forbidden'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('Access denied');
});
it('should provide specific error for network issues', async () => {
mockClient.request = jest.fn().mockRejectedValue(new Error('ENOTFOUND'));
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('ENOTFOUND');
});
it('should handle missing error response', async () => {
const mockError: ApiResponse<any> = {
success: false,
error: undefined
};
mockClient.request = jest.fn().mockResolvedValue(mockError);
const result = await tool.execute({});
expect(result.success).toBe(true);
expect(result.data?.connected).toBe(false);
expect(result.data?.errorMessage).toContain('Failed to connect to Quickbase');
});
it('should validate parameters', async () => {
// Test with invalid parameters (if any required)
const result = await tool.execute({});
// Since test_connection has no required parameters, this should not fail validation
expect(result).toBeDefined();
});
});
describe('integration', () => {
it('should call client with correct parameters for app-specific test', async () => {
const mockResponse: ApiResponse<any> = {
success: true,
data: {
id: 'test-app-id',
name: 'Test App'
}
};
mockClient.request = jest.fn().mockResolvedValue(mockResponse);
await tool.execute({});
expect(mockClient.request).toHaveBeenCalledWith({
method: 'GET',
path: '/apps/test-app-id'
});
});
});
});