test-refactor.jsโข5.99 kB
#!/usr/bin/env node
/**
 * Quick test to verify the refactored code works correctly
 */
import { MetabaseMCPServer } from './src/server/MetabaseMCPServer.js';
import { MetabaseClient } from './src/client/MetabaseClient.js';
import { logger } from './src/shared/utils/logger.js';
import { Validators } from './src/shared/utils/validators.js';
import { DashboardUrlDecoder } from './src/shared/utils/urlDecoder.js';
import {
  MetabaseError,
  ApiError,
  ValidationError,
  ConfigurationError,
} from './src/shared/errors/MetabaseError.js';
async function main() {
  console.log('๐งช Testing Refactored Code Structure\n');
  console.log('='.repeat(60));
  let passedTests = 0;
  let failedTests = 0;
  async function runTest(name, testFn) {
    try {
      await testFn();
      console.log(`โ
 PASSED: ${name}`);
      passedTests++;
    } catch (error) {
      console.log(`โ FAILED: ${name}`);
      console.error(`   Error: ${error.message}`);
      failedTests++;
    }
  }
  // Test 1: Error classes
  await runTest('Error classes are properly exported', () => {
  const error = new ValidationError('Test error', 'testField', 'testValue');
  if (error.name !== 'ValidationError') throw new Error('ValidationError not properly initialized');
  if (error.field !== 'testField') throw new Error('ValidationError field not set');
});
  // Test 2: Validators
  await runTest('Validators work correctly', () => {
  try {
    Validators.validateCardId(-1);
    throw new Error('Should have thrown ValidationError');
  } catch (error) {
    if (!(error instanceof ValidationError)) throw new Error('Did not throw ValidationError');
  }
});
  await runTest('Validators accept valid input', () => {
  Validators.validateCardId(123); // Should not throw
});
  // Test 3: Logger
  await runTest('Logger is properly initialized', () => {
  const testLogger = logger.child('Test');
  if (!testLogger.context.includes('Test')) throw new Error('Child logger not created correctly');
});
  // Test 4: DashboardUrlDecoder (error case only, as we need a real URL for success case)
  await runTest('DashboardUrlDecoder throws on invalid URL', () => {
  try {
    DashboardUrlDecoder.decode('invalid-url-without-fragment');
    throw new Error('Should have thrown ValidationError');
  } catch (error) {
    if (!(error instanceof ValidationError)) throw new Error('Did not throw ValidationError');
  }
});
  // Test 5: MetabaseClient can be instantiated
  await runTest('MetabaseClient can be instantiated', () => {
  const client = new MetabaseClient('https://test.com', 'test-key');
  if (!client.metabaseUrl) throw new Error('Client not properly initialized');
  if (client.metabaseUrl !== 'https://test.com') throw new Error('URL not set correctly');
});
  // Test 6: MetabaseMCPServer can be instantiated
  await runTest('MetabaseMCPServer can be instantiated', () => {
  const config = {
    metabaseUrl: 'https://test.com',
    apiKey: 'test-key',
    requestTimeout: 30000,
  };
  const server = new MetabaseMCPServer(config);
  if (!server.apiClient) throw new Error('Server not properly initialized');
});
  // Test 7: Tool definitions are properly exported
  await runTest('Tool definitions are available', async () => {
  const { TOOL_DEFINITIONS } = await import('./src/server/config/toolDefinitions.js');
  if (!Array.isArray(TOOL_DEFINITIONS)) throw new Error('TOOL_DEFINITIONS is not an array');
  if (TOOL_DEFINITIONS.length === 0) throw new Error('TOOL_DEFINITIONS is empty');
  
  // Check that all tools have required properties
  TOOL_DEFINITIONS.forEach(tool => {
    if (!tool.name) throw new Error(`Tool missing name: ${JSON.stringify(tool)}`);
    if (!tool.description) throw new Error(`Tool ${tool.name} missing description`);
    if (!tool.inputSchema) throw new Error(`Tool ${tool.name} missing inputSchema`);
  });
  
  console.log(`   Found ${TOOL_DEFINITIONS.length} tool definitions`);
});
  // Test 8: All handlers are properly exported
  await runTest('All handler classes are available', async () => {
  const { CardHandlers } = await import('./src/server/handlers/cardHandlers.js');
  const { DashboardHandlers } = await import('./src/server/handlers/dashboardHandlers.js');
  const { DatabaseHandlers } = await import('./src/server/handlers/databaseHandlers.js');
  const { CollectionHandlers } = await import('./src/server/handlers/collectionHandlers.js');
  const { QueryHandlers } = await import('./src/server/handlers/queryHandlers.js');
  const { FieldHandlers } = await import('./src/server/handlers/fieldHandlers.js');
  const { SegmentMetricHandlers } = await import('./src/server/handlers/segmentMetricHandlers.js');
  const { UserHandlers } = await import('./src/server/handlers/userHandlers.js');
  
  const handlers = [
    CardHandlers,
    DashboardHandlers,
    DatabaseHandlers,
    CollectionHandlers,
    QueryHandlers,
    FieldHandlers,
    SegmentMetricHandlers,
    UserHandlers,
  ];
  
  handlers.forEach(Handler => {
    if (typeof Handler !== 'function') throw new Error(`Handler is not a class: ${Handler}`);
  });
  
  console.log(`   Found ${handlers.length} handler classes`);
});
  // Summary
  console.log('\n' + '='.repeat(60));
  console.log('\n๐ Test Summary:');
  console.log(`   โ
 Passed: ${passedTests}`);
  console.log(`   โ Failed: ${failedTests}`);
  console.log(`   ๐ Success Rate: ${((passedTests / (passedTests + failedTests)) * 100).toFixed(1)}%`);
  if (failedTests === 0) {
    console.log('\n๐ All refactoring tests passed! The code structure is working correctly.');
    console.log('\n๐ Next steps:');
    console.log('   1. Test with actual Metabase instance');
    console.log('   2. Run the existing test suite: node testing/test-new-tools.js');
    process.exit(0);
  } else {
    console.log('\nโ ๏ธ  Some tests failed. Review the errors above.');
    process.exit(1);
  }
}
// Run main
main().catch(error => {
  console.error('Fatal error:', error);
  process.exit(1);
});