@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
435 lines (322 loc) • 18.6 kB
text/typescript
import { describe, expect, it } from 'vitest';
import { processWithArtifact } from './utils';
describe('processWithArtifact', () => {
it('should removeLineBreaks with closed tag', () => {
const input = `好的
<lobeArtifact identifier="sleep-interpretation-card" type="image/svg+xml" title="睡觉的新解释">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600">
<defs>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap');
</style>
</defs>
<!-- 背景 -->
<rect width="400" height="600" fill="#F0EAD6"/>
<!-- 总结 -->
<text x="200" y="500" font-family="'Noto Serif SC', serif" font-size="20" text-anchor="middle" fill="#8B4513">睡觉:生产力的假死,创造力的重生。</text>
</svg>
</lobeArtifact>`;
const output = processWithArtifact(input);
expect(output).toEqual(`好的
<lobeArtifact identifier="sleep-interpretation-card" type="image/svg+xml" title="睡觉的新解释"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600"><defs><style>@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap');</style></defs><!-- 背景 --><rect width="400" height="600" fill="#F0EAD6"/><!-- 总结 --><text x="200" y="500" font-family="'Noto Serif SC', serif" font-size="20" text-anchor="middle" fill="#8B4513">睡觉:生产力的假死,创造力的重生。</text></svg></lobeArtifact>`);
});
it('should removeLineBreaks with open tag', () => {
const input = `好的
<lobeArtifact identifier="ai-interpretation-card" type="image/svg+xml" title="人工智能新解卡片">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600">
<defs>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap');
</style>
</defs>
`;
const output = processWithArtifact(input);
expect(output).toEqual(`好的
<lobeArtifact identifier="ai-interpretation-card" type="image/svg+xml" title="人工智能新解卡片"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600"> <defs> <style> @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap'); </style> </defs>`);
});
it('should not throw error with empty', () => {
const input = '';
const output = processWithArtifact(input);
expect(output).toEqual('');
});
describe('close the <lobeArtifact tag', () => {
it('close tag for <lobeArtifact', () => {
const input = '<lobeArtifact';
const output = processWithArtifact(input);
expect(output).toEqual('<lobeArtifact>');
});
it('close tag for <lobeArtifact identifier="something"', () => {
const input = '<lobeArtifact identifier="something"';
const output = processWithArtifact(input);
expect(output).toEqual('<lobeArtifact>');
});
it('close tag for <lobeArtifact identifier="ai-interpretation" type="image/svg+xml" titl', () => {
const input = '<lobeArtifact identifier="ai-interpretation" type="image/svg+xml" titl';
const output = processWithArtifact(input);
expect(output).toEqual('<lobeArtifact>');
});
it('only change the <lobeArtifact> part', () => {
const input = `好的,让我来用新的视角解释"人工智能"这个词汇。
<lobeThinking>这个词汇涉及了当代科技和社会热点,需要用批判性和幽默感来解读其本质。我会用隐喻和讽刺来表达,同时保持简洁有力。</lobeThinking>
<lobeArtifact identifier="ai-new-interpretation" type="image/svg+xml" t`;
const output = processWithArtifact(input);
expect(output).toEqual(`好的,让我来用新的视角解释"人工智能"这个词汇。
<lobeThinking>这个词汇涉及了当代科技和社会热点,需要用批判性和幽默感来解读其本质。我会用隐喻和讽刺来表达,同时保持简洁有力。</lobeThinking>
<lobeArtifact>`);
});
it('not change for <lobeArtifact />', () => {
const input = '<lobeArtifact/>';
const output = processWithArtifact(input);
expect(output).toEqual(input);
});
});
it('should removeLinkBreaks for lobeThinking', () => {
const input = `好的,让我以一个特别的视角来解释"人工智能"这个词汇。
<lobeThinking>
这个词汇涉及了当代科技和社会热点,需要用批判性、幽默而深刻的视角来解读。我会运用隐喻和讽刺,抓住其本质,并以精练的方式表达出来。这符合一个好的artifact的标准,因为它是一个独立的、可能被用户修改或重用的内容。我将创建一个新的SVG artifact来呈现这个解释。
</lobeThinking>
<lobeArtifact identifier="ai-new-interpretation" type="image/svg+xml" title="人工智能的新解释">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600">
<defs>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap');
.background { fill: #f0f0f0; }
.title { font-family: 'Noto Serif SC', serif; font-size: 28px; font-weight: 700; fill: #333; }
.content { font-family: 'Noto Serif SC', serif; font-size: 18px; fill: #555; }
.divider { stroke: #999; stroke-width: 1; }
.decoration { fill: none; stroke: #999; stroke-width: 1; }
</style>
</defs>
</svg>
</lobeArtifact>
我为"人工智能"这个词创建了一个新的解释,并将其呈现在一个SVG卡片中。这个解释采用了批判性和幽默的视角,试图揭示这个概念背后的一些潜在问题。`;
const output = processWithArtifact(input);
expect(output).toEqual(`好的,让我以一个特别的视角来解释"人工智能"这个词汇。
<lobeThinking>这个词汇涉及了当代科技和社会热点,需要用批判性、幽默而深刻的视角来解读。我会运用隐喻和讽刺,抓住其本质,并以精练的方式表达出来。这符合一个好的artifact的标准,因为它是一个独立的、可能被用户修改或重用的内容。我将创建一个新的SVG artifact来呈现这个解释。</lobeThinking>
<lobeArtifact identifier="ai-new-interpretation" type="image/svg+xml" title="人工智能的新解释"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 600"> <defs> <style> @import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap'); .background { fill: #f0f0f0; } .title { font-family: 'Noto Serif SC', serif; font-size: 28px; font-weight: 700; fill: #333; } .content { font-family: 'Noto Serif SC', serif; font-size: 18px; fill: #555; } .divider { stroke: #999; stroke-width: 1; } .decoration { fill: none; stroke: #999; stroke-width: 1; } </style> </defs></svg></lobeArtifact>
我为"人工智能"这个词创建了一个新的解释,并将其呈现在一个SVG卡片中。这个解释采用了批判性和幽默的视角,试图揭示这个概念背后的一些潜在问题。`);
});
it('should removeLinkBreaks for lobeThinking', () => {
const input = `<lobeThinking>
这个词汇涉及了
`;
const output = processWithArtifact(input);
expect(output).toEqual(`<lobeThinking>这个词汇涉及了`);
});
it('should handle no empty line between lobeThinking and lobeArtifact', () => {
const input = `<lobeThinking>这是一个思考过程。</lobeThinking>
<lobeArtifact identifier="test" type="image/svg+xml" title="测试">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect width="100" height="100" fill="blue"/>
</svg>
</lobeArtifact>`;
const output = processWithArtifact(input);
expect(output).toEqual(`<lobeThinking>这是一个思考过程。</lobeThinking>
<lobeArtifact identifier="test" type="image/svg+xml" title="测试"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> <rect width="100" height="100" fill="blue"/></svg></lobeArtifact>`);
});
it('should remove fenced code block between lobeArtifact and HTML content', () => {
const input = `<lobeArtifact identifier="web-calculator" type="text/html" title="简单的 Web 计算器">
\`\`\`html
<html lang="zh">
<head>
<title>计算器</title>
</head>
<body>
<div>计算器</div>
</body>
</html>
\`\`\`
</lobeArtifact>`;
const output = processWithArtifact(input);
expect(output).toEqual(
`<lobeArtifact identifier="web-calculator" type="text/html" title="简单的 Web 计算器"><html lang="zh"><head> <title>计算器</title></head><body> <div>计算器</div></body></html></lobeArtifact>`,
);
});
it('should remove fenced code block between lobeArtifact and HTML content without doctype', () => {
const input = `<lobeArtifact identifier="web-calculator" type="text/html" title="简单的 Web 计算器">
\`\`\`html
<html lang="zh">
<head>
<title>计算器</title>
</head>
<body>
<div>计算器</div>
</body>
</html>
\`\`\`
</lobeArtifact>`;
const output = processWithArtifact(input);
expect(output).toEqual(
`<lobeArtifact identifier="web-calculator" type="text/html" title="简单的 Web 计算器"><html lang="zh"><head> <title>计算器</title></head><body> <div>计算器</div></body></html></lobeArtifact>`,
);
});
it('should remove outer fenced code block wrapping lobeThinking and lobeArtifact', () => {
const input =
'```tool_code\n<lobeThinking>这是一个思考过程。</lobeThinking>\n\n<lobeArtifact identifier="test" type="text/html" title="测试">\n<div>测试内容</div>\n</lobeArtifact>\n```';
const output = processWithArtifact(input);
expect(output).toEqual(
'<lobeThinking>这是一个思考过程。</lobeThinking>\n\n<lobeArtifact identifier="test" type="text/html" title="测试"><div>测试内容</div></lobeArtifact>',
);
});
it('should handle both outer code block and inner HTML code block', () => {
const input =
'```tool_code\n<lobeThinking>这是一个思考过程。</lobeThinking>\n\n<lobeArtifact identifier="test" type="text/html" title="测试">\n```html\n \n<html>\n<body>\n<div>测试内容</div>\n</body>\n</html>\n```\n</lobeArtifact>\n```';
const output = processWithArtifact(input);
expect(output).toEqual(
'<lobeThinking>这是一个思考过程。</lobeThinking>\n\n<lobeArtifact identifier="test" type="text/html" title="测试"><html><body><div>测试内容</div></body></html></lobeArtifact>',
);
});
it('should handle complete conversation with text and tags', () => {
const input = `Sure, I can help you with that! Here is a basic calculator built using HTML, CSS, and JavaScript.
<lobeThinking>A web calculator is a substantial piece of code and a good candidate for an artifact. It's self-contained, and it's likely that the user will want to modify it. This is a new request, so I will create a new artifact.</lobeThinking>
<lobeArtifact identifier="web-calculator" type="text/html" title="Web Calculator">
\`\`\`html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Calculator</title>
</head>
<body>
<div>Calculator</div>
</body>
</html>
\`\`\`
</lobeArtifact>
This code provides a basic calculator that can perform addition, subtraction, multiplication, and division.`;
const output = processWithArtifact(input);
expect(output)
.toEqual(`Sure, I can help you with that! Here is a basic calculator built using HTML, CSS, and JavaScript.
<lobeThinking>A web calculator is a substantial piece of code and a good candidate for an artifact. It's self-contained, and it's likely that the user will want to modify it. This is a new request, so I will create a new artifact.</lobeThinking>
<lobeArtifact identifier="web-calculator" type="text/html" title="Web Calculator"><html lang="en"><head> <meta charset="UTF-8"> <title>Simple Calculator</title></head><body> <div>Calculator</div></body></html></lobeArtifact>
This code provides a basic calculator that can perform addition, subtraction, multiplication, and division.`);
});
});
describe('outer code block removal', () => {
it('should remove outer html code block', () => {
const input = `\`\`\`html
<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test">
<html>
<body>Test</body>
</html>
</lobeArtifact>
\`\`\``;
const output = processWithArtifact(input);
expect(output).toEqual(`<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test"><html><body>Test</body></html></lobeArtifact>`);
});
it('should remove outer tool_code code block', () => {
const input = `\`\`\`tool_code
<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test">
<html>
<body>Test</body>
</html>
</lobeArtifact>
\`\`\``;
const output = processWithArtifact(input);
expect(output).toEqual(`<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test"><html><body>Test</body></html></lobeArtifact>`);
});
it('should handle input without outer code block', () => {
const input = `<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test">
<html>
<body>Test</body>
</html>
</lobeArtifact>`;
const output = processWithArtifact(input);
expect(output).toEqual(`<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test"><html><body>Test</body></html></lobeArtifact>`);
});
it('should handle code block with content before and after', () => {
const input = `Some text before
\`\`\`html
<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test">
<html>
<body>Test</body>
</html>
</lobeArtifact>
\`\`\`
Some text after`;
const output = processWithArtifact(input);
expect(output).toEqual(`Some text before
<lobeThinking>Test thinking</lobeThinking>
<lobeArtifact identifier="test" type="text/html" title="Test"><html><body>Test</body></html></lobeArtifact>
Some text after`);
});
it('should handle code block with only lobeArtifact tag', () => {
const input = `\`\`\`html
<lobeArtifact identifier="test" type="text/html" title="Test">
<html>
<body>Test</body>
</html>
</lobeArtifact>
\`\`\``;
const output = processWithArtifact(input);
expect(output).toEqual(
`<lobeArtifact identifier="test" type="text/html" title="Test"><html><body>Test</body></html></lobeArtifact>`,
);
});
it('should handle code block with surrounding text and both lobeThinking and lobeArtifact', () => {
const input = `---
\`\`\`tool_code
<lobeThinking>The user reported a \`SyntaxError\` in the browser console, indicating a problem with the JavaScript code in the calculator artifact. The error message "Identifier 'display' has already been declared" suggests a variable naming conflict. I need to review the JavaScript code and correct the issue. This is an update to the existing "calculator-web-artifact" artifact.</lobeThinking>
<lobeArtifact identifier="calculator-web-artifact" type="text/html" title="Simple Calculator">
<html lang="en">
...
</html>
</lobeArtifact>
\`\`\`
I've updated the calculator artifact. The issue was a naming conflict with the \`display\` variable. I've renamed the input element's ID to \`calc-display\` and the JavaScript variable to \`displayElement\` to avoid the conflict. The calculator should now function correctly.
---`;
const output = processWithArtifact(input);
expect(output).toEqual(`---
<lobeThinking>The user reported a \`SyntaxError\` in the browser console, indicating a problem with the JavaScript code in the calculator artifact. The error message "Identifier 'display' has already been declared" suggests a variable naming conflict. I need to review the JavaScript code and correct the issue. This is an update to the existing "calculator-web-artifact" artifact.</lobeThinking>
<lobeArtifact identifier="calculator-web-artifact" type="text/html" title="Simple Calculator"><html lang="en">...</html></lobeArtifact>
I've updated the calculator artifact. The issue was a naming conflict with the \`display\` variable. I've renamed the input element's ID to \`calc-display\` and the JavaScript variable to \`displayElement\` to avoid the conflict. The calculator should now function correctly.
---`);
});
it('should handle code block before lobeThinking and lobeArtifact', () => {
const input = `
Okay, I'll create a temperature converter with the logic wrapped in an IIFE and event listeners attached in Javascript.
\`\`\`html
<html lang="en">
...
</html>
\`\`\`
<lobeThinking>This is a good candidate for an artifact. It's a self-contained HTML document with embedded JavaScript that provides a functional temperature converter. It's more than a simple code snippet and can be reused or modified. This is a new request, so I'll create a new artifact with the identifier "temperature-converter".</lobeThinking>
<lobeArtifact identifier="temperature-converter" type="text/html" title="Temperature Converter">
\`\`\`html
<html lang="en">
...
</html>
\`\`\`
</lobeArtifact>
This HTML document includes the temperature converter with the requested features: the logic is wrapped in an IIFE, and event listeners are attached in JavaScript.
`;
const output = processWithArtifact(input);
expect(output)
.toEqual(`Okay, I'll create a temperature converter with the logic wrapped in an IIFE and event listeners attached in Javascript.
\`\`\`html
<html lang="en">
...
</html>
\`\`\`
<lobeThinking>This is a good candidate for an artifact. It's a self-contained HTML document with embedded JavaScript that provides a functional temperature converter. It's more than a simple code snippet and can be reused or modified. This is a new request, so I'll create a new artifact with the identifier "temperature-converter".</lobeThinking>
<lobeArtifact identifier="temperature-converter" type="text/html" title="Temperature Converter"><html lang="en">...</html></lobeArtifact>
This HTML document includes the temperature converter with the requested features: the logic is wrapped in an IIFE, and event listeners are attached in JavaScript.`);
});
});