/** * Unit Tests — engine/command-queue.js */ import { describe, it, expect } from 'vitest'; const { CommandQueue, CommandLaneClearedError } = require('../../src/engine/command-queue'); describe('CommandQueue', () => { describe('basic enqueue', () => { it('should execute a simple task', async () => { const q = new CommandQueue(); const result = await q.enqueue('main', async () => 42); expect(result).toBe(42); }); it('should execute tasks in order within a lane', async () => { const q = new CommandQueue(); const order = []; await Promise.all([ q.enqueue('main', async () => { order.push(1); }), q.enqueue('main', async () => { order.push(2); }), q.enqueue('main', async () => { order.push(3); }), ]); expect(order).toEqual([1, 2, 3]); }); it('should run different lanes in parallel', async () => { const q = new CommandQueue(); const results = []; await Promise.all([ q.enqueue('A', async () => { results.push('A'); }), q.enqueue('B', async () => { results.push('B'); }), ]); expect(results).toContain('A'); expect(results).toContain('B'); }); }); describe('clearAll', () => { it('should increment generation', () => { const q = new CommandQueue(); const gen0 = q.generation; q.clearAll(); expect(q.generation).toBe(gen0 + 1); }); it('should reject queued tasks with CommandLaneClearedError', async () => { const q = new CommandQueue(); // Enqueue a slow task to block the lane q.enqueue('main', () => new Promise(r => setTimeout(r, 200))); // Queue another behind it const p = q.enqueue('main', async () => 'should not run'); // Clear immediately q.clearAll(); await expect(p).rejects.toThrow(CommandLaneClearedError); }); }); describe('clearLane', () => { it('should clear a specific lane', () => { const q = new CommandQueue(); q.enqueue('A', async () => {}); q.clearLane('A'); expect(q.size).toBe(0); }); }); describe('size', () => { it('should reflect active lane count', async () => { const q = new CommandQueue(); expect(q.size).toBe(0); const p = q.enqueue('lane1', () => new Promise(r => setTimeout(r, 100))); expect(q.size).toBe(1); await p; }); }); describe('CommandLaneClearedError', () => { it('should be an Error subclass', () => { const err = new CommandLaneClearedError('test'); expect(err).toBeInstanceOf(Error); expect(err.name).toBe('CommandLaneClearedError'); expect(err.lane).toBe('test'); }); it('should work without lane name', () => { const err = new CommandLaneClearedError(); expect(err.message).toContain('cleared'); }); }); describe('error handling in tasks', () => { it('should propagate task errors', async () => { const q = new CommandQueue(); await expect( q.enqueue('main', async () => { throw new Error('task failed'); }) ).rejects.toThrow('task failed'); }); it('should continue lane after a failed task', async () => { const q = new CommandQueue(); try { await q.enqueue('main', async () => { throw new Error('fail'); }); } catch {} // Next task should still work const result = await q.enqueue('main', async () => 'ok'); expect(result).toBe('ok'); }); }); });