chatContextInjection.test.js 2.33 KB
/**
 * 回归测试:graph-console 底部聊天条的上下文注入不变式——
 * context 变了才拼上下文行,没变就原样发,不能每条消息都刷一遍。
 */
import { describe, it, expect } from 'vitest';
import { contextKey, buildOutgoingMessage } from './chatContextInjection.js';

const ctxA = { taskId: 'T-1', taskTitle: '任务A', taskStatus: 'running', goalId: 'G-1', goalTitle: '目标A' };
const ctxB = { taskId: 'T-2', taskTitle: '任务B', taskStatus: 'pending', goalId: 'G-2', goalTitle: '目标B' };

describe('chatContextInjection · buildOutgoingMessage', () => {
  it('首次发送(lastSentKey 为空)带上下文时要拼上下文行', () => {
    const { payload, nextKey } = buildOutgoingMessage('你好', ctxA, '');
    expect(payload).toContain('T-1');
    expect(payload).toContain('任务A');
    expect(payload.endsWith('你好')).toBe(true);
    expect(nextKey).toBe(contextKey(ctxA));
  });

  it('context 跟上次相同时不重复拼上下文行,原样发送用户文本', () => {
    const first = buildOutgoingMessage('第一条', ctxA, '');
    const second = buildOutgoingMessage('第二条', ctxA, first.nextKey);
    expect(second.payload).toBe('第二条');
    expect(second.nextKey).toBe(first.nextKey);
  });

  it('context 换了(task 或 goal 变化)要重新拼一次', () => {
    const first = buildOutgoingMessage('第一条', ctxA, '');
    const second = buildOutgoingMessage('切到另一个任务了', ctxB, first.nextKey);
    expect(second.payload).toContain('T-2');
    expect(second.payload).toContain('任务B');
    expect(second.nextKey).toBe(contextKey(ctxB));
    expect(second.nextKey).not.toBe(first.nextKey);
  });

  it('没有 context(没选中任务)时原样发送,不拼任何说明', () => {
    const { payload, nextKey } = buildOutgoingMessage('随便聊聊', null, 'stale-key');
    expect(payload).toBe('随便聊聊');
    expect(nextKey).toBe('stale-key'); // 透传,不产生新 key
  });
});

describe('chatContextInjection · contextKey', () => {
  it('null context 的 key 是空字符串', () => {
    expect(contextKey(null)).toBe('');
  });

  it('taskId/goalId 相同则 key 相同,跟 title/status 无关', () => {
    const same = { ...ctxA, taskTitle: '改了标题', taskStatus: 'completed' };
    expect(contextKey(same)).toBe(contextKey(ctxA));
  });
});