39 lines
2.0 KiB
TypeScript
39 lines
2.0 KiB
TypeScript
// @vitest-environment node
|
|
import { describe, expect, it } from 'vitest';
|
|
import { previewTeacherReply } from '../../shared/teacher-reply';
|
|
|
|
describe('teacher streaming prose', () => {
|
|
it('decodes text before the envelope or string closes, withholding incomplete escapes', () => {
|
|
const reply = '先看 "代码"。\n路径 C:\\game\n🍎';
|
|
const raw = JSON.stringify({ reply, quickReplies: ['下一步'], tool: { reply: 'never-visible' } });
|
|
const previews = Array.from({ length: raw.length + 1 }, (_, i) => previewTeacherReply(raw.slice(0, i)));
|
|
for (const preview of previews) {
|
|
expect(reply.startsWith(preview)).toBe(true);
|
|
expect(preview).not.toContain('quickReplies');
|
|
}
|
|
expect(previews[raw.indexOf('代码') + 2]).toBe('先看 "代码');
|
|
expect(previews.at(-1)).toBe(reply);
|
|
expect(previewTeacherReply('{"reply":"你好\\u4')).toBe('你好');
|
|
expect(previewTeacherReply('{"reply":"你好\\u4e16')).toBe('你好世');
|
|
});
|
|
|
|
it.each(['```json\n', '```JSON\r\n', '~~~json\n', '```makelore-teacher-reply\n', '```\n'])(
|
|
'streams fenced replies without leaking the protocol (%s)', fence => {
|
|
const raw = fence + '{"quickReplies":[],"reply":"逐步回答';
|
|
for (let i = 0; i <= raw.length; i++) {
|
|
const preview = previewTeacherReply(raw.slice(0, i));
|
|
expect('逐步回答'.startsWith(preview)).toBe(true);
|
|
}
|
|
expect(previewTeacherReply(raw)).toBe('逐步回答');
|
|
},
|
|
);
|
|
|
|
it('accepts plain text and completed ordinary JSON while excluding nested retired payloads', () => {
|
|
expect(previewTeacherReply('## 标题\n\n逐步说明')).toBe('## 标题\n\n逐步说明');
|
|
expect(previewTeacherReply('{"count":1}')).toBe('{"count":1}');
|
|
expect(previewTeacherReply('{"tool":{"reply":"不要显示"},"reply":"正文')).toBe('正文');
|
|
expect(previewTeacherReply('{"intro":"旧版正文","questions":[')).toBe('旧版正文');
|
|
expect(previewTeacherReply('{"reply":"正文","quickReplies":["隐藏')).toBe('正文');
|
|
});
|
|
});
|