@ufdevsllc/authme2.0
Version:
SDK for license management and remote monitoring with automatic system tracking, license validation, and remote control capabilities
278 lines (228 loc) • 10.5 kB
JavaScript
import mongoose from 'mongoose';
import RemoteCommand from '../../models/remote-command.js';
describe('RemoteCommand Model', () => {
beforeAll(async () => {
await mongoose.connect('mongodb://localhost:27017/test-license-sdk-command');
});
afterAll(async () => {
await mongoose.connection.dropDatabase();
await mongoose.connection.close();
});
beforeEach(async () => {
await RemoteCommand.deleteMany({});
});
describe('Schema Validation', () => {
const validCommandData = {
licenseKey: 'TEST-LICENSE-123',
command: 'block',
parameters: { reason: 'License violation' },
priority: 5
};
test('should create a valid remote command', async () => {
const command = new RemoteCommand(validCommandData);
const saved = await command.save();
expect(saved._id).toBeDefined();
expect(saved.licenseKey).toBe(validCommandData.licenseKey);
expect(saved.command).toBe(validCommandData.command);
expect(saved.status).toBe('pending');
expect(saved.priority).toBe(validCommandData.priority);
expect(saved.retryCount).toBe(0);
expect(saved.maxRetries).toBe(3);
});
test('should require licenseKey and command', async () => {
const noLicense = new RemoteCommand({ ...validCommandData, licenseKey: undefined });
await expect(noLicense.save()).rejects.toThrow('License key is required');
const noCommand = new RemoteCommand({ ...validCommandData, command: undefined });
await expect(noCommand.save()).rejects.toThrow('Command is required');
});
test('should validate command enum', async () => {
const invalidCommand = new RemoteCommand({
...validCommandData,
command: 'invalid_command'
});
await expect(invalidCommand.save()).rejects.toThrow('Command must be one of: block, activate, deactivate, update, restart, status, config');
});
test('should validate status enum', async () => {
const invalidStatus = new RemoteCommand({
...validCommandData,
status: 'invalid_status'
});
await expect(invalidStatus.save()).rejects.toThrow('Status must be one of: pending, executing, executed, failed, cancelled');
});
test('should validate priority range', async () => {
const lowPriority = new RemoteCommand({ ...validCommandData, priority: 0 });
await expect(lowPriority.save()).rejects.toThrow('Priority must be at least 1');
const highPriority = new RemoteCommand({ ...validCommandData, priority: 11 });
await expect(highPriority.save()).rejects.toThrow('Priority cannot exceed 10');
});
test('should validate executedAt is after createdAt', async () => {
const command = new RemoteCommand({
...validCommandData,
executedAt: new Date(Date.now() - 24 * 60 * 60 * 1000) // Yesterday
});
await expect(command.save()).rejects.toThrow('Execution date cannot be before creation date');
});
test('should validate expiresAt is after createdAt', async () => {
const command = new RemoteCommand({
...validCommandData,
expiresAt: new Date(Date.now() - 60 * 60 * 1000) // 1 hour ago
});
await expect(command.save()).rejects.toThrow('Expiration date must be after creation date');
});
test('should validate parameters size', async () => {
const largeParams = {};
for (let i = 0; i < 1000; i++) {
largeParams[`key${i}`] = 'a'.repeat(100);
}
const command = new RemoteCommand({
...validCommandData,
parameters: largeParams
});
await expect(command.save()).rejects.toThrow('Parameters must be an object and cannot exceed 10KB');
});
test('should validate retry counts', async () => {
const highRetry = new RemoteCommand({
...validCommandData,
retryCount: 6
});
await expect(highRetry.save()).rejects.toThrow('Retry count cannot exceed 5');
const highMaxRetry = new RemoteCommand({
...validCommandData,
maxRetries: 6
});
await expect(highMaxRetry.save()).rejects.toThrow('Max retries cannot exceed 5');
});
});
describe('Virtual Properties', () => {
test('should calculate isExpired correctly', async () => {
const activeCommand = new RemoteCommand({
licenseKey: 'ACTIVE-LICENSE-123',
command: 'block',
expiresAt: new Date(Date.now() + 60 * 60 * 1000) // 1 hour from now
});
const expiredCommand = new RemoteCommand({
licenseKey: 'EXPIRED-LICENSE-123',
command: 'block',
expiresAt: new Date(Date.now() - 60 * 60 * 1000) // 1 hour ago
});
expect(activeCommand.isExpired).toBe(false);
expect(expiredCommand.isExpired).toBe(true);
});
test('should calculate canRetry correctly', async () => {
const retryableCommand = new RemoteCommand({
licenseKey: 'RETRY-LICENSE-123',
command: 'block',
status: 'failed',
retryCount: 2,
maxRetries: 3
});
const nonRetryableCommand = new RemoteCommand({
licenseKey: 'NO-RETRY-LICENSE-123',
command: 'block',
status: 'failed',
retryCount: 3,
maxRetries: 3
});
expect(retryableCommand.canRetry).toBe(true);
expect(nonRetryableCommand.canRetry).toBe(false);
});
});
describe('Instance Methods', () => {
let command;
beforeEach(async () => {
command = new RemoteCommand({
licenseKey: 'TEST-LICENSE-METHODS-123',
command: 'block',
parameters: { reason: 'Test' }
});
await command.save();
});
test('markAsExecuting should update status', async () => {
expect(command.status).toBe('pending');
await command.markAsExecuting();
expect(command.status).toBe('executing');
});
test('markAsExecuted should update status and result', async () => {
const result = {
message: 'Command executed successfully',
data: { blocked: true },
executionTime: 150
};
await command.markAsExecuted(result);
expect(command.status).toBe('executed');
expect(command.executedAt).toBeDefined();
expect(command.result.success).toBe(true);
expect(command.result.message).toBe(result.message);
expect(command.result.data).toEqual(result.data);
expect(command.result.executionTime).toBe(result.executionTime);
});
test('markAsFailed should update status and result', async () => {
const error = {
message: 'Command execution failed',
data: { error: 'Network timeout' },
executionTime: 5000
};
await command.markAsFailed(error);
expect(command.status).toBe('failed');
expect(command.executedAt).toBeDefined();
expect(command.result.success).toBe(false);
expect(command.result.message).toBe(error.message);
expect(command.result.data).toEqual(error.data);
expect(command.result.executionTime).toBe(error.executionTime);
});
test('retry should increment retry count and reset status', async () => {
// First mark as failed
await command.markAsFailed({ message: 'Test failure' });
expect(command.status).toBe('failed');
expect(command.retryCount).toBe(0);
// Then retry
await command.retry();
expect(command.status).toBe('pending');
expect(command.retryCount).toBe(1);
expect(command.executedAt).toBeUndefined();
expect(command.result).toEqual({});
});
test('retry should throw error when cannot retry', async () => {
// Create a fresh command for this test
const testCommand = new RemoteCommand({
licenseKey: 'TEST-LICENSE-RETRY-123',
command: 'block',
parameters: { reason: 'Test' },
retryCount: 3,
maxRetries: 3,
status: 'failed'
});
await testCommand.save();
try {
await testCommand.retry();
expect.fail('Expected retry to throw an error');
} catch (error) {
expect(error.message).toBe('Command cannot be retried');
}
});
test('cancel should update status for pending commands', async () => {
expect(command.status).toBe('pending');
await command.cancel();
expect(command.status).toBe('cancelled');
expect(command.executedAt).toBeDefined();
expect(command.result.success).toBe(false);
expect(command.result.message).toBe('Command was cancelled');
});
test('cancel should throw error for non-pending commands', async () => {
// Create a fresh command for this test
const testCommand = new RemoteCommand({
licenseKey: 'TEST-LICENSE-CANCEL-123',
command: 'block',
parameters: { reason: 'Test' }
});
await testCommand.save();
await testCommand.markAsExecuting();
try {
await testCommand.cancel();
expect.fail('Expected cancel to throw an error');
} catch (error) {
expect(error.message).toBe('Only pending commands can be cancelled');
}
});
});
});