import { describe, it, expect, beforeEach } from 'vitest'; import { pauseQueue } from '../src/proxymodel/pause-queue.js'; beforeEach(() => { // Reset state between tests pauseQueue.setPaused(false); }); describe('PauseQueue', () => { it('returns transformed content immediately when not paused', async () => { const result = await pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'test/tool', original: 'raw content', transformed: 'processed content', }); expect(result).toBe('processed content'); expect(pauseQueue.size).toBe(0); }); it('holds content when paused', async () => { pauseQueue.setPaused(true); let resolved = false; const promise = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'test/tool', original: 'raw', transformed: 'processed', }).then((r) => { resolved = true; return r; }); // Should not resolve immediately await new Promise((r) => setTimeout(r, 50)); expect(resolved).toBe(false); expect(pauseQueue.size).toBe(1); // Release it const items = pauseQueue.getItems(); expect(items).toHaveLength(1); pauseQueue.releaseOne(items[0]!.id); const result = await promise; expect(result).toBe('processed'); expect(resolved).toBe(true); expect(pauseQueue.size).toBe(0); }); it('editAndRelease sends edited content', async () => { pauseQueue.setPaused(true); const promise = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'test/tool', original: 'raw', transformed: 'auto-processed', }); const items = pauseQueue.getItems(); pauseQueue.editAndRelease(items[0]!.id, 'manually-edited'); const result = await promise; expect(result).toBe('manually-edited'); }); it('dropOne sends empty content', async () => { pauseQueue.setPaused(true); const promise = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'test/tool', original: 'raw', transformed: 'processed', }); const items = pauseQueue.getItems(); pauseQueue.dropOne(items[0]!.id); const result = await promise; expect(result).toBe(''); }); it('setPaused(false) releases all queued items', async () => { pauseQueue.setPaused(true); const p1 = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool1', original: 'r1', transformed: 't1', }); const p2 = pauseQueue.enqueue({ sessionId: 's2', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool2', original: 'r2', transformed: 't2', }); expect(pauseQueue.size).toBe(2); // Resume releases all pauseQueue.setPaused(false); const [r1, r2] = await Promise.all([p1, p2]); expect(r1).toBe('t1'); expect(r2).toBe('t2'); expect(pauseQueue.size).toBe(0); }); it('releaseAll releases all items and returns count', async () => { pauseQueue.setPaused(true); const p1 = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool1', original: 'r1', transformed: 't1', }); const p2 = pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool2', original: 'r2', transformed: 't2', }); const count = pauseQueue.releaseAll(); expect(count).toBe(2); const [r1, r2] = await Promise.all([p1, p2]); expect(r1).toBe('t1'); expect(r2).toBe('t2'); }); it('returns false for operations on non-existent IDs', () => { expect(pauseQueue.releaseOne('nonexistent')).toBe(false); expect(pauseQueue.editAndRelease('nonexistent', 'x')).toBe(false); expect(pauseQueue.dropOne('nonexistent')).toBe(false); }); it('getItems strips internal resolve function', async () => { pauseQueue.setPaused(true); pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool', original: 'raw', transformed: 'processed', }); const items = pauseQueue.getItems(); expect(items).toHaveLength(1); const item = items[0]!; expect(item.id).toBeTruthy(); expect(item.sessionId).toBe('s1'); expect(item.projectName).toBe('proj'); expect(item.contentType).toBe('toolResult'); expect(item.sourceName).toBe('tool'); expect(item.original).toBe('raw'); expect(item.transformed).toBe('processed'); expect(item.timestamp).toBeGreaterThan(0); // Must not expose resolve expect((item as Record)['resolve']).toBeUndefined(); // Cleanup pauseQueue.releaseAll(); }); it('notifies subscribers on enqueue and release', async () => { const notifications: number[] = []; const unsub = pauseQueue.subscribe((items) => notifications.push(items.length)); pauseQueue.setPaused(true); pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool', original: 'r', transformed: 't', }); expect(notifications).toContain(1); pauseQueue.releaseAll(); expect(notifications).toContain(0); unsub(); }); it('each item gets a unique ID', async () => { pauseQueue.setPaused(true); pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool1', original: 'r1', transformed: 't1', }); pauseQueue.enqueue({ sessionId: 's1', projectName: 'proj', contentType: 'toolResult', sourceName: 'tool2', original: 'r2', transformed: 't2', }); const items = pauseQueue.getItems(); expect(items).toHaveLength(2); expect(items[0]!.id).not.toBe(items[1]!.id); pauseQueue.releaseAll(); }); });