UNPKG

@ufdevsllc/authme2.0

Version:

SDK for license management and remote monitoring with automatic system tracking, license validation, and remote control capabilities

356 lines (279 loc) 15.3 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import DataLogger from '../data-logger.js'; import DatabaseManager from '../database-manager.js'; // Mock the DatabaseManager vi.mock('../database-manager.js'); describe('DataLogger', () => { let dataLogger; let mockDatabaseManager; beforeEach(() => { // Reset all mocks vi.clearAllMocks(); // Create mock database manager mockDatabaseManager = { initMonitoringConnection: vi.fn(), isMonitoringConnected: vi.fn(), saveUserData: vi.fn(), closeConnection: vi.fn() }; // Mock the DatabaseManager constructor DatabaseManager.mockImplementation(() => mockDatabaseManager); dataLogger = new DataLogger(); }); afterEach(async () => { if (dataLogger) { await dataLogger.close(); } }); describe('Initialization', () => { it('should initialize successfully', async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); await dataLogger.init(); expect(mockDatabaseManager.initMonitoringConnection).toHaveBeenCalledOnce(); expect(dataLogger.isInitialized).toBe(true); }); it('should handle initialization failure', async () => { const error = new Error('Connection failed'); mockDatabaseManager.initMonitoringConnection.mockRejectedValue(error); await expect(dataLogger.init()).rejects.toThrow('DataLogger initialization failed: Connection failed'); expect(dataLogger.isInitialized).toBe(false); }); it('should not reinitialize if already initialized', async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); await dataLogger.init(); await dataLogger.init(); expect(mockDatabaseManager.initMonitoringConnection).toHaveBeenCalledOnce(); }); }); describe('Input Validation', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should validate collection name in logData', async () => { await expect(dataLogger.logData('', { test: 'data' })).rejects.toThrow('Collection name must be a non-empty string'); await expect(dataLogger.logData(null, { test: 'data' })).rejects.toThrow('Collection name must be a non-empty string'); await expect(dataLogger.logData(123, { test: 'data' })).rejects.toThrow('Collection name must be a non-empty string'); }); it('should validate data in logData', async () => { await expect(dataLogger.logData('test', null)).rejects.toThrow('Data cannot be null or undefined'); await expect(dataLogger.logData('test', undefined)).rejects.toThrow('Data cannot be null or undefined'); }); it('should validate operation type in logData', async () => { await expect(dataLogger.logData('test', { data: 'test' }, 123)).rejects.toThrow('Operation must be a string'); }); it('should validate userId in logUserActivity', async () => { await expect(dataLogger.logUserActivity('', 'login')).rejects.toThrow('User ID must be a non-empty string'); await expect(dataLogger.logUserActivity(null, 'login')).rejects.toThrow('User ID must be a non-empty string'); await expect(dataLogger.logUserActivity(123, 'login')).rejects.toThrow('User ID must be a non-empty string'); }); it('should validate action in logUserActivity', async () => { await expect(dataLogger.logUserActivity('user123', '')).rejects.toThrow('Action must be a non-empty string'); await expect(dataLogger.logUserActivity('user123', null)).rejects.toThrow('Action must be a non-empty string'); await expect(dataLogger.logUserActivity('user123', 123)).rejects.toThrow('Action must be a non-empty string'); }); it('should validate modelName in logModelOperation', async () => { await expect(dataLogger.logModelOperation('', 'save', {})).rejects.toThrow('Model name must be a non-empty string'); await expect(dataLogger.logModelOperation(null, 'save', {})).rejects.toThrow('Model name must be a non-empty string'); await expect(dataLogger.logModelOperation(123, 'save', {})).rejects.toThrow('Model name must be a non-empty string'); }); }); describe('logData', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should log data successfully', async () => { const testData = { name: 'test', value: 123 }; const mockResult = { insertedId: 'mock-id' }; mockDatabaseManager.saveUserData.mockResolvedValue(mockResult); const result = await dataLogger.logData('test_collection', testData, 'create'); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledWith('usage_logs', { collectionName: 'test_collection', operation: 'create', data: testData, timestamp: expect.any(Date), logType: 'general_data' }); expect(result).toBe(mockResult); }); it('should use default operation when not provided', async () => { const testData = { name: 'test' }; mockDatabaseManager.saveUserData.mockResolvedValue({}); await dataLogger.logData('test_collection', testData); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledWith('usage_logs', expect.objectContaining({ operation: 'unknown' })); }); it('should handle database save errors', async () => { const error = new Error('Database error'); mockDatabaseManager.saveUserData.mockRejectedValue(error); await expect(dataLogger.logData('test', { data: 'test' })).rejects.toThrow('Failed to log data: Database error'); }); it('should require initialization', async () => { const uninitializedLogger = new DataLogger(); await expect(uninitializedLogger.logData('test', { data: 'test' })).rejects.toThrow('DataLogger not initialized'); }); it('should require database connection', async () => { mockDatabaseManager.isMonitoringConnected.mockReturnValue(false); await expect(dataLogger.logData('test', { data: 'test' })).rejects.toThrow('Monitoring database not connected'); }); }); describe('logUserActivity', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should log user activity successfully', async () => { const mockResult = { insertedId: 'mock-id' }; mockDatabaseManager.saveUserData.mockResolvedValue(mockResult); const result = await dataLogger.logUserActivity('user123', 'login', { ip: '192.168.1.1' }); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledWith('usage_logs', { userId: 'user123', action: 'login', details: { ip: '192.168.1.1' }, timestamp: expect.any(Date), logType: 'user_activity' }); expect(result).toBe(mockResult); }); it('should use empty object as default details', async () => { mockDatabaseManager.saveUserData.mockResolvedValue({}); await dataLogger.logUserActivity('user123', 'logout'); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledWith('usage_logs', expect.objectContaining({ details: {} })); }); it('should handle database save errors', async () => { const error = new Error('Database error'); mockDatabaseManager.saveUserData.mockRejectedValue(error); await expect(dataLogger.logUserActivity('user123', 'login')).rejects.toThrow('Failed to log user activity: Database error'); }); }); describe('logModelOperation', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should log model operation successfully', async () => { const testData = { id: 1, name: 'test' }; const mockResult = { insertedId: 'mock-id' }; mockDatabaseManager.saveUserData.mockResolvedValue(mockResult); const result = await dataLogger.logModelOperation('User', 'save', testData); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledWith('usage_logs', { modelName: 'User', operation: 'save', data: testData, timestamp: expect.any(Date), logType: 'model_operation' }); expect(result).toBe(mockResult); }); it('should handle database save errors', async () => { const error = new Error('Database error'); mockDatabaseManager.saveUserData.mockRejectedValue(error); await expect(dataLogger.logModelOperation('User', 'save', {})).rejects.toThrow('Failed to log model operation: Database error'); }); }); describe('bulkLog', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should validate operations array', async () => { await expect(dataLogger.bulkLog(null)).rejects.toThrow('Operations must be an array'); await expect(dataLogger.bulkLog('not-array')).rejects.toThrow('Operations must be an array'); await expect(dataLogger.bulkLog([])).rejects.toThrow('Operations array cannot be empty'); }); it('should process multiple operations successfully', async () => { const operations = [ { type: 'logData', collectionName: 'test1', data: { value: 1 }, operation: 'create' }, { type: 'logUserActivity', userId: 'user123', action: 'login', details: {} }, { type: 'logModelOperation', modelName: 'User', operation: 'save', data: { id: 1 } } ]; mockDatabaseManager.saveUserData.mockResolvedValue({ insertedId: 'mock-id' }); const results = await dataLogger.bulkLog(operations); expect(results).toHaveLength(3); expect(results.every(r => r.success)).toBe(true); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledTimes(3); }); it('should handle mixed success and failure operations', async () => { const operations = [ { type: 'logData', collectionName: 'test1', data: { value: 1 }, operation: 'create' }, { type: 'logUserActivity', userId: '', action: 'login' }, // This will fail { type: 'logModelOperation', modelName: 'User', operation: 'save', data: { id: 1 } } ]; mockDatabaseManager.saveUserData.mockResolvedValue({ insertedId: 'mock-id' }); const results = await dataLogger.bulkLog(operations); expect(results).toHaveLength(3); expect(results[0].success).toBe(true); expect(results[1].success).toBe(false); expect(results[2].success).toBe(true); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledTimes(2); }); it('should throw error when all operations fail', async () => { const operations = [ { type: 'logUserActivity', userId: '', action: 'login' }, { type: 'logModelOperation', modelName: '', operation: 'save', data: {} } ]; await expect(dataLogger.bulkLog(operations)).rejects.toThrow('All bulk operations failed'); }); it('should validate operation structure', async () => { const operations = [ null, { type: 'invalid-type', data: {} }, { /* missing type */ data: {} } ]; await expect(dataLogger.bulkLog(operations)).rejects.toThrow('All bulk operations failed'); }); }); describe('Utility Methods', () => { it('should check if ready correctly', async () => { expect(dataLogger.isReady()).toBe(false); mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); expect(dataLogger.isReady()).toBe(true); mockDatabaseManager.isMonitoringConnected.mockReturnValue(false); expect(dataLogger.isReady()).toBe(false); }); it('should close connections properly', async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); await dataLogger.init(); await dataLogger.close(); expect(mockDatabaseManager.closeConnection).toHaveBeenCalledOnce(); expect(dataLogger.isInitialized).toBe(false); }); }); describe('Data Serialization', () => { beforeEach(async () => { mockDatabaseManager.initMonitoringConnection.mockResolvedValue(); mockDatabaseManager.isMonitoringConnected.mockReturnValue(true); await dataLogger.init(); }); it('should handle complex objects in logData', async () => { const complexData = { nested: { value: 123 }, array: [1, 2, 3], date: new Date(), func: () => { } // This should be serialized properly }; mockDatabaseManager.saveUserData.mockResolvedValue({}); await dataLogger.logData('test', complexData); const savedData = mockDatabaseManager.saveUserData.mock.calls[0][1]; expect(savedData.data).toEqual(JSON.parse(JSON.stringify(complexData))); }); it('should handle primitive data types', async () => { mockDatabaseManager.saveUserData.mockResolvedValue({}); await dataLogger.logData('test', 'string data'); await dataLogger.logData('test', 123); await dataLogger.logData('test', true); expect(mockDatabaseManager.saveUserData).toHaveBeenCalledTimes(3); }); }); });