@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
JavaScript
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 }) } }
);
});
});
});