Skip to main content
Glama
clean-database-manager.test.ts.legacy8.05 kB
/** * CleanDatabaseManager Tests - Production Infrastructure * Single responsibility: Test database management operations * * Test Coverage Target: 90%+ (Critical database infrastructure) */ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { CleanDatabaseManager } from '../../../src/infrastructure/database/clean-database-manager'; import { Neo4jDriverManager } from '../../../src/infrastructure/database/neo4j-driver'; import { SessionFactory } from '../../../src/infrastructure/database/session-factory'; // Mock dependencies vi.mock('../../../src/infrastructure/database/neo4j-driver'); vi.mock('../../../src/infrastructure/database/session-factory'); describe('CleanDatabaseManager - Database Operations', () => { let databaseManager: CleanDatabaseManager; let mockDriverManager: vi.Mocked<Neo4jDriverManager>; let mockSessionFactory: vi.Mocked<SessionFactory>; let mockSession: any; let mockSystemSession: any; beforeEach(() => { // Create mock sessions mockSession = { run: vi.fn(), close: vi.fn() }; mockSystemSession = { run: vi.fn(), close: vi.fn() }; // Mock SessionFactory mockSessionFactory = { createSession: vi.fn().mockReturnValue(mockSession), createSystemSession: vi.fn().mockReturnValue(mockSystemSession), withSession: vi.fn() } as any; // Mock DriverManager mockDriverManager = { getCurrentDatabase: vi.fn().mockReturnValue({ database: 'test-db' }), switchDatabase: vi.fn(), close: vi.fn() } as any; databaseManager = new CleanDatabaseManager(mockDriverManager, mockSessionFactory); }); describe('switchDatabase', () => { it('should switch to existing database successfully', async () => { // Arrange const databaseName = 'project-database'; // Mock database exists check mockSystemSession.run.mockResolvedValue({ records: [{ get: () => databaseName }] }); // Mock schema check mockSession.run .mockResolvedValueOnce({ records: [{}] }) // hasRequiredSchema - constraints .mockResolvedValueOnce({ records: [{}] }); // hasRequiredSchema - indexes // Act const result = await databaseManager.switchDatabase(databaseName); // Assert expect(mockDriverManager.switchDatabase).toHaveBeenCalledWith(databaseName); expect(result).toEqual({ previousDatabase: 'test-db', currentDatabase: databaseName, created: false }); }); it('should create new database when it does not exist', async () => { // Arrange const databaseName = 'new-project-db'; // Mock database does not exist mockSystemSession.run .mockResolvedValueOnce({ records: [] }) // Database doesn't exist .mockResolvedValueOnce({}); // CREATE DATABASE command // Mock schema initialization mockSession.run.mockResolvedValue({ records: [] }); // Act const result = await databaseManager.switchDatabase(databaseName, true); // Assert expect(mockSystemSession.run).toHaveBeenCalledWith( 'CREATE DATABASE $name IF NOT EXISTS', { name: databaseName } ); expect(result.created).toBe(true); }); it('should stay in same database when switching to current database', async () => { // Arrange const currentDb = 'test-db'; mockDriverManager.getCurrentDatabase.mockReturnValue({ database: currentDb }); // Mock schema exists mockSession.run .mockResolvedValueOnce({ records: [{}] }) // hasRequiredSchema - constraints .mockResolvedValueOnce({ records: [{}] }); // hasRequiredSchema - indexes // Act const result = await databaseManager.switchDatabase(currentDb); // Assert expect(mockDriverManager.switchDatabase).not.toHaveBeenCalled(); expect(result).toEqual({ previousDatabase: currentDb, currentDatabase: currentDb, created: false }); }); it('should validate database name format', async () => { // Arrange const invalidName = 'Invalid-Database-Name-With-CAPS'; // Act & Assert await expect(databaseManager.switchDatabase(invalidName)) .rejects .toThrow(`Invalid database name: ${invalidName}`); }); it('should handle database creation errors gracefully', async () => { // Arrange const databaseName = 'test-creation-error'; // Mock database does not exist mockSystemSession.run .mockResolvedValueOnce({ records: [] }) // Database doesn't exist .mockRejectedValueOnce(new Error('Database creation failed')); // CREATE fails // Act & Assert await expect(databaseManager.switchDatabase(databaseName, false)) .rejects .toThrow(`Database '${databaseName}' does not exist`); }); }); describe('getCurrentDatabase', () => { it('should return current database from driver manager', () => { // Arrange const expectedDb = { database: 'current-test-db' }; mockDriverManager.getCurrentDatabase.mockReturnValue(expectedDb); // Act const result = databaseManager.getCurrentDatabase(); // Assert expect(result).toEqual(expectedDb); expect(mockDriverManager.getCurrentDatabase).toHaveBeenCalled(); }); }); describe('close', () => { it('should close driver manager', async () => { // Act await databaseManager.close(); // Assert expect(mockDriverManager.close).toHaveBeenCalled(); }); }); describe('Database Name Validation', () => { it('should accept valid database names', async () => { // Arrange const validNames = [ 'valid-db-name', 'test_database', 'project123', 'a.b.c' ]; for (const name of validNames) { mockSystemSession.run.mockResolvedValue({ records: [{}] }); mockSession.run.mockResolvedValue({ records: [] }); // Act & Assert - Should not throw await expect(databaseManager.switchDatabase(name)).resolves.toBeDefined(); } }); it('should reject invalid database names', async () => { // Arrange const invalidNames = [ 'Invalid-With-CAPS', '123-starts-with-number', 'too-long-name-' + 'x'.repeat(50), 'has spaces', 'has@special#chars' ]; for (const name of invalidNames) { // Act & Assert await expect(databaseManager.switchDatabase(name)) .rejects .toThrow(`Invalid database name: ${name}`); } }); }); describe('Error Handling', () => { it('should handle network timeouts during database operations', async () => { // Arrange const databaseName = 'timeout-test'; mockSystemSession.run.mockRejectedValue(new Error('Connection timeout')); // Act & Assert await expect(databaseManager.switchDatabase(databaseName)) .rejects .toThrow(`Failed to switch to database '${databaseName}': Error: Connection timeout`); }); it('should handle permission errors', async () => { // Arrange const databaseName = 'permission-test'; mockSystemSession.run.mockRejectedValue(new Error('Access denied')); // Act & Assert await expect(databaseManager.switchDatabase(databaseName)) .rejects .toThrow('Access denied'); }); it('should initialize schema in new database', async () => { // Arrange const databaseName = 'schema-test-db'; // Mock successful database operations mockSystemSession.run.mockResolvedValue({ records: [{ get: () => databaseName }] }); mockSession.run.mockResolvedValue({ records: [] }); // Act await databaseManager.switchDatabase(databaseName); // Assert expect(mockSessionFactory.createSession).toHaveBeenCalled(); // Schema initialization happens through IndexManager }); }); });

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/sylweriusz/mcp-neo4j-memory-server'

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