@ufdevsllc/authme2.0
Version:
SDK for license management and remote monitoring with automatic system tracking, license validation, and remote control capabilities
287 lines (228 loc) • 9.93 kB
JavaScript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import DatabaseManager from '../database-manager.js';
// Create a mock connection class
class MockConnection {
constructor() {
this.readyState = 1;
this.eventHandlers = {};
}
once(event, handler) {
this.eventHandlers[event] = handler;
}
on(event, handler) {
this.eventHandlers[event] = handler;
}
collection(name) {
return {
insertOne: vi.fn().mockResolvedValue({ insertedId: 'test-id' })
};
}
close() {
return Promise.resolve();
}
}
// Mock mongoose
vi.mock('mongoose', () => ({
default: {
createConnection: vi.fn()
}
}));
describe('DatabaseManager', () => {
let dbManager;
let mockConnection;
let mongoose;
beforeEach(async () => {
// Import mongoose after mocking
mongoose = (await import('mongoose')).default;
dbManager = new DatabaseManager();
mockConnection = new MockConnection();
vi.clearAllMocks();
});
afterEach(() => {
vi.clearAllMocks();
});
describe('constructor', () => {
it('should initialize with correct default values', () => {
expect(dbManager.monitoringConnection).toBeNull();
expect(dbManager.isConnected).toBe(false);
expect(dbManager.connectionString).toBe('mongodb+srv://incrypto09:VcFzmdvSgSbqHx5m@transcoding.jcngo.mongodb.net/?retryWrites=true&w=majority&appName=transcoding');
expect(dbManager.databaseName).toBe('authme2.0');
expect(dbManager.maxRetries).toBe(5);
expect(dbManager.retryDelay).toBe(1000);
});
});
describe('initMonitoringConnection', () => {
it('should successfully connect to monitoring database', async () => {
mongoose.createConnection.mockReturnValue(mockConnection);
// Simulate successful connection
const connectionPromise = dbManager.initMonitoringConnection();
// Trigger the 'open' event
setTimeout(() => {
if (mockConnection.eventHandlers.open) {
mockConnection.eventHandlers.open();
}
}, 10);
await connectionPromise;
expect(mongoose.createConnection).toHaveBeenCalledWith(
dbManager.connectionString,
expect.objectContaining({
dbName: 'authme2.0',
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
bufferCommands: false,
bufferMaxEntries: 0
})
);
expect(dbManager.isConnected).toBe(true);
expect(dbManager.monitoringConnection).toBe(mockConnection);
});
it('should return early if already connected', async () => {
dbManager.isConnected = true;
dbManager.monitoringConnection = mockConnection;
await dbManager.initMonitoringConnection();
expect(mongoose.createConnection).not.toHaveBeenCalled();
});
it('should handle connection errors and retry', async () => {
const mockError = new Error('Connection failed');
mongoose.createConnection.mockReturnValue(mockConnection);
// Mock the sleep function to make test faster
dbManager.sleep = vi.fn().mockResolvedValue();
let attemptCount = 0;
const connectionPromise = dbManager.initMonitoringConnection();
// Simulate first failure, then success
setTimeout(() => {
attemptCount++;
if (attemptCount === 1) {
if (mockConnection.eventHandlers.error) {
mockConnection.eventHandlers.error(mockError);
}
}
}, 10);
// Simulate success on retry
setTimeout(() => {
if (attemptCount === 1) {
if (mockConnection.eventHandlers.open) {
mockConnection.eventHandlers.open();
}
}
}, 50);
await connectionPromise;
expect(dbManager.isConnected).toBe(true);
expect(dbManager.sleep).toHaveBeenCalled();
});
});
describe('getMonitoringDB', () => {
it('should return monitoring connection when connected', () => {
dbManager.isConnected = true;
dbManager.monitoringConnection = mockConnection;
const result = dbManager.getMonitoringDB();
expect(result).toBe(mockConnection);
});
it('should throw error when not connected', () => {
expect(() => dbManager.getMonitoringDB()).toThrow('Monitoring database not connected');
});
});
describe('saveUserData', () => {
beforeEach(() => {
dbManager.isConnected = true;
dbManager.monitoringConnection = mockConnection;
});
it('should save user data to monitoring database', async () => {
const testData = { userId: 'test-user', action: 'test-action' };
const mockCollection = {
insertOne: vi.fn().mockResolvedValue({ insertedId: 'test-id' })
};
mockConnection.collection = vi.fn().mockReturnValue(mockCollection);
const result = await dbManager.saveUserData('test-collection', testData);
expect(mockConnection.collection).toHaveBeenCalledWith('test-collection');
expect(mockCollection.insertOne).toHaveBeenCalledWith(
expect.objectContaining({
userId: 'test-user',
action: 'test-action',
timestamp: expect.any(Date),
_createdAt: expect.any(Date)
})
);
expect(result).toEqual({ insertedId: 'test-id' });
});
it('should throw error when not connected', async () => {
dbManager.isConnected = false;
await expect(dbManager.saveUserData('test', {})).rejects.toThrow('Monitoring database not connected');
});
it('should handle database errors', async () => {
const mockError = new Error('Database error');
const mockCollection = {
insertOne: vi.fn().mockRejectedValue(mockError)
};
mockConnection.collection = vi.fn().mockReturnValue(mockCollection);
await expect(dbManager.saveUserData('test', {})).rejects.toThrow('Database error');
});
});
describe('isMonitoringConnected', () => {
it('should return true when connected and ready', () => {
dbManager.isConnected = true;
dbManager.monitoringConnection = mockConnection;
mockConnection.readyState = 1;
expect(dbManager.isMonitoringConnected()).toBe(true);
});
it('should return false when not connected', () => {
dbManager.isConnected = false;
expect(dbManager.isMonitoringConnected()).toBe(false);
});
it('should return false when connection not ready', () => {
dbManager.isConnected = true;
dbManager.monitoringConnection = mockConnection;
mockConnection.readyState = 0;
expect(dbManager.isMonitoringConnected()).toBe(false);
});
});
describe('closeConnection', () => {
it('should close monitoring connection', async () => {
dbManager.monitoringConnection = mockConnection;
mockConnection.close = vi.fn().mockResolvedValue();
await dbManager.closeConnection();
expect(mockConnection.close).toHaveBeenCalled();
expect(dbManager.isConnected).toBe(false);
});
it('should handle close errors', async () => {
const mockError = new Error('Close error');
dbManager.monitoringConnection = mockConnection;
mockConnection.close = vi.fn().mockRejectedValue(mockError);
await expect(dbManager.closeConnection()).rejects.toThrow('Close error');
});
it('should do nothing when no connection exists', async () => {
dbManager.monitoringConnection = null;
await expect(dbManager.closeConnection()).resolves.toBeUndefined();
});
});
describe('setupConnectionHandlers', () => {
it('should set up event handlers for connection', () => {
dbManager.monitoringConnection = mockConnection;
mockConnection.on = vi.fn();
dbManager.setupConnectionHandlers();
expect(mockConnection.on).toHaveBeenCalledWith('error', expect.any(Function));
expect(mockConnection.on).toHaveBeenCalledWith('disconnected', expect.any(Function));
expect(mockConnection.on).toHaveBeenCalledWith('reconnected', expect.any(Function));
});
it('should handle error events', () => {
dbManager.monitoringConnection = mockConnection;
dbManager.isConnected = true;
dbManager.setupConnectionHandlers();
// Simulate error event
const errorHandler = mockConnection.eventHandlers.error;
if (errorHandler) {
errorHandler(new Error('Test error'));
}
expect(dbManager.isConnected).toBe(false);
});
});
describe('sleep', () => {
it('should resolve after specified time', async () => {
const start = Date.now();
await dbManager.sleep(50);
const end = Date.now();
expect(end - start).toBeGreaterThanOrEqual(40); // Allow some tolerance
});
});
});