import { describe, it, expect } from 'vitest' import { Command, CommandStatus, CommandType, Priority } from '../../../app/domain/commands/command.js' import { DeviceId } from '../../../app/domain/device/device_id.js' function makeCommand(status = CommandStatus.PENDING) { return new Command('cmd-1', new DeviceId('Mfr', 'OUI', 'PC', 'SN'), CommandType.REFRESH, {}, Priority.NORMAL, new Date(), status) } describe('Command', () => { it('creates with PENDING status by default', () => { const cmd = makeCommand() expect(cmd.status).toBe(CommandStatus.PENDING) expect(cmd.canExecute()).toBe(true) expect(cmd.isCompleted()).toBe(false) }) it('markAsSent transitions PENDING → SENT', () => { const cmd = makeCommand() cmd.markAsSent() expect(cmd.status).toBe(CommandStatus.SENT) expect(cmd.executedAt).not.toBeNull() }) it('markAsSent throws if not PENDING', () => { const cmd = makeCommand(CommandStatus.SENT) expect(() => cmd.markAsSent()).toThrow('Cannot mark command as sent') }) it('markAsWaiting transitions SENT → WAITING', () => { const cmd = makeCommand() cmd.markAsSent() cmd.markAsWaiting() expect(cmd.status).toBe(CommandStatus.WAITING) }) it('markAsWaiting throws if not SENT', () => { const cmd = makeCommand() expect(() => cmd.markAsWaiting()).toThrow('Cannot mark command as waiting') }) it('complete transitions SENT → COMPLETED', () => { const cmd = makeCommand() cmd.markAsSent() cmd.complete({ success: true, timestamp: new Date() }) expect(cmd.status).toBe(CommandStatus.COMPLETED) expect(cmd.result?.success).toBe(true) expect(cmd.isCompleted()).toBe(true) }) it('complete throws if PENDING', () => { const cmd = makeCommand() expect(() => cmd.complete({ success: true, timestamp: new Date() } as any)).toThrow('Cannot complete command') }) it('fail transitions to FAILED', () => { const cmd = makeCommand() cmd.markAsSent() cmd.fail('timeout') expect(cmd.status).toBe(CommandStatus.FAILED) expect(cmd.error).toBe('timeout') expect(cmd.isCompleted()).toBe(true) }) it('fail throws if already COMPLETED', () => { const cmd = makeCommand() cmd.markAsSent() cmd.complete({ success: true, timestamp: new Date() } as any) expect(() => cmd.fail('oops')).toThrow('Cannot fail a successful command') }) it('cancel transitions PENDING → CANCELLED', () => { const cmd = makeCommand() cmd.cancel() expect(cmd.status).toBe(CommandStatus.CANCELLED) expect(cmd.isCompleted()).toBe(true) }) it('cancel throws if COMPLETED', () => { const cmd = makeCommand() cmd.markAsSent() cmd.complete({ success: true, timestamp: new Date() } as any) expect(() => cmd.cancel()).toThrow('Cannot cancel command') }) it('hasExpired returns true for old commands', () => { const old = new Date(Date.now() - 60 * 60 * 1000) // 1h ago const cmd = new Command('x', new DeviceId('M', 'O', 'P', 'S'), CommandType.REFRESH, {}, Priority.NORMAL, old) expect(cmd.hasExpired(30)).toBe(true) }) it('hasExpired returns false for fresh commands', () => { const cmd = makeCommand() expect(cmd.hasExpired(30)).toBe(false) }) })