import { describe, expect, it } from 'vitest'; import { firstMessageTitle } from '../../electron/coding-runtime/conversation-title'; import type { ConversationMessageNode } from '../../shared/coding-conversation-contracts'; function message(text: string, overrides: Partial = {}): ConversationMessageNode { return { kind: 'message', id: 'user', role: 'user', status: 'complete', blocks: [{ kind: 'text', id: 'text', status: 'complete', text }], ...overrides }; } describe('first user message title', () => { it('uses the first line, collapses whitespace, and bounds long text by characters', () => { expect(firstMessageTitle(message(' 做一个 登录页\n支持短信登录'))).toBe('做一个 登录页'); expect(firstMessageTitle(message('🦊'.repeat(40)))).toBe('🦊'.repeat(32)); }); it('ignores optimistic, assistant, command and empty content', () => { expect(firstMessageTitle(message('draft', { status: 'optimistic' }))).toBeNull(); expect(firstMessageTitle(message('reply', { role: 'assistant' }))).toBeNull(); expect(firstMessageTitle(message('/compact'))).toBeNull(); expect(firstMessageTitle(message(' '))).toBeNull(); }); it('names image-only conversations without inspecting the attachment', () => { expect(firstMessageTitle(message('', { blocks: [{ kind: 'image', id: 'img', attachmentId: 'attachment', mime: 'image/png' }] }))).toBe('附件对话'); }); });