mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
## CHANGES
- Upgraded group chat exports to true GitHub-flavored Markdown rendering! 🚀 - Added `marked` dependency and configured GFM plus line-break handling! ✨ - Exported messages now support tables, blockquotes, rules, and strikethrough! 🔥 - Code formatting improved: inline code and fenced blocks render correctly! 🧠 - Image embedding revamped: replaces references with base64 before parsing! 🖼️ - New branded export header with Maestro icon, tagline, and links! 🎉 - Export title now reads “Maestro Group Chat Export” for clarity! 🏷️ - Footer attribution updated to <a href="https://runmaestro.ai" target="_blank">runmaestro.ai</a> for consistency! 🌐 - Markdown styling massively enhanced: headings, lists, tables, and code look great! 🎨 - AutoRunLightbox tests updated for portal backdrop and higher z-index! ✅
This commit is contained in:
23
package-lock.json
generated
23
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "maestro",
|
||||
"version": "0.10.0",
|
||||
"version": "0.10.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "maestro",
|
||||
"version": "0.10.0",
|
||||
"version": "0.10.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL 3.0",
|
||||
"dependencies": {
|
||||
@@ -31,6 +31,7 @@
|
||||
"electron-updater": "^6.6.2",
|
||||
"fastify": "^4.25.2",
|
||||
"js-tiktoken": "^1.0.21",
|
||||
"marked": "^17.0.1",
|
||||
"mermaid": "^11.12.1",
|
||||
"node-pty": "^1.0.0",
|
||||
"qrcode": "^1.5.4",
|
||||
@@ -10151,9 +10152,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
|
||||
"integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
|
||||
"version": "17.0.1",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-17.0.1.tgz",
|
||||
"integrity": "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
@@ -10543,6 +10544,18 @@
|
||||
"uuid": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid/node_modules/marked": {
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
|
||||
"integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/micromark": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
|
||||
|
||||
16
package.json
16
package.json
@@ -121,15 +121,24 @@
|
||||
"target": [
|
||||
{
|
||||
"target": "AppImage",
|
||||
"arch": ["x64", "arm64"]
|
||||
"arch": [
|
||||
"x64",
|
||||
"arm64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "deb",
|
||||
"arch": ["x64", "arm64"]
|
||||
"arch": [
|
||||
"x64",
|
||||
"arm64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "rpm",
|
||||
"arch": ["x64", "arm64"]
|
||||
"arch": [
|
||||
"x64",
|
||||
"arm64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"category": "Development",
|
||||
@@ -198,6 +207,7 @@
|
||||
"electron-updater": "^6.6.2",
|
||||
"fastify": "^4.25.2",
|
||||
"js-tiktoken": "^1.0.21",
|
||||
"marked": "^17.0.1",
|
||||
"mermaid": "^11.12.1",
|
||||
"node-pty": "^1.0.0",
|
||||
"qrcode": "^1.5.4",
|
||||
|
||||
@@ -147,8 +147,8 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
// Should render the backdrop container
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
// Should render the backdrop container (rendered via portal to document.body)
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
expect(backdrop).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -341,7 +341,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onNavigate });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'ArrowRight' });
|
||||
|
||||
expect(onNavigate).toHaveBeenCalledWith('image2.png');
|
||||
@@ -355,7 +355,7 @@ describe('AutoRunLightbox', () => {
|
||||
});
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'ArrowLeft' });
|
||||
|
||||
expect(onNavigate).toHaveBeenCalledWith('image1.png');
|
||||
@@ -365,7 +365,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
const event = fireEvent.keyDown(backdrop!, { key: 'ArrowRight' });
|
||||
|
||||
// fireEvent.keyDown returns false when preventDefault is called
|
||||
@@ -376,7 +376,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
const event = fireEvent.keyDown(backdrop!, { key: 'ArrowLeft' });
|
||||
|
||||
expect(event).toBe(false);
|
||||
@@ -390,7 +390,7 @@ describe('AutoRunLightbox', () => {
|
||||
});
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'ArrowRight' });
|
||||
|
||||
expect(onNavigate).not.toHaveBeenCalled();
|
||||
@@ -406,7 +406,7 @@ describe('AutoRunLightbox', () => {
|
||||
});
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'ArrowRight' });
|
||||
|
||||
expect(onNavigate).not.toHaveBeenCalled();
|
||||
@@ -450,7 +450,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onDelete });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'Delete' });
|
||||
|
||||
// Confirm modal should appear
|
||||
@@ -469,7 +469,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onDelete });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'Backspace' });
|
||||
|
||||
// Confirm modal should appear
|
||||
@@ -486,7 +486,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
const event = fireEvent.keyDown(backdrop!, { key: 'Delete' });
|
||||
|
||||
expect(event).toBe(false);
|
||||
@@ -500,7 +500,7 @@ describe('AutoRunLightbox', () => {
|
||||
});
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.keyDown(backdrop!, { key: 'Delete' });
|
||||
|
||||
expect(onDelete).not.toHaveBeenCalled();
|
||||
@@ -510,7 +510,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onDelete: undefined });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
// This should not throw or cause issues
|
||||
fireEvent.keyDown(backdrop!, { key: 'Delete' });
|
||||
// No assertion needed - just verifying it doesn't throw
|
||||
@@ -750,7 +750,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onClose });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
fireEvent.click(backdrop!);
|
||||
|
||||
expect(onClose).toHaveBeenCalled();
|
||||
@@ -871,7 +871,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
expect(backdrop).toHaveAttribute('tabIndex', '-1');
|
||||
// The ref={(el) => el?.focus()} should focus the element
|
||||
expect(document.activeElement).toBe(backdrop);
|
||||
@@ -951,7 +951,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
expect(backdrop).toHaveClass('bg-black/90');
|
||||
});
|
||||
|
||||
@@ -959,7 +959,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
expect(backdrop).toHaveClass('flex');
|
||||
expect(backdrop).toHaveClass('items-center');
|
||||
expect(backdrop).toHaveClass('justify-center');
|
||||
@@ -1034,7 +1034,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps({ onNavigate });
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
|
||||
// Rapid arrow key presses
|
||||
for (let i = 0; i < 10; i++) {
|
||||
@@ -1101,7 +1101,7 @@ describe('AutoRunLightbox', () => {
|
||||
const props = createDefaultProps();
|
||||
renderWithProviders(<AutoRunLightbox {...props} />);
|
||||
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-50');
|
||||
const backdrop = document.querySelector('.fixed.inset-0.z-\\[9999\\]');
|
||||
expect(backdrop).toHaveAttribute('tabIndex', '-1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -124,7 +124,7 @@ describe('groupChatExport', () => {
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('<title>My Custom Chat - Group Chat Export</title>');
|
||||
expect(html).toContain('<title>My Custom Chat - Maestro Group Chat Export</title>');
|
||||
});
|
||||
|
||||
it('includes group chat name in header', () => {
|
||||
@@ -149,6 +149,49 @@ describe('groupChatExport', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('branding', () => {
|
||||
it('includes Maestro branding section', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('class="branding"');
|
||||
expect(html).toContain('Maestro');
|
||||
expect(html).toContain('Multi-agent orchestration');
|
||||
});
|
||||
|
||||
it('includes runmaestro.ai link', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('href="https://runmaestro.ai"');
|
||||
expect(html).toContain('runmaestro.ai');
|
||||
});
|
||||
|
||||
it('includes GitHub link', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('href="https://github.com/pedramamini/Maestro"');
|
||||
expect(html).toContain('GitHub');
|
||||
});
|
||||
|
||||
it('includes Maestro logo SVG', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('class="branding-logo"');
|
||||
expect(html).toContain('<svg');
|
||||
});
|
||||
});
|
||||
|
||||
describe('theme colors', () => {
|
||||
it('uses theme colors in CSS variables', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
@@ -310,27 +353,29 @@ describe('groupChatExport', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('content escaping and formatting', () => {
|
||||
it('escapes HTML special characters in message content', () => {
|
||||
describe('markdown rendering with marked library', () => {
|
||||
it('renders tables correctly', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'user', content: '<div>test</div>' },
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '| A | B |\n|---|---|\n| 1 | 2 |' },
|
||||
];
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
// The message content should be escaped in the rendered HTML
|
||||
expect(html).toContain('<div>test</div>');
|
||||
expect(html).toContain('<table>');
|
||||
expect(html).toContain('<th>');
|
||||
expect(html).toContain('<td>');
|
||||
});
|
||||
|
||||
it('escapes HTML in group chat name in title', () => {
|
||||
const groupChat = createMockGroupChat({ name: '<b>Bold Name</b>' });
|
||||
const messages = createMockMessages();
|
||||
it('renders horizontal rules correctly', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: 'Before\n\n---\n\nAfter' },
|
||||
];
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
// The title should have escaped HTML
|
||||
expect(html).toContain('<title><b>Bold Name</b> - Group Chat Export</title>');
|
||||
expect(html).toContain('<hr');
|
||||
});
|
||||
|
||||
it('converts inline code to HTML code tags', () => {
|
||||
@@ -341,8 +386,7 @@ describe('groupChatExport', () => {
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('inline-code');
|
||||
expect(html).toContain('npm install');
|
||||
expect(html).toContain('<code>npm install</code>');
|
||||
});
|
||||
|
||||
it('converts code blocks to pre tags', () => {
|
||||
@@ -357,7 +401,7 @@ describe('groupChatExport', () => {
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('code-block');
|
||||
expect(html).toContain('<pre>');
|
||||
expect(html).toContain('const x = 1;');
|
||||
});
|
||||
|
||||
@@ -386,14 +430,17 @@ describe('groupChatExport', () => {
|
||||
it('converts markdown headers', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '# Heading 1\n## Heading 2\n### Heading 3' },
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '# Heading 1\n\n## Heading 2\n\n### Heading 3' },
|
||||
];
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('<h1>Heading 1</h1>');
|
||||
expect(html).toContain('<h2>Heading 2</h2>');
|
||||
expect(html).toContain('<h3>Heading 3</h3>');
|
||||
expect(html).toContain('<h1');
|
||||
expect(html).toContain('Heading 1');
|
||||
expect(html).toContain('<h2');
|
||||
expect(html).toContain('Heading 2');
|
||||
expect(html).toContain('<h3');
|
||||
expect(html).toContain('Heading 3');
|
||||
});
|
||||
|
||||
it('converts markdown bullet lists', () => {
|
||||
@@ -406,6 +453,7 @@ describe('groupChatExport', () => {
|
||||
|
||||
expect(html).toContain('<li>Item 1</li>');
|
||||
expect(html).toContain('<li>Item 2</li>');
|
||||
expect(html).toContain('<ul>');
|
||||
});
|
||||
|
||||
it('converts markdown links', () => {
|
||||
@@ -416,18 +464,30 @@ describe('groupChatExport', () => {
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('<a href="https://example.com" target="_blank">this link</a>');
|
||||
expect(html).toContain('href="https://example.com"');
|
||||
expect(html).toContain('this link');
|
||||
});
|
||||
|
||||
it('converts newlines to br tags', () => {
|
||||
it('converts blockquotes', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: 'Line 1\nLine 2' },
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '> This is a quote' },
|
||||
];
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('<br>');
|
||||
expect(html).toContain('<blockquote>');
|
||||
});
|
||||
|
||||
it('converts strikethrough text', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '~~deleted~~' },
|
||||
];
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('<del>deleted</del>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -442,10 +502,9 @@ describe('groupChatExport', () => {
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], images, mockTheme);
|
||||
|
||||
expect(html).toContain('src="data:image/png;base64,abc123"');
|
||||
expect(html).toContain('class="embedded-image"');
|
||||
});
|
||||
|
||||
it('handles image references in different formats', () => {
|
||||
it('handles [Image: filename] pattern', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages: GroupChatMessage[] = [
|
||||
{ timestamp: '2023-12-21T10:00:00Z', from: 'Agent1', content: '[Image: photo.jpg]' },
|
||||
@@ -533,24 +592,14 @@ describe('groupChatExport', () => {
|
||||
});
|
||||
|
||||
describe('footer', () => {
|
||||
it('includes Maestro attribution', () => {
|
||||
it('includes Maestro attribution with runmaestro.ai', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
expect(html).toContain('Maestro');
|
||||
expect(html).toContain('https://maestro.sh');
|
||||
});
|
||||
|
||||
it('does not include JSON extraction tip', () => {
|
||||
const groupChat = createMockGroupChat();
|
||||
const messages = createMockMessages();
|
||||
|
||||
const html = generateGroupChatExportHtml(groupChat, messages, [], {}, mockTheme);
|
||||
|
||||
// JSON was removed, so no extraction tip
|
||||
expect(html).not.toContain('embedded JSON');
|
||||
expect(html).toContain('Exported from');
|
||||
expect(html).toContain('href="https://runmaestro.ai"');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user