CoolFace
Apppublic

Leon4gr45/builder

sourceHugging Facemitupdated 3d agoView on Hugging Face
0likes
integration.test.ts117 linesDownload Raw Back to __tests__
1import { describe, it, expect, beforeEach, afterEach } from 'vitest';2import { TaskManager } from '../task-manager';3import { SSEEventBus } from '../sse-event-bus';4import { ServerConfigManager } from '../server-config-manager';5 6describe('Server-side generation integration', () => {7  let tm: TaskManager;8  let bus: SSEEventBus;9 10  beforeEach(() => {11    tm = new TaskManager({ maxConcurrentPerScope: 3, keyTTLMs: 30 * 60 * 1000 });12    bus = new SSEEventBus({ maxBufferSize: 500 });13  });14 15  afterEach(() => {16    tm.dispose();17  });18 19  it('full lifecycle: create task → emit events → complete → cleanup', () => {20    const taskId = tm.createTask('proj-1', 'sess-1', 'sk-key');21    expect(tm.getTask(taskId)?.status).toBe('running');22    expect(tm.getApiKey(taskId)).toBe('sk-key');23 24    const received: any[] = [];25    bus.addListener('sess-1', (e) => received.push(e));26 27    bus.emit(taskId, 'proj-1', 'assistant_delta', { text: 'Hello' }, 'sess-1');28    bus.emit(taskId, 'proj-1', 'tool_status', { status: 'running' }, 'sess-1');29    bus.emit(taskId, 'proj-1', 'task_complete', { result: 'success' }, 'sess-1');30 31    expect(received).toHaveLength(3);32    expect(bus.getBuffer(taskId)).toHaveLength(2); // delta not buffered33 34    tm.completeTask(taskId, 'completed');35    expect(tm.getTask(taskId)?.status).toBe('completed');36    expect(tm.getApiKey(taskId)).toBeUndefined();37  });38 39  it('SSE reconnect replays non-delta events', () => {40    const taskId = tm.createTask('proj-1', 'sess-1', 'sk-key');41    bus.emit(taskId, 'proj-1', 'assistant_delta', { text: 'a' }, 'sess-1');42    bus.emit(taskId, 'proj-1', 'tool_status', { status: 'started' }, 'sess-1');43    bus.emit(taskId, 'proj-1', 'conversation_message', { msg: 'hi' }, 'sess-1');44 45    const replayed = bus.replayFrom(taskId, 0);46    expect(replayed).toHaveLength(2);47    expect(replayed![0].event).toBe('tool_status');48    expect(replayed![1].event).toBe('conversation_message');49  });50 51  it('task limit enforcement across create and complete', () => {52    const t1 = tm.createTask('p1', 's1', 'k1', 'ws-1');53    tm.createTask('p2', 's1', 'k2', 'ws-1');54    tm.createTask('p3', 's1', 'k3', 'ws-1');55 56    expect(() => tm.createTask('p4', 's1', 'k4', 'ws-1')).toThrow();57 58    tm.completeTask(t1, 'completed');59    const t4 = tm.createTask('p4', 's1', 'k4', 'ws-1');60    expect(t4).toBeDefined();61  });62 63  it('fresh tab reconnect (lastEventId=0) replays full buffer via getBuffer', () => {64    const taskId = tm.createTask('proj-1', 'sess-1', 'sk-key');65    bus.emit(taskId, 'proj-1', 'conversation_message', {66      message: { role: 'user', content: 'hello', ui_metadata: { projectContext: 'files...' } },67    }, 'sess-1');68    bus.emit(taskId, 'proj-1', 'assistant_delta', { text: 'Hi' }, 'sess-1');69    bus.emit(taskId, 'proj-1', 'tool_status', { status: 'running', name: 'bash' }, 'sess-1');70    bus.emit(taskId, 'proj-1', 'conversation_message', {71      message: { role: 'assistant', content: 'Done' },72    }, 'sess-1');73 74    // Fresh tab: getBuffer returns all buffered (non-delta) events75    const buffer = bus.getBuffer(taskId);76    expect(buffer).toHaveLength(3); // user msg, tool_status, assistant msg (delta excluded)77 78    // replayFrom with 0 also returns full buffer79    const replayed = bus.replayFrom(taskId, 0);80    expect(replayed).toHaveLength(3);81    expect(replayed![0].event).toBe('conversation_message');82    expect((replayed![0].data as any).message.ui_metadata.projectContext).toBe('files...');83  });84 85  it('task metadata is available in getTasksForSession for shelf display', () => {86    const taskId = tm.createTask('proj-1', 'sess-1', 'sk-key');87    const task = tm.getTask(taskId)!;88    task.prompt = 'add a navbar';89    task.model = 'claude-3.5-sonnet';90    task.projectName = 'Portfolio';91 92    const tasks = tm.getTasksForSession('sess-1');93    expect(tasks).toHaveLength(1);94    expect(tasks[0].prompt).toBe('add a navbar');95    expect(tasks[0].model).toBe('claude-3.5-sonnet');96    expect(tasks[0].projectName).toBe('Portfolio');97  });98 99  it('ServerConfigManager tracks cost across multiple updates', () => {100    const config = new ServerConfigManager({101      provider: 'openai',102      model: 'gpt-4o',103      apiKey: 'sk-test',104      modelPricing: { 'gpt-4o': { prompt: 2.5, completion: 10 } },105    });106 107    config.updateSessionCost({ promptTokens: 1000, completionTokens: 500 }, 0.075);108    config.updateSessionCost({ promptTokens: 2000, completionTokens: 1000 }, 0.15);109 110    const session = config.getSessionCost();111    expect(session.totalCost).toBeCloseTo(0.225);112    expect(session.requestCount).toBe(2);113    expect(session.totalPromptTokens).toBe(3000);114    expect(session.totalCompletionTokens).toBe(1500);115  });116});117