cc-haha/desktop/src/components/chat/composerUtils.test.ts
程序员阿江(Relakkes) 635a966c3e fix(desktop): unblock rollout with reliable session and IM flows
This folds together the desktop-side fixes needed before broader rollout.
Session resume no longer deadlocks waiting on init, Mermaid and inline image
output render inside chat, task and sub-agent state stay visible during
execution, local build/release paths are safer, and Feishu/Telegram now expose
lightweight mobile commands (/help, /status, /clear) without adding a new
adapter-specific protocol.

Constraint: Desktop releases must publish updater artifacts from non-draft GitHub releases
Constraint: IM commands need short, phone-friendly responses and low operational complexity
Rejected: Add a dedicated IM command API surface | re-used existing slash commands and session/task REST endpoints to keep adapters thin
Rejected: Wait for task_update push events in WebUI | added low-risk polling because the current frontend ignores that event path
Confidence: medium
Scope-risk: broad
Reversibility: clean
Directive: Keep IM command replies terse and mobile-first, and merge local fallback slash commands when server-provided lists are partial
Tested: cd desktop && bun x vitest run src/components/chat/MermaidRenderer.test.tsx src/components/markdown/MarkdownRenderer.test.tsx
Tested: cd desktop && bun x vitest run src/components/chat/composerUtils.test.ts src/pages/ActiveSession.test.tsx src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "SDK init arrives only after the first user turn" --timeout 60000
Tested: cd adapters && bun test common/ feishu/ telegram/
Tested: cd adapters && bunx tsc --noEmit
Not-tested: Full GitHub Actions release run on all three desktop platforms
Not-tested: Local DMG packaging end-to-end on Apple Silicon
Not-tested: Real Feishu/Telegram device sessions against a live adapter process
2026-04-10 16:41:59 +08:00

56 lines
1.7 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
findSlashToken,
insertSlashTrigger,
mergeSlashCommands,
replaceSlashCommand,
} from './composerUtils'
describe('composerUtils', () => {
it('finds slash token without trailing space', () => {
expect(findSlashToken('/rev', 4)).toEqual({ start: 0, filter: 'rev' })
expect(findSlashToken('hello /rev', 10)).toEqual({ start: 6, filter: 'rev' })
})
it('does not treat slash followed by a space as an active token', () => {
expect(findSlashToken('/ review', 8)).toBeNull()
})
it('inserts a slash trigger without appending a trailing space', () => {
expect(insertSlashTrigger('', 0)).toEqual({ value: '/', cursorPos: 1 })
expect(insertSlashTrigger('hello', 5)).toEqual({ value: 'hello /', cursorPos: 7 })
})
it('replaces the current slash token with a command and one trailing separator', () => {
expect(replaceSlashCommand('/rev', 4, 'review')).toEqual({
value: '/review ',
cursorPos: 8,
})
})
it('merges fallback commands so built-in entries like /clear remain visible', () => {
expect(
mergeSlashCommands([
{ name: 'help', description: '' },
]),
).toEqual(
expect.arrayContaining([
{ name: 'help', description: 'Show available commands' },
{ name: 'clear', description: 'Clear conversation history' },
]),
)
})
it('keeps server-provided descriptions when they exist', () => {
expect(
mergeSlashCommands([
{ name: 'clear', description: 'Server description' },
]),
).toEqual(
expect.arrayContaining([
{ name: 'clear', description: 'Server description' },
]),
)
})
})