UNPKG

@ufdevsllc/authme2.0

Version:

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

486 lines (390 loc) 19.6 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import RemoteControlHandler from '../remote-control-handler.js'; import DatabaseManager from '../database-manager.js'; // Mock DatabaseManager vi.mock('../database-manager.js'); describe('RemoteControlHandler', () => { let remoteControlHandler; let mockDatabaseManager; let mockDb; let mockCollection; beforeEach(() => { // Reset all mocks vi.clearAllMocks(); // Create mock collection mockCollection = { find: vi.fn(), updateOne: vi.fn(), insertOne: vi.fn() }; // Create mock database mockDb = { collection: vi.fn().mockReturnValue(mockCollection) }; // Create mock database manager mockDatabaseManager = { initMonitoringConnection: vi.fn().mockResolvedValue(), getMonitoringDB: vi.fn().mockReturnValue(mockDb), closeConnection: vi.fn().mockResolvedValue() }; // Mock the DatabaseManager constructor DatabaseManager.mockImplementation(() => mockDatabaseManager); remoteControlHandler = new RemoteControlHandler(); }); afterEach(() => { if (remoteControlHandler) { remoteControlHandler.stopCommandPolling(); } // Clean up environment variables delete process.env.SDK_APPLICATION_BLOCKED; delete process.env.SDK_BLOCK_REASON; }); describe('Constructor', () => { it('should initialize with default values', () => { expect(remoteControlHandler.isPolling).toBe(false); expect(remoteControlHandler.pollingInterval).toBeNull(); expect(remoteControlHandler.pollingIntervalMs).toBe(30000); expect(remoteControlHandler.currentLicenseKey).toBeNull(); expect(remoteControlHandler.applicationBlocked).toBe(false); expect(remoteControlHandler.commandHandlers).toBeInstanceOf(Map); expect(remoteControlHandler.commandHandlers.size).toBe(7); }); it('should initialize command handlers', () => { const expectedCommands = ['block', 'activate', 'deactivate', 'update', 'restart', 'status', 'config']; expectedCommands.forEach(command => { expect(remoteControlHandler.commandHandlers.has(command)).toBe(true); }); }); }); describe('initialize', () => { it('should initialize with valid license key', async () => { const licenseKey = 'test-license-123'; await remoteControlHandler.initialize(licenseKey); expect(remoteControlHandler.currentLicenseKey).toBe(licenseKey); expect(mockDatabaseManager.initMonitoringConnection).toHaveBeenCalledOnce(); }); it('should throw error if license key is not provided', async () => { await expect(remoteControlHandler.initialize()).rejects.toThrow('License key is required for remote control initialization'); await expect(remoteControlHandler.initialize('')).rejects.toThrow('License key is required for remote control initialization'); }); it('should handle database connection errors', async () => { const error = new Error('Database connection failed'); mockDatabaseManager.initMonitoringConnection.mockRejectedValue(error); await expect(remoteControlHandler.initialize('test-license')).rejects.toThrow('Database connection failed'); }); }); describe('checkForCommands', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); }); it('should retrieve pending commands for license key', async () => { const mockCommands = [ { _id: '1', command: 'block', licenseKey: 'test-license-123', status: 'pending' }, { _id: '2', command: 'activate', licenseKey: 'test-license-123', status: 'pending' } ]; const mockCursor = { sort: vi.fn().mockReturnThis(), toArray: vi.fn().mockResolvedValue(mockCommands) }; mockCollection.find.mockReturnValue(mockCursor); const commands = await remoteControlHandler.checkForCommands(); expect(mockCollection.find).toHaveBeenCalledWith({ licenseKey: 'test-license-123', status: 'pending', expiresAt: { $gt: expect.any(Date) } }); expect(mockCursor.sort).toHaveBeenCalledWith({ priority: -1, createdAt: 1 }); expect(commands).toEqual(mockCommands); }); it('should throw error if not initialized', async () => { const uninitializedHandler = new RemoteControlHandler(); await expect(uninitializedHandler.checkForCommands()).rejects.toThrow('Remote control handler not initialized with license key'); }); it('should handle database errors', async () => { const error = new Error('Database query failed'); mockCollection.find.mockImplementation(() => { throw error; }); await expect(remoteControlHandler.checkForCommands()).rejects.toThrow('Database query failed'); }); }); describe('executeCommand', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); mockCollection.updateOne.mockResolvedValue({ matchedCount: 1 }); }); it('should execute valid block command', async () => { const command = { _id: 'cmd-123', command: 'block', licenseKey: 'test-license-123', parameters: { reason: 'Test block' } }; const result = await remoteControlHandler.executeCommand(command); expect(result.success).toBe(true); expect(result.message).toContain('Application blocked successfully'); expect(remoteControlHandler.applicationBlocked).toBe(true); expect(process.env.SDK_APPLICATION_BLOCKED).toBe('true'); expect(process.env.SDK_BLOCK_REASON).toBe('Test block'); }); it('should execute valid activate command', async () => { const command = { _id: 'cmd-123', command: 'activate', licenseKey: 'test-license-123', parameters: {} }; const result = await remoteControlHandler.executeCommand(command); expect(result.success).toBe(true); expect(result.message).toContain('License activated successfully'); expect(remoteControlHandler.applicationBlocked).toBe(false); expect(process.env.SDK_APPLICATION_BLOCKED).toBeUndefined(); }); it('should execute valid status command', async () => { const command = { _id: 'cmd-123', command: 'status', licenseKey: 'test-license-123', parameters: {} }; const result = await remoteControlHandler.executeCommand(command); expect(result.success).toBe(true); expect(result.data).toHaveProperty('licenseKey', 'test-license-123'); expect(result.data).toHaveProperty('isBlocked'); expect(result.data).toHaveProperty('isPolling'); }); it('should validate command object', async () => { await expect(remoteControlHandler.executeCommand(null)).rejects.toThrow('Invalid command object'); await expect(remoteControlHandler.executeCommand({})).rejects.toThrow('Command missing required fields'); }); it('should validate license key match', async () => { const command = { _id: 'cmd-123', command: 'block', licenseKey: 'different-license', parameters: {} }; await expect(remoteControlHandler.executeCommand(command)).rejects.toThrow('Command license key does not match current license'); }); it('should handle unknown command types', async () => { const command = { _id: 'cmd-123', command: 'unknown', licenseKey: 'test-license-123', parameters: {} }; await expect(remoteControlHandler.executeCommand(command)).rejects.toThrow('Unknown command type: unknown'); }); it('should update command status during execution', async () => { const command = { _id: 'cmd-123', command: 'status', licenseKey: 'test-license-123', parameters: {} }; await remoteControlHandler.executeCommand(command); // Should be called twice: once for 'executing', once for 'executed' expect(mockCollection.updateOne).toHaveBeenCalledTimes(2); expect(mockCollection.updateOne).toHaveBeenCalledWith( { _id: 'cmd-123' }, { $set: { status: 'executing', executedAt: expect.any(Date) } } ); expect(mockCollection.updateOne).toHaveBeenCalledWith( { _id: 'cmd-123' }, { $set: { status: 'executed', result: expect.any(Object) } } ); }); }); describe('blockApplication', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); mockCollection.insertOne.mockResolvedValue({ insertedId: 'log-123' }); }); it('should block application with default reason', async () => { await remoteControlHandler.blockApplication(); expect(remoteControlHandler.applicationBlocked).toBe(true); expect(process.env.SDK_APPLICATION_BLOCKED).toBe('true'); expect(process.env.SDK_BLOCK_REASON).toBe('License violation detected'); }); it('should block application with custom reason', async () => { const customReason = 'Custom block reason'; await remoteControlHandler.blockApplication(customReason); expect(remoteControlHandler.applicationBlocked).toBe(true); expect(process.env.SDK_BLOCK_REASON).toBe(customReason); }); it('should log blocking event', async () => { await remoteControlHandler.blockApplication('Test reason'); expect(mockCollection.insertOne).toHaveBeenCalledWith({ licenseKey: 'test-license-123', action: 'remote_control_application_blocked', timestamp: expect.any(Date), systemId: expect.any(String), details: { reason: 'Test reason', timestamp: expect.any(Date), licenseKey: 'test-license-123' }, success: true }); }); }); describe('updateLicenseStatus', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); mockCollection.updateOne.mockResolvedValue({ matchedCount: 1 }); mockCollection.insertOne.mockResolvedValue({ insertedId: 'log-123' }); }); it('should update license status to active', async () => { await remoteControlHandler.updateLicenseStatus('active'); expect(mockDb.collection).toHaveBeenCalledWith('licenses'); expect(mockCollection.updateOne).toHaveBeenCalledWith( { licenseKey: 'test-license-123' }, { $set: { isActive: true, lastStatusUpdate: expect.any(Date) } } ); }); it('should update license status to inactive', async () => { await remoteControlHandler.updateLicenseStatus('inactive'); expect(mockCollection.updateOne).toHaveBeenCalledWith( { licenseKey: 'test-license-123' }, { $set: { isActive: false, lastStatusUpdate: expect.any(Date) } } ); }); it('should include additional data in update', async () => { const additionalData = { reason: 'Manual update', updatedBy: 'admin' }; await remoteControlHandler.updateLicenseStatus('active', additionalData); expect(mockCollection.updateOne).toHaveBeenCalledWith( { licenseKey: 'test-license-123' }, { $set: { isActive: true, lastStatusUpdate: expect.any(Date), ...additionalData } } ); }); it('should throw error if no license key available', async () => { const uninitializedHandler = new RemoteControlHandler(); await expect(uninitializedHandler.updateLicenseStatus('active')).rejects.toThrow('No license key available for status update'); }); }); describe('Command Polling', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); it('should start command polling', () => { remoteControlHandler.startCommandPolling(1000); expect(remoteControlHandler.isPolling).toBe(true); expect(remoteControlHandler.pollingIntervalMs).toBe(1000); expect(remoteControlHandler.pollingInterval).not.toBeNull(); }); it('should not start polling if already running', () => { remoteControlHandler.startCommandPolling(1000); const firstInterval = remoteControlHandler.pollingInterval; remoteControlHandler.startCommandPolling(2000); expect(remoteControlHandler.pollingInterval).toBe(firstInterval); expect(remoteControlHandler.pollingIntervalMs).toBe(1000); // Should not change }); it('should stop command polling', () => { remoteControlHandler.startCommandPolling(1000); remoteControlHandler.stopCommandPolling(); expect(remoteControlHandler.isPolling).toBe(false); expect(remoteControlHandler.pollingInterval).toBeNull(); }); it('should execute commands during polling', async () => { const mockCommands = [ { _id: 'cmd-1', command: 'status', licenseKey: 'test-license-123', parameters: {} } ]; const mockCursor = { sort: vi.fn().mockReturnThis(), toArray: vi.fn().mockResolvedValue(mockCommands) }; mockCollection.find.mockReturnValue(mockCursor); mockCollection.updateOne.mockResolvedValue({ matchedCount: 1 }); remoteControlHandler.startCommandPolling(1000); // Fast-forward time to trigger polling await vi.advanceTimersByTimeAsync(1000); expect(mockCollection.find).toHaveBeenCalled(); expect(mockCollection.updateOne).toHaveBeenCalled(); }); }); describe('Application State', () => { it('should check if application is blocked', () => { expect(remoteControlHandler.isApplicationBlocked()).toBe(false); remoteControlHandler.applicationBlocked = true; expect(remoteControlHandler.isApplicationBlocked()).toBe(true); remoteControlHandler.applicationBlocked = false; process.env.SDK_APPLICATION_BLOCKED = 'true'; expect(remoteControlHandler.isApplicationBlocked()).toBe(true); }); it('should get block reason', () => { expect(remoteControlHandler.getBlockReason()).toBeNull(); process.env.SDK_BLOCK_REASON = 'Test reason'; expect(remoteControlHandler.getBlockReason()).toBe('Test reason'); }); }); describe('Command Handlers', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); mockCollection.updateOne.mockResolvedValue({ matchedCount: 1 }); mockCollection.insertOne.mockResolvedValue({ insertedId: 'log-123' }); }); it('should handle deactivate command', async () => { const result = await remoteControlHandler.handleDeactivateCommand({ reason: 'Test deactivation' }); expect(result.message).toContain('License deactivated successfully'); expect(result.data.status).toBe('inactive'); expect(remoteControlHandler.applicationBlocked).toBe(true); }); it('should handle update command', async () => { const parameters = { newLimit: 10, updatedBy: 'admin' }; const result = await remoteControlHandler.handleUpdateCommand(parameters); expect(result.message).toContain('License updated successfully'); expect(result.data).toEqual(parameters); }); it('should handle restart command', async () => { const result = await remoteControlHandler.handleRestartCommand({}); expect(result.message).toContain('Restart command acknowledged'); expect(result.data.restartRequested).toBe(true); }); it('should handle config command', async () => { const parameters = { pollingInterval: 5000 }; const result = await remoteControlHandler.handleConfigCommand(parameters); expect(result.message).toContain('Configuration updated successfully'); expect(remoteControlHandler.pollingIntervalMs).toBe(5000); }); }); describe('Cleanup', () => { it('should cleanup resources', async () => { await remoteControlHandler.initialize('test-license-123'); remoteControlHandler.startCommandPolling(1000); await remoteControlHandler.cleanup(); expect(remoteControlHandler.isPolling).toBe(false); expect(mockDatabaseManager.closeConnection).toHaveBeenCalledOnce(); }); }); describe('Error Handling', () => { beforeEach(async () => { await remoteControlHandler.initialize('test-license-123'); }); it('should handle database errors gracefully during logging', async () => { mockCollection.insertOne.mockRejectedValue(new Error('Database error')); // Should not throw error for logging failures await expect(remoteControlHandler.logRemoteControlEvent('test', {})).resolves.toBeUndefined(); }); it('should handle command execution errors', async () => { const command = { _id: 'cmd-123', command: 'block', licenseKey: 'test-license-123', parameters: {} }; // Mock blockApplication to throw error vi.spyOn(remoteControlHandler, 'blockApplication').mockRejectedValue(new Error('Block failed')); mockCollection.updateOne.mockResolvedValue({ matchedCount: 1 }); await expect(remoteControlHandler.executeCommand(command)).rejects.toThrow('Block failed'); // Should mark command as failed expect(mockCollection.updateOne).toHaveBeenCalledWith( { _id: 'cmd-123' }, { $set: { status: 'failed', result: expect.objectContaining({ success: false }) } } ); }); }); });