Skip to main content
Glama
AnalyzeSchemaUseCase.test.js14.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const AnalyzeSchemaUseCase_1 = require("./AnalyzeSchemaUseCase"); const SchemaAnalyzer_1 = require("../../domain/services/SchemaAnalyzer"); const DatabaseConfig_1 = require("../../infrastructure/config/DatabaseConfig"); const Environment_1 = require("../../domain/value-objects/Environment"); const DatabaseSchema_1 = require("../../domain/entities/DatabaseSchema"); const TableInfo_1 = require("../../domain/entities/TableInfo"); const Column_1 = require("../../domain/entities/Column"); const Index_1 = require("../../domain/entities/Index"); const ForeignKey_1 = require("../../domain/entities/ForeignKey"); (0, vitest_1.describe)('AnalyzeSchemaUseCase', () => { let useCase; let mockRepository; let mockCache; let mockSchemaAnalyzer; let mockDatabaseConfig; (0, vitest_1.beforeEach)(() => { // Mock repository mockRepository = { fetchDatabaseSchema: vitest_1.vi.fn(), fetchTableDetails: vitest_1.vi.fn(), fetchIndexInformation: vitest_1.vi.fn(), executeSQLQuery: vitest_1.vi.fn(), }; // Mock cache mockCache = { get: vitest_1.vi.fn(), set: vitest_1.vi.fn(), delete: vitest_1.vi.fn(), clear: vitest_1.vi.fn(), has: vitest_1.vi.fn(), }; // Mock schema analyzer mockSchemaAnalyzer = new SchemaAnalyzer_1.SchemaAnalyzer(); // Mock database config const databases = new Map(); databases.set(Environment_1.Environment.DEVELOPMENT, { name: 'dev_db', id: 'dev-123' }); databases.set(Environment_1.Environment.STAGING, { name: 'staging_db', id: 'staging-456' }); databases.set(Environment_1.Environment.PRODUCTION, { name: 'prod_db', id: 'prod-789' }); mockDatabaseConfig = new DatabaseConfig_1.DatabaseConfig(databases); useCase = new AnalyzeSchemaUseCase_1.AnalyzeSchemaUseCase(mockRepository, mockSchemaAnalyzer, mockDatabaseConfig, mockCache); vitest_1.vi.clearAllMocks(); }); (0, vitest_1.describe)('constructor', () => { (0, vitest_1.it)('should create use case and freeze instance', () => { (0, vitest_1.expect)(Object.isFrozen(useCase)).toBe(true); }); }); (0, vitest_1.describe)('execute()', () => { (0, vitest_1.it)('should fetch schema and return analysis when cache is empty', async () => { // Mock cache miss mockCache.get.mockResolvedValue(undefined); // Mock schema const columns = [ new Column_1.Column('id', 'INTEGER', false, true, null), new Column_1.Column('name', 'TEXT', false, false, null), ]; const indexes = [new Index_1.Index('idx_name', 'users', ['name'], false, false)]; const foreignKeys = []; const table = new TableInfo_1.TableInfo('users', 'table', columns, indexes, foreignKeys); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); mockRepository.executeSQLQuery.mockResolvedValue({ success: true, results: [{ id: 1, name: 'Alice' }], }); // Execute const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: true, maxSampleRows: 5, }); // Verify repository was called with correct database ID (0, vitest_1.expect)(mockRepository.fetchDatabaseSchema).toHaveBeenCalledWith('dev-123'); // Verify cache was set with 10-minute TTL (0, vitest_1.expect)(mockCache.set).toHaveBeenCalledWith('schema:development', schema, 600); // Verify response structure (0, vitest_1.expect)(result.databaseName).toBe('dev_db'); (0, vitest_1.expect)(result.environment).toBe(Environment_1.Environment.DEVELOPMENT); (0, vitest_1.expect)(result.tableCount).toBe(1); (0, vitest_1.expect)(result.tables).toHaveLength(1); // Verify table analysis const tableAnalysis = result.tables[0]; (0, vitest_1.expect)(tableAnalysis.name).toBe('users'); (0, vitest_1.expect)(tableAnalysis.type).toBe('table'); (0, vitest_1.expect)(tableAnalysis.columnCount).toBe(2); (0, vitest_1.expect)(tableAnalysis.columns).toHaveLength(2); (0, vitest_1.expect)(tableAnalysis.indexes).toHaveLength(1); (0, vitest_1.expect)(tableAnalysis.samples).toEqual([{ id: 1, name: 'Alice' }]); }); (0, vitest_1.it)('should return cached schema when available', async () => { // Mock cached schema const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('products', 'table', columns, [], []); const cachedSchema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockCache.get.mockResolvedValue(cachedSchema); // Execute const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: false, }); // Verify cache was checked (0, vitest_1.expect)(mockCache.get).toHaveBeenCalledWith('schema:development'); // Verify repository was NOT called (0, vitest_1.expect)(mockRepository.fetchDatabaseSchema).not.toHaveBeenCalled(); // Verify cache was NOT set again (0, vitest_1.expect)(mockCache.set).not.toHaveBeenCalled(); // Verify response uses cached data (0, vitest_1.expect)(result.databaseName).toBe('dev_db'); (0, vitest_1.expect)(result.tableCount).toBe(1); }); (0, vitest_1.it)('should handle different environments correctly', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('orders', 'table', columns, [], []); const schema = new DatabaseSchema_1.DatabaseSchema('prod_db', Environment_1.Environment.PRODUCTION, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); // Execute with production environment await useCase.execute({ environment: Environment_1.Environment.PRODUCTION, includeSamples: false, }); // Verify correct database ID used (0, vitest_1.expect)(mockRepository.fetchDatabaseSchema).toHaveBeenCalledWith('prod-789'); // Verify correct cache key (0, vitest_1.expect)(mockCache.set).toHaveBeenCalledWith('schema:production', schema, 600); }); (0, vitest_1.it)('should include samples when includeSamples is true', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('items', 'table', columns, [], []); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); mockRepository.executeSQLQuery.mockResolvedValue({ success: true, results: [{ id: 1 }, { id: 2 }], }); const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: true, maxSampleRows: 2, }); // Verify sample query was executed (0, vitest_1.expect)(mockRepository.executeSQLQuery).toHaveBeenCalledWith('dev-123', 'SELECT * FROM "items" LIMIT 2'); // Verify samples are included (0, vitest_1.expect)(result.tables[0].samples).toEqual([{ id: 1 }, { id: 2 }]); }); (0, vitest_1.it)('should exclude samples when includeSamples is false', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('items', 'table', columns, [], []); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: false, }); // Verify sample query was NOT executed (0, vitest_1.expect)(mockRepository.executeSQLQuery).not.toHaveBeenCalled(); // Verify samples are not included (0, vitest_1.expect)(result.tables[0].samples).toBeUndefined(); }); (0, vitest_1.it)('should use default values for optional parameters', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('items', 'table', columns, [], []); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); mockRepository.executeSQLQuery.mockResolvedValue({ success: true, results: [], }); // Execute with minimal request (no optional params) await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, }); // Verify default includeSamples=true and maxSampleRows=5 (0, vitest_1.expect)(mockRepository.executeSQLQuery).toHaveBeenCalledWith('dev-123', 'SELECT * FROM "items" LIMIT 5'); }); (0, vitest_1.it)('should handle sample fetch errors gracefully', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [new Column_1.Column('id', 'INTEGER', false, true, null)]; const table = new TableInfo_1.TableInfo('items', 'table', columns, [], []); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); mockRepository.executeSQLQuery.mockRejectedValue(new Error('Table not found')); const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: true, }); // Verify sample fetch was attempted (0, vitest_1.expect)(mockRepository.executeSQLQuery).toHaveBeenCalled(); // Verify empty array returned on error (doesn't fail entire analysis) (0, vitest_1.expect)(result.tables[0].samples).toEqual([]); }); (0, vitest_1.it)('should correctly format all table metadata', async () => { mockCache.get.mockResolvedValue(undefined); const columns = [ new Column_1.Column('id', 'INTEGER', true, false, null), new Column_1.Column('name', 'TEXT', false, true, "'unknown'"), ]; const indexes = [ new Index_1.Index('pk_users', 'users', ['id'], true, true), new Index_1.Index('idx_name', 'users', ['name'], false, false), ]; const foreignKeys = [ new ForeignKey_1.ForeignKey('users', 'department_id', 'departments', 'id', 'CASCADE', 'RESTRICT'), ]; const table = new TableInfo_1.TableInfo('users', 'table', columns, indexes, foreignKeys); const schema = new DatabaseSchema_1.DatabaseSchema('dev_db', Environment_1.Environment.DEVELOPMENT, [table], new Date()); mockRepository.fetchDatabaseSchema.mockResolvedValue(schema); const result = await useCase.execute({ environment: Environment_1.Environment.DEVELOPMENT, includeSamples: false, }); const tableAnalysis = result.tables[0]; // Verify columns (0, vitest_1.expect)(tableAnalysis.columns).toHaveLength(2); (0, vitest_1.expect)(tableAnalysis.columns[0]).toEqual({ name: 'id', type: 'INTEGER', nullable: false, isPrimaryKey: true, defaultValue: null, }); (0, vitest_1.expect)(tableAnalysis.columns[1]).toEqual({ name: 'name', type: 'TEXT', nullable: true, isPrimaryKey: false, defaultValue: "'unknown'", }); // Verify indexes (0, vitest_1.expect)(tableAnalysis.indexes).toHaveLength(2); (0, vitest_1.expect)(tableAnalysis.indexes[0]).toEqual({ name: 'pk_users', columns: ['id'], isUnique: true, isPrimaryKey: true, }); // Verify foreign keys (0, vitest_1.expect)(tableAnalysis.foreignKeys).toHaveLength(1); (0, vitest_1.expect)(tableAnalysis.foreignKeys[0]).toEqual({ column: 'department_id', referencedTable: 'departments', referencedColumn: 'id', onDelete: 'CASCADE', onUpdate: 'RESTRICT', }); }); }); }); //# sourceMappingURL=AnalyzeSchemaUseCase.test.js.map

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/semanticintent/semantic-d1-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server