UNPKG

@ufdevsllc/authme2.0

Version:

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

350 lines (289 loc) 12.9 kB
import mongoose from 'mongoose'; import UsageLog from '../../models/usage-log.js'; describe('UsageLog Model', () => { beforeAll(async () => { await mongoose.connect('mongodb://localhost:27017/test-license-sdk-usage'); }); afterAll(async () => { await mongoose.connection.dropDatabase(); await mongoose.connection.close(); }); beforeEach(async () => { await UsageLog.deleteMany({}); }); describe('Schema Validation', () => { const validLogData = { licenseKey: 'TEST-LICENSE-123', action: 'validation', systemId: 'system-001', details: { operation: 'license_check', result: 'valid' }, success: true, duration: 150, ipAddress: '192.168.1.100', userAgent: 'Mozilla/5.0 Test Agent', sessionId: 'session-123', severity: 'info', category: 'security', tags: ['license', 'validation'] }; test('should create a valid usage log', async () => { const log = new UsageLog(validLogData); const saved = await log.save(); expect(saved._id).toBeDefined(); expect(saved.licenseKey).toBe(validLogData.licenseKey); expect(saved.action).toBe(validLogData.action); expect(saved.systemId).toBe(validLogData.systemId); expect(saved.success).toBe(validLogData.success); expect(saved.severity).toBe(validLogData.severity); expect(saved.category).toBe(validLogData.category); expect(saved.tags).toEqual(validLogData.tags); }); test('should require licenseKey, action, and systemId', async () => { const noLicense = new UsageLog({ ...validLogData, licenseKey: undefined }); await expect(noLicense.save()).rejects.toThrow('License key is required'); const noAction = new UsageLog({ ...validLogData, action: undefined }); await expect(noAction.save()).rejects.toThrow('Action is required'); const noSystemId = new UsageLog({ ...validLogData, systemId: undefined }); await expect(noSystemId.save()).rejects.toThrow('System ID is required'); }); test('should validate action enum', async () => { const invalidAction = new UsageLog({ ...validLogData, action: 'invalid_action' }); await expect(invalidAction.save()).rejects.toThrow('Action must be a valid operation type'); }); test('should validate severity enum', async () => { const invalidSeverity = new UsageLog({ ...validLogData, severity: 'invalid_severity' }); await expect(invalidSeverity.save()).rejects.toThrow('Severity must be one of: debug, info, warning, error, critical'); }); test('should validate IP address format', async () => { const invalidIP = new UsageLog({ ...validLogData, ipAddress: 'invalid-ip' }); await expect(invalidIP.save()).rejects.toThrow('Invalid IP address format'); }); test('should accept valid IPv4 and IPv6 addresses', async () => { const ipv4Log = new UsageLog({ ...validLogData, ipAddress: '10.0.0.1' }); await expect(ipv4Log.save()).resolves.toBeDefined(); const ipv6Log = new UsageLog({ ...validLogData, licenseKey: 'TEST-LICENSE-IPV6', ipAddress: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' }); await expect(ipv6Log.save()).resolves.toBeDefined(); }); test('should validate field lengths', async () => { const longSystemId = new UsageLog({ ...validLogData, systemId: 'a'.repeat(101) }); await expect(longSystemId.save()).rejects.toThrow('System ID cannot exceed 100 characters'); const longErrorMessage = new UsageLog({ ...validLogData, success: false, errorMessage: 'a'.repeat(1001) }); await expect(longErrorMessage.save()).rejects.toThrow('Error message cannot exceed 1000 characters'); const longUserAgent = new UsageLog({ ...validLogData, userAgent: 'a'.repeat(501) }); await expect(longUserAgent.save()).rejects.toThrow('User agent cannot exceed 500 characters'); const longCategory = new UsageLog({ ...validLogData, category: 'a'.repeat(51) }); await expect(longCategory.save()).rejects.toThrow('Category cannot exceed 50 characters'); }); test('should validate duration range', async () => { const negativeDuration = new UsageLog({ ...validLogData, duration: -1 }); await expect(negativeDuration.save()).rejects.toThrow('Duration cannot be negative'); const longDuration = new UsageLog({ ...validLogData, duration: 3600001 }); await expect(longDuration.save()).rejects.toThrow('Duration cannot exceed 1 hour (3600000ms)'); }); test('should validate details object size', async () => { const largeDetails = {}; for (let i = 0; i < 5000; i++) { largeDetails[`key${i}`] = 'a'.repeat(100); } const log = new UsageLog({ ...validLogData, details: largeDetails }); await expect(log.save()).rejects.toThrow('Details object cannot exceed 50KB'); }); test('should require error message when success is false', async () => { const errorLog = new UsageLog({ ...validLogData, success: false // Missing errorMessage }); await expect(errorLog.save()).rejects.toThrow('Error message is required when success is false'); }); test('should validate tag lengths', async () => { const longTag = new UsageLog({ ...validLogData, tags: ['a'.repeat(31)] }); await expect(longTag.save()).rejects.toThrow('Tag cannot exceed 30 characters'); }); }); describe('Virtual Properties', () => { test('should calculate ageInHours correctly', async () => { const oldLog = new UsageLog({ licenseKey: 'OLD-LICENSE-123', action: 'validation', systemId: 'system-001', timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) // 2 hours ago }); expect(oldLog.ageInHours).toBe(2); }); test('should calculate isRecent correctly', async () => { const recentLog = new UsageLog({ licenseKey: 'RECENT-LICENSE-123', action: 'validation', systemId: 'system-001', timestamp: new Date() // Current time }); const oldLog = new UsageLog({ licenseKey: 'OLD-LICENSE-123', action: 'validation', systemId: 'system-001', timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) // 2 hours ago }); expect(recentLog.isRecent).toBe(true); expect(oldLog.isRecent).toBe(false); }); }); describe('Static Methods', () => { test('createSuccessLog should create a success log', async () => { const log = await UsageLog.createSuccessLog( 'TEST-LICENSE-123', 'validation', 'system-001', { result: 'valid' } ); expect(log.licenseKey).toBe('TEST-LICENSE-123'); expect(log.action).toBe('validation'); expect(log.systemId).toBe('system-001'); expect(log.success).toBe(true); expect(log.severity).toBe('info'); expect(log.details).toEqual({ result: 'valid' }); }); test('createErrorLog should create an error log', async () => { const log = await UsageLog.createErrorLog( 'TEST-LICENSE-123', 'validation', 'system-001', 'License validation failed', { error: 'expired' } ); expect(log.licenseKey).toBe('TEST-LICENSE-123'); expect(log.action).toBe('validation'); expect(log.systemId).toBe('system-001'); expect(log.success).toBe(false); expect(log.severity).toBe('error'); expect(log.errorMessage).toBe('License validation failed'); expect(log.details).toEqual({ error: 'expired' }); }); test('getLogsByDateRange should filter logs by date', async () => { const startDate = new Date(Date.now() - 24 * 60 * 60 * 1000); // 24 hours ago const endDate = new Date(); // Create logs with different timestamps await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'validation', systemId: 'system-001', timestamp: new Date(Date.now() - 12 * 60 * 60 * 1000) // 12 hours ago (within range) }); await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'startup', systemId: 'system-001', timestamp: new Date(Date.now() - 48 * 60 * 60 * 1000) // 48 hours ago (outside range) }); const logs = await UsageLog.getLogsByDateRange('TEST-LICENSE-123', startDate, endDate); expect(logs).toHaveLength(1); expect(logs[0].action).toBe('validation'); }); test('getLogsByDateRange should filter by action when provided', async () => { await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'validation', systemId: 'system-001' }); await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'startup', systemId: 'system-001' }); const startDate = new Date(Date.now() - 60 * 60 * 1000); // 1 hour ago const endDate = new Date(); const validationLogs = await UsageLog.getLogsByDateRange('TEST-LICENSE-123', startDate, endDate, 'validation'); expect(validationLogs).toHaveLength(1); expect(validationLogs[0].action).toBe('validation'); }); test('getErrorLogs should return only failed logs', async () => { await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'validation', systemId: 'system-001', success: true }); await UsageLog.create({ licenseKey: 'TEST-LICENSE-123', action: 'startup', systemId: 'system-001', success: false, errorMessage: 'Startup failed' }); const errorLogs = await UsageLog.getErrorLogs('TEST-LICENSE-123'); expect(errorLogs).toHaveLength(1); expect(errorLogs[0].success).toBe(false); expect(errorLogs[0].action).toBe('startup'); }); }); describe('Instance Methods', () => { let log; beforeEach(async () => { log = new UsageLog({ licenseKey: 'TEST-LICENSE-METHODS-123', action: 'validation', systemId: 'system-001', tags: ['initial', 'test'] }); await log.save(); }); test('addTags should add new tags without duplicates', async () => { await log.addTags(['new', 'tags']); expect(log.tags).toContain('initial'); expect(log.tags).toContain('test'); expect(log.tags).toContain('new'); expect(log.tags).toContain('tags'); expect(log.tags).toHaveLength(4); }); test('addTags should not add duplicate tags', async () => { await log.addTags(['test', 'duplicate']); expect(log.tags.filter(tag => tag === 'test')).toHaveLength(1); expect(log.tags).toContain('duplicate'); }); test('addTags should handle single tag', async () => { await log.addTags('single'); expect(log.tags).toContain('single'); }); }); });