import { describe, expect, test } from 'bun:test'; import { applySessionEventWorkspace } from '@renderer/lib/sessionWorkspace'; import type { SessionEventRecord } from '@shared/domain/event'; import { createWorkspaceSettings } from '@shared/domain/tooling'; import type { WorkspaceState } from '@shared/domain/workspace'; describe('session workspace helpers', () => { function createWorkspace(): WorkspaceState { return { projects: [], patterns: [], settings: createWorkspaceSettings(), sessions: [ { id: 'session-1', projectId: 'project-1', patternId: 'pattern-1', title: 'Session', createdAt: '2026-03-23T00:00:00.000Z', updatedAt: '2026-03-23T00:00:00.000Z', status: 'idle', messages: [], }, ], selectedSessionId: 'session-1', lastUpdatedAt: '2026-03-23T00:00:00.000Z', }; } test('applies message deltas by creating and appending assistant messages', () => { const created = applySessionEventWorkspace(createWorkspace(), { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:01.000Z', messageId: 'assistant-1', authorName: 'Architect', contentDelta: 'Hello', content: 'Hello', } satisfies SessionEventRecord); expect(created?.sessions[0].messages).toEqual([ { id: 'assistant-1', role: 'assistant', authorName: 'Architect', content: 'Hello', createdAt: '2026-03-23T00:00:01.000Z', pending: true, }, ]); const appended = applySessionEventWorkspace(created, { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:02.000Z', messageId: 'assistant-1', authorName: 'Architect', contentDelta: ' world', content: 'Hello world', } satisfies SessionEventRecord); expect(appended?.sessions[0].messages[0]).toMatchObject({ authorName: 'Architect', content: 'Hello world', pending: true, }); }); test('marks streamed messages complete when the session event arrives', () => { const workspace = applySessionEventWorkspace(createWorkspace(), { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:01.000Z', messageId: 'assistant-1', authorName: 'Implementer', contentDelta: 'Done', content: 'Done', } satisfies SessionEventRecord); const completed = applySessionEventWorkspace(workspace, { sessionId: 'session-1', kind: 'message-complete', occurredAt: '2026-03-23T00:00:02.000Z', messageId: 'assistant-1', authorName: 'Implementer', content: 'Done', } satisfies SessionEventRecord); expect(completed?.sessions[0].messages[0]).toMatchObject({ authorName: 'Implementer', content: 'Done', pending: false, }); }); test('keeps snapshot-like streamed updates readable while a message is pending', () => { const first = applySessionEventWorkspace(createWorkspace(), { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:01.000Z', messageId: 'assistant-1', authorName: 'Writer', contentDelta: 'How about', content: 'How about', } satisfies SessionEventRecord); const second = applySessionEventWorkspace(first, { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:02.000Z', messageId: 'assistant-1', authorName: 'Writer', contentDelta: 'The **Ashen Crown** feels', content: 'How about The **Ashen Crown** feels', } satisfies SessionEventRecord); const third = applySessionEventWorkspace(second, { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:03.000Z', messageId: 'assistant-1', authorName: 'Writer', contentDelta: 'classic and timeless.', content: 'How about The **Ashen Crown** feels classic and timeless.', } satisfies SessionEventRecord); expect(third?.sessions[0].messages[0]).toMatchObject({ authorName: 'Writer', content: 'How about The **Ashen Crown** feels classic and timeless.', pending: true, }); }); test('applies final content from completion events without waiting for a workspace refresh', () => { const workspace = applySessionEventWorkspace(createWorkspace(), { sessionId: 'session-1', kind: 'message-delta', occurredAt: '2026-03-23T00:00:01.000Z', messageId: 'assistant-1', authorName: 'Reviewer', contentDelta: 'Draft', content: 'Draft', } satisfies SessionEventRecord); const completed = applySessionEventWorkspace(workspace, { sessionId: 'session-1', kind: 'message-complete', occurredAt: '2026-03-23T00:00:02.000Z', messageId: 'assistant-1', authorName: 'Reviewer', content: 'Draft polished into the final review.', } satisfies SessionEventRecord); expect(completed?.sessions[0].messages[0]).toMatchObject({ authorName: 'Reviewer', content: 'Draft polished into the final review.', pending: false, }); }); test('updates session status and error state from session events', () => { const running = applySessionEventWorkspace(createWorkspace(), { sessionId: 'session-1', kind: 'status', occurredAt: '2026-03-23T00:00:01.000Z', status: 'running', } satisfies SessionEventRecord); expect(running?.sessions[0]).toMatchObject({ status: 'running', lastError: undefined, }); const failed = applySessionEventWorkspace(running, { sessionId: 'session-1', kind: 'error', occurredAt: '2026-03-23T00:00:02.000Z', error: 'Boom', } satisfies SessionEventRecord); expect(failed?.sessions[0]).toMatchObject({ status: 'error', lastError: 'Boom', }); }); test('ignores events for unknown sessions', () => { const workspace = createWorkspace(); expect( applySessionEventWorkspace(workspace, { sessionId: 'missing', kind: 'message-delta', occurredAt: '2026-03-23T00:00:01.000Z', messageId: 'assistant-1', authorName: 'Architect', contentDelta: 'Hello', } satisfies SessionEventRecord), ).toBe(workspace); }); });