115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
getSessionRefreshIntervalMs,
|
|
getTaskCardMessageIndexes,
|
|
mergeServerWithPendingUsers,
|
|
shouldDisplayChatMessage,
|
|
shouldMergePendingUsers,
|
|
} from '@/lib/chat-messages';
|
|
import type { ChatMessage } from '@/types';
|
|
|
|
describe('chat message helpers', () => {
|
|
it('keeps pending local user messages after server refreshes', () => {
|
|
const serverMessages: ChatMessage[] = [
|
|
{
|
|
role: 'assistant',
|
|
content: 'Earlier answer',
|
|
timestamp: '2026-05-21T08:00:00.000Z',
|
|
},
|
|
];
|
|
const localMessages: ChatMessage[] = [
|
|
...serverMessages,
|
|
{
|
|
role: 'user',
|
|
content: 'Please continue',
|
|
timestamp: '2026-05-21T08:01:00.000Z',
|
|
},
|
|
];
|
|
|
|
expect(mergeServerWithPendingUsers(serverMessages, localMessages)).toEqual([
|
|
...serverMessages,
|
|
localMessages[1],
|
|
]);
|
|
});
|
|
|
|
it('does not duplicate local user messages already persisted by the server', () => {
|
|
const serverMessages: ChatMessage[] = [
|
|
{
|
|
role: 'user',
|
|
content: 'Please continue',
|
|
timestamp: '2026-05-21T08:01:00.000Z',
|
|
},
|
|
];
|
|
const localMessages: ChatMessage[] = [
|
|
{
|
|
role: 'user',
|
|
content: 'Please continue',
|
|
timestamp: '2026-05-21T08:01:01.000Z',
|
|
},
|
|
];
|
|
|
|
expect(mergeServerWithPendingUsers(serverMessages, localMessages)).toEqual(serverMessages);
|
|
});
|
|
|
|
it('merges pending user messages when local state has an unpersisted trailing user turn', () => {
|
|
const serverMessages: ChatMessage[] = [
|
|
{
|
|
role: 'assistant',
|
|
content: 'Earlier answer',
|
|
timestamp: '2026-05-21T08:00:00.000Z',
|
|
},
|
|
];
|
|
const localMessages: ChatMessage[] = [
|
|
...serverMessages,
|
|
{
|
|
role: 'user',
|
|
content: 'Do this long task',
|
|
timestamp: '2026-05-21T08:01:00.000Z',
|
|
},
|
|
];
|
|
|
|
expect(shouldMergePendingUsers(serverMessages, localMessages, false)).toBe(true);
|
|
});
|
|
|
|
it('shows a task card only on the latest assistant message for the same task', () => {
|
|
const messages: ChatMessage[] = [
|
|
{
|
|
role: 'assistant',
|
|
content: 'I will start.',
|
|
run_id: 'run-1',
|
|
task_id: 'task-1',
|
|
},
|
|
{
|
|
role: 'assistant',
|
|
content: 'I found data.',
|
|
run_id: 'run-1',
|
|
task_id: 'task-1',
|
|
},
|
|
{
|
|
role: 'assistant',
|
|
content: 'Final answer.',
|
|
run_id: 'run-1',
|
|
task_id: 'task-1',
|
|
task_status: 'awaiting_acceptance',
|
|
},
|
|
];
|
|
|
|
expect(Array.from(getTaskCardMessageIndexes(messages))).toEqual([2]);
|
|
});
|
|
|
|
it('hides empty assistant records from session history', () => {
|
|
expect(shouldDisplayChatMessage({ role: 'assistant', content: '', task_id: 'task-1', run_id: 'run-1' })).toBe(false);
|
|
expect(shouldDisplayChatMessage({ role: 'assistant', content: '\u200B\uFEFF', task_id: 'task-1', run_id: 'run-1' })).toBe(false);
|
|
expect(shouldDisplayChatMessage({ role: 'assistant', content: 'Final answer.', task_id: 'task-1', run_id: 'run-1' })).toBe(true);
|
|
expect(shouldDisplayChatMessage({ role: 'user', content: '' })).toBe(true);
|
|
});
|
|
|
|
it('keeps polling idle visible chats so external channel messages appear', () => {
|
|
expect(getSessionRefreshIntervalMs({ isLoading: true, isThinking: false, documentHidden: false })).toBe(1500);
|
|
expect(getSessionRefreshIntervalMs({ isLoading: false, isThinking: true, documentHidden: false })).toBe(1500);
|
|
expect(getSessionRefreshIntervalMs({ isLoading: false, isThinking: false, documentHidden: false })).toBe(5000);
|
|
expect(getSessionRefreshIntervalMs({ isLoading: false, isThinking: false, documentHidden: true })).toBeNull();
|
|
});
|
|
});
|