@patternfly/chatbot 6.4.0-prerelease.2 → 6.4.0-prerelease.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Chatbot/Chatbot.js +1 -7
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +15 -9
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +40 -2
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
- package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/index.js +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
- package/dist/cjs/DeepThinking/index.d.ts +2 -0
- package/dist/cjs/DeepThinking/index.js +23 -0
- package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
- package/dist/cjs/FilePreview/FilePreview.js +26 -0
- package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
- package/dist/cjs/FilePreview/index.d.ts +2 -0
- package/dist/cjs/FilePreview/index.js +23 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -3
- package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/cjs/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/cjs/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/cjs/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/cjs/Message/Message.d.ts +15 -0
- package/dist/cjs/Message/Message.js +129 -32
- package/dist/cjs/Message/Message.test.js +71 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.js +5 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/cjs/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/cjs/Message/UserFeedback/UserFeedback.test.js +44 -0
- package/dist/cjs/MessageBar/MessageBar.js +19 -4
- package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
- package/dist/cjs/MessageBox/JumpButton.js +1 -1
- package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
- package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
- package/dist/cjs/MessageBox/MessageBox.js +2 -2
- package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
- package/dist/cjs/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/cjs/SourcesCard/SourcesCard.js +6 -6
- package/dist/cjs/SourcesCard/SourcesCard.test.js +49 -0
- package/dist/cjs/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/cjs/ToolResponse/ToolResponse.js +18 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
- package/dist/cjs/ToolResponse/index.d.ts +2 -0
- package/dist/cjs/ToolResponse/index.js +23 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +10 -1
- package/dist/css/main.css +273 -17
- package/dist/css/main.css.map +1 -1
- package/dist/dynamic/DeepThinking/package.json +1 -0
- package/dist/dynamic/FilePreview/package.json +1 -0
- package/dist/dynamic/ToolResponse/package.json +1 -0
- package/dist/esm/Chatbot/Chatbot.js +1 -7
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +17 -11
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +41 -3
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
- package/dist/esm/ChatbotHeader/index.d.ts +1 -0
- package/dist/esm/ChatbotHeader/index.js +1 -0
- package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/esm/DeepThinking/DeepThinking.js +14 -0
- package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
- package/dist/esm/DeepThinking/index.d.ts +2 -0
- package/dist/esm/DeepThinking/index.js +2 -0
- package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
- package/dist/esm/FilePreview/FilePreview.js +21 -0
- package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/esm/FilePreview/FilePreview.test.js +92 -0
- package/dist/esm/FilePreview/index.d.ts +2 -0
- package/dist/esm/FilePreview/index.js +2 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +5 -5
- package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/esm/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/esm/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/esm/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/esm/Message/Message.d.ts +15 -0
- package/dist/esm/Message/Message.js +129 -32
- package/dist/esm/Message/Message.test.js +71 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.js +3 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/esm/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/esm/Message/UserFeedback/UserFeedback.test.js +45 -1
- package/dist/esm/MessageBar/MessageBar.js +19 -4
- package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
- package/dist/esm/MessageBox/JumpButton.js +1 -1
- package/dist/esm/MessageBox/JumpButton.test.js +4 -4
- package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
- package/dist/esm/MessageBox/MessageBox.js +2 -2
- package/dist/esm/MessageBox/MessageBox.test.js +2 -2
- package/dist/esm/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/esm/SourcesCard/SourcesCard.js +6 -6
- package/dist/esm/SourcesCard/SourcesCard.test.js +50 -1
- package/dist/esm/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/esm/ToolResponse/ToolResponse.js +14 -0
- package/dist/esm/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/esm/ToolResponse/ToolResponse.test.js +55 -0
- package/dist/esm/ToolResponse/index.d.ts +2 -0
- package/dist/esm/ToolResponse/index.js +2 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +101 -3
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +111 -85
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +70 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +135 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +28 -4
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +107 -2
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +616 -3
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +36 -5
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +12 -2
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +22 -3
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +1 -1
- package/patternfly-docs/patternfly-docs.config.js +1 -1
- package/src/Chatbot/Chatbot.scss +9 -2
- package/src/Chatbot/Chatbot.tsx +18 -31
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +28 -10
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +132 -3
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +80 -33
- package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
- package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
- package/src/ChatbotHeader/index.ts +1 -0
- package/src/ChatbotModal/ChatbotModal.scss +1 -1
- package/src/DeepThinking/DeepThinking.scss +24 -0
- package/src/DeepThinking/DeepThinking.test.tsx +61 -0
- package/src/DeepThinking/DeepThinking.tsx +68 -0
- package/src/DeepThinking/index.ts +3 -0
- package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +6 -9
- package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +6 -9
- package/src/FilePreview/FilePreview.scss +22 -0
- package/src/FilePreview/FilePreview.test.tsx +112 -0
- package/src/FilePreview/FilePreview.tsx +58 -0
- package/src/FilePreview/index.ts +3 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +2 -1
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +6 -5
- package/src/Message/LinkMessage/LinkMessage.tsx +6 -2
- package/src/Message/ListMessage/ListItemMessage.tsx +5 -1
- package/src/Message/ListMessage/ListMessage.scss +17 -0
- package/src/Message/Message.scss +44 -0
- package/src/Message/Message.test.tsx +90 -0
- package/src/Message/Message.tsx +171 -46
- package/src/Message/SuperscriptMessage/SuperscriptMessage.scss +8 -0
- package/src/Message/SuperscriptMessage/SuperscriptMessage.tsx +13 -0
- package/src/Message/TextMessage/TextMessage.scss +46 -5
- package/src/Message/UserFeedback/UserFeedback.test.tsx +107 -0
- package/src/Message/UserFeedback/UserFeedback.tsx +41 -6
- package/src/MessageBar/MessageBar.tsx +23 -3
- package/src/MessageBox/JumpButton.test.tsx +4 -4
- package/src/MessageBox/JumpButton.tsx +20 -4
- package/src/MessageBox/MessageBox.test.tsx +2 -2
- package/src/MessageBox/MessageBox.tsx +22 -1
- package/src/SourcesCard/SourcesCard.scss +17 -0
- package/src/SourcesCard/SourcesCard.test.tsx +93 -0
- package/src/SourcesCard/SourcesCard.tsx +116 -80
- package/src/ToolResponse/ToolResponse.scss +36 -0
- package/src/ToolResponse/ToolResponse.test.tsx +78 -0
- package/src/ToolResponse/ToolResponse.tsx +95 -0
- package/src/ToolResponse/index.ts +3 -0
- package/src/index.ts +9 -0
- package/src/main.scss +3 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Deep Thinking
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardBody,
|
|
7
|
+
CardBodyProps,
|
|
8
|
+
CardProps,
|
|
9
|
+
ExpandableSection,
|
|
10
|
+
ExpandableSectionProps
|
|
11
|
+
} from '@patternfly/react-core';
|
|
12
|
+
import { useState, type FunctionComponent } from 'react';
|
|
13
|
+
|
|
14
|
+
export interface DeepThinkingProps {
|
|
15
|
+
/** Toggle content shown for expandable section */
|
|
16
|
+
toggleContent: React.ReactNode;
|
|
17
|
+
/** Additional props passed to expandable section */
|
|
18
|
+
expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
|
|
19
|
+
/** Subheading rendered inside expandable section */
|
|
20
|
+
subheading?: string;
|
|
21
|
+
/** Body text rendered inside expandable section */
|
|
22
|
+
body?: React.ReactNode | string;
|
|
23
|
+
/** Additional props passed to main card */
|
|
24
|
+
cardProps?: CardProps;
|
|
25
|
+
/** Additional props passed to main card body */
|
|
26
|
+
cardBodyProps?: CardBodyProps;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const DeepThinking: FunctionComponent<DeepThinkingProps> = ({
|
|
30
|
+
body,
|
|
31
|
+
cardProps,
|
|
32
|
+
expandableSectionProps,
|
|
33
|
+
subheading,
|
|
34
|
+
toggleContent,
|
|
35
|
+
cardBodyProps
|
|
36
|
+
}: DeepThinkingProps) => {
|
|
37
|
+
const [isExpanded, setIsExpanded] = useState(true);
|
|
38
|
+
|
|
39
|
+
const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => {
|
|
40
|
+
setIsExpanded(isExpanded);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Card isCompact className="pf-chatbot__deep-thinking" {...cardProps}>
|
|
45
|
+
<CardBody {...cardBodyProps}>
|
|
46
|
+
<ExpandableSection
|
|
47
|
+
toggleContent={toggleContent}
|
|
48
|
+
onToggle={onToggle}
|
|
49
|
+
isExpanded={isExpanded}
|
|
50
|
+
isIndented
|
|
51
|
+
className="pf-chatbot__deep-thinking-expandable-section"
|
|
52
|
+
{...expandableSectionProps}
|
|
53
|
+
>
|
|
54
|
+
<div className="pf-chatbot__deep-thinking-section">
|
|
55
|
+
{subheading && (
|
|
56
|
+
<div className="pf-chatbot__deep-thinking-subheading">
|
|
57
|
+
<span>{subheading}</span>
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
{body && <div className="pf-chatbot__deep-thinking-body">{body}</div>}
|
|
61
|
+
</div>
|
|
62
|
+
</ExpandableSection>
|
|
63
|
+
</CardBody>
|
|
64
|
+
</Card>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default DeepThinking;
|
|
@@ -48,19 +48,16 @@ exports[`FileDetails should render file details 1`] = `
|
|
|
48
48
|
<span
|
|
49
49
|
class="pf-chatbot__code-fileName"
|
|
50
50
|
>
|
|
51
|
-
<
|
|
52
|
-
|
|
51
|
+
<span
|
|
52
|
+
class="pf-v6-c-truncate"
|
|
53
|
+
tabindex="0"
|
|
53
54
|
>
|
|
54
55
|
<span
|
|
55
|
-
class="pf-v6-c-
|
|
56
|
+
class="pf-v6-c-truncate__start"
|
|
56
57
|
>
|
|
57
|
-
|
|
58
|
-
class="pf-v6-c-truncate__start"
|
|
59
|
-
>
|
|
60
|
-
test
|
|
61
|
-
</span>
|
|
58
|
+
test
|
|
62
59
|
</span>
|
|
63
|
-
</
|
|
60
|
+
</span>
|
|
64
61
|
</span>
|
|
65
62
|
</div>
|
|
66
63
|
<div
|
|
@@ -60,19 +60,16 @@ exports[`FileDetailsLabel should render file details label 1`] = `
|
|
|
60
60
|
<span
|
|
61
61
|
class="pf-chatbot__code-fileName"
|
|
62
62
|
>
|
|
63
|
-
<
|
|
64
|
-
|
|
63
|
+
<span
|
|
64
|
+
class="pf-v6-c-truncate"
|
|
65
|
+
tabindex="0"
|
|
65
66
|
>
|
|
66
67
|
<span
|
|
67
|
-
class="pf-v6-c-
|
|
68
|
+
class="pf-v6-c-truncate__start"
|
|
68
69
|
>
|
|
69
|
-
|
|
70
|
-
class="pf-v6-c-truncate__start"
|
|
71
|
-
>
|
|
72
|
-
test
|
|
73
|
-
</span>
|
|
70
|
+
test
|
|
74
71
|
</span>
|
|
75
|
-
</
|
|
72
|
+
</span>
|
|
76
73
|
</span>
|
|
77
74
|
</div>
|
|
78
75
|
<div
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.pf-chatbot__file-preview-body {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--pf-t--global--spacer--md);
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.pf-chatbot__file-preview-icon {
|
|
10
|
+
color: var(--pf-t--global--icon--color--subtle);
|
|
11
|
+
width: var(--pf-t--global--icon--size--2xl);
|
|
12
|
+
height: var(--pf-t--global--icon--size--2xl);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.pf-chatbot__file-preview-name {
|
|
16
|
+
font-size: var(--pf-t--global--font--size--xl);
|
|
17
|
+
font-weight: var(--pf-t--global--font--weight--heading--default);
|
|
18
|
+
}
|
|
19
|
+
.pf-chatbot__file-preview-body {
|
|
20
|
+
color: var(--pf-t--global--text--color--subtle);
|
|
21
|
+
font-size: var(--pf-t--global--font--size--body--lg);
|
|
22
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import FilePreview from './FilePreview';
|
|
4
|
+
import { ChatbotDisplayMode } from '../Chatbot';
|
|
5
|
+
import { Button, ModalBodyProps, ModalHeaderProps } from '@patternfly/react-core';
|
|
6
|
+
|
|
7
|
+
describe('FilePreview', () => {
|
|
8
|
+
const defaultProps = {
|
|
9
|
+
isModalOpen: true,
|
|
10
|
+
handleModalToggle: jest.fn(),
|
|
11
|
+
fileName: 'test-file.txt',
|
|
12
|
+
children: 'File content preview'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
jest.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should render with basic props', () => {
|
|
20
|
+
render(<FilePreview {...defaultProps} />);
|
|
21
|
+
expect(screen.getByText('File preview')).toBeInTheDocument();
|
|
22
|
+
expect(screen.getByText('test-file.txt')).toBeInTheDocument();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should render with custom title', () => {
|
|
26
|
+
const customTitle = 'Custom file preview title';
|
|
27
|
+
render(<FilePreview {...defaultProps} title={customTitle} />);
|
|
28
|
+
expect(screen.getByRole('heading', { name: customTitle })).toBeTruthy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should handle modal toggle when closed', () => {
|
|
32
|
+
const mockToggle = jest.fn();
|
|
33
|
+
render(<FilePreview {...defaultProps} isModalOpen={false} handleModalToggle={mockToggle} />);
|
|
34
|
+
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should apply default display mode class', () => {
|
|
38
|
+
render(<FilePreview {...defaultProps} />);
|
|
39
|
+
const modal = screen.getByRole('dialog');
|
|
40
|
+
expect(modal).toHaveClass('pf-chatbot__file-preview-modal--default');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should apply custom display mode class', () => {
|
|
44
|
+
render(<FilePreview {...defaultProps} displayMode={ChatbotDisplayMode.fullscreen} />);
|
|
45
|
+
const modal = screen.getByRole('dialog');
|
|
46
|
+
expect(modal).toHaveClass('pf-chatbot__file-preview-modal--fullscreen');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should apply compact styling when isCompact is true', () => {
|
|
50
|
+
render(<FilePreview {...defaultProps} isCompact />);
|
|
51
|
+
const modal = screen.getByRole('dialog');
|
|
52
|
+
expect(modal).toHaveClass('pf-m-compact');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should not apply compact styling when isCompact is false', () => {
|
|
56
|
+
render(<FilePreview {...defaultProps} isCompact={false} />);
|
|
57
|
+
const modal = screen.getByRole('dialog');
|
|
58
|
+
expect(modal).not.toHaveClass('pf-m-compact');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should apply custom className', () => {
|
|
62
|
+
const customClass = 'custom-file-preview';
|
|
63
|
+
render(<FilePreview {...defaultProps} className={customClass} />);
|
|
64
|
+
const modal = screen.getByRole('dialog');
|
|
65
|
+
expect(modal).toHaveClass(customClass);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should pass through additional props to ChatbotModal', () => {
|
|
69
|
+
render(<FilePreview {...defaultProps} data-testid="file-preview-modal" />);
|
|
70
|
+
const modal = screen.getByTestId('file-preview-modal');
|
|
71
|
+
expect(modal).toBeInTheDocument();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should pass modalHeaderProps to ModalHeader', () => {
|
|
75
|
+
const modalHeaderProps = {
|
|
76
|
+
'data-testid': 'custom-header'
|
|
77
|
+
} as ModalHeaderProps;
|
|
78
|
+
render(<FilePreview {...defaultProps} modalHeaderProps={modalHeaderProps} />);
|
|
79
|
+
const header = screen.getByTestId('custom-header');
|
|
80
|
+
expect(header).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should pass modalBodyProps to ModalBody', () => {
|
|
84
|
+
const modalBodyProps = {
|
|
85
|
+
'data-testid': 'custom-body'
|
|
86
|
+
} as ModalBodyProps;
|
|
87
|
+
render(<FilePreview {...defaultProps} modalBodyProps={modalBodyProps} />);
|
|
88
|
+
const body = screen.getByTestId('custom-body');
|
|
89
|
+
expect(body).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should pass ouiaId to ChatbotModal', () => {
|
|
93
|
+
const ouiaId = 'file-preview-ouia-id';
|
|
94
|
+
render(<FilePreview {...defaultProps} ouiaId={ouiaId} />);
|
|
95
|
+
const modal = screen.getByRole('dialog');
|
|
96
|
+
expect(modal).toHaveAttribute('data-ouia-component-id', ouiaId);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should handle complex children', () => {
|
|
100
|
+
const complexChildren = (
|
|
101
|
+
<div>
|
|
102
|
+
<h3>File details</h3>
|
|
103
|
+
<p>Size: 1.2 MB</p>
|
|
104
|
+
<Button>Download</Button>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
render(<FilePreview {...defaultProps}>{complexChildren}</FilePreview>);
|
|
108
|
+
expect(screen.getByRole('heading', { name: /File details/i })).toBeTruthy();
|
|
109
|
+
expect(screen.getByText('Size: 1.2 MB')).toBeTruthy();
|
|
110
|
+
expect(screen.getByRole('button', { name: /Download/i })).toBeTruthy();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ModalBody, ModalBodyProps, ModalHeader, ModalHeaderProps } from '@patternfly/react-core';
|
|
2
|
+
import type { FunctionComponent } from 'react';
|
|
3
|
+
import { ChatbotDisplayMode } from '../Chatbot';
|
|
4
|
+
import ChatbotModal, { ChatbotModalProps } from '../ChatbotModal';
|
|
5
|
+
import { FileIcon } from '@patternfly/react-icons';
|
|
6
|
+
|
|
7
|
+
export interface FilePreviewProps extends ChatbotModalProps {
|
|
8
|
+
/** Class applied to modal */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Function that handles modal toggle */
|
|
11
|
+
handleModalToggle: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
|
|
12
|
+
/** Whether modal is open */
|
|
13
|
+
isModalOpen: boolean;
|
|
14
|
+
/** Title of modal */
|
|
15
|
+
title?: string;
|
|
16
|
+
/** Display mode for the Chatbot parent; this influences the styles applied */
|
|
17
|
+
displayMode?: ChatbotDisplayMode;
|
|
18
|
+
/** File name */
|
|
19
|
+
fileName: string;
|
|
20
|
+
/** Sets modal to compact styling. */
|
|
21
|
+
isCompact?: boolean;
|
|
22
|
+
/** Additional props passed to modal header */
|
|
23
|
+
modalHeaderProps?: ModalHeaderProps;
|
|
24
|
+
/** Additional props passed to modal body */
|
|
25
|
+
modalBodyProps?: ModalBodyProps;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const FilePreview: FunctionComponent<FilePreviewProps> = ({
|
|
29
|
+
isModalOpen,
|
|
30
|
+
displayMode = ChatbotDisplayMode.default,
|
|
31
|
+
children,
|
|
32
|
+
fileName,
|
|
33
|
+
isCompact,
|
|
34
|
+
className,
|
|
35
|
+
handleModalToggle,
|
|
36
|
+
title = 'File preview',
|
|
37
|
+
modalHeaderProps,
|
|
38
|
+
modalBodyProps,
|
|
39
|
+
...props
|
|
40
|
+
}: FilePreviewProps) => (
|
|
41
|
+
<ChatbotModal
|
|
42
|
+
isOpen={isModalOpen}
|
|
43
|
+
className={`pf-chatbot__file-preview-modal pf-chatbot__file-preview-modal--${displayMode} ${isCompact ? 'pf-m-compact' : ''} ${className ? className : ''}`}
|
|
44
|
+
displayMode={displayMode}
|
|
45
|
+
onClose={handleModalToggle}
|
|
46
|
+
isCompact={isCompact}
|
|
47
|
+
{...props}
|
|
48
|
+
>
|
|
49
|
+
<ModalHeader title={title} {...modalHeaderProps} />
|
|
50
|
+
<ModalBody className="pf-chatbot__file-preview-body" {...modalBodyProps}>
|
|
51
|
+
<FileIcon className="pf-chatbot__file-preview-icon" />
|
|
52
|
+
<h2 className="pf-chatbot__file-preview-name">{fileName}</h2>
|
|
53
|
+
{children && <div className="pf-chatbot__file-preview-body">{children}</div>}
|
|
54
|
+
</ModalBody>
|
|
55
|
+
</ChatbotModal>
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
export default FilePreview;
|
|
@@ -77,8 +77,9 @@
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
.pf-chatbot__message-inline-code {
|
|
80
|
+
--pf-chatbot-message-text-inline-code-font-size: var(--pf-t--global--font--size--body--default);
|
|
80
81
|
background-color: var(--pf-t--global--background--color--tertiary--default);
|
|
81
|
-
font-size: var(--pf-
|
|
82
|
+
font-size: var(--pf-chatbot-message-text-inline-code-font-size);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
.pf-chatbot__message-code-toggle {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ============================================================================
|
|
2
2
|
// Chatbot Main - Message - Content - Code Block
|
|
3
3
|
// ============================================================================
|
|
4
|
-
import { useState, useRef,
|
|
4
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
5
5
|
// Import PatternFly components
|
|
6
6
|
import {
|
|
7
7
|
CodeBlock,
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
ExpandableSectionToggle,
|
|
14
14
|
ExpandableSectionProps,
|
|
15
15
|
ExpandableSectionToggleProps,
|
|
16
|
-
ExpandableSectionVariant
|
|
16
|
+
ExpandableSectionVariant,
|
|
17
|
+
getUniqueId
|
|
17
18
|
} from '@patternfly/react-core';
|
|
18
19
|
|
|
19
20
|
import { CheckIcon } from '@patternfly/react-icons/dist/esm/icons/check-icon';
|
|
@@ -56,9 +57,9 @@ const CodeBlockMessage = ({
|
|
|
56
57
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
57
58
|
|
|
58
59
|
const buttonRef = useRef();
|
|
59
|
-
const tooltipID =
|
|
60
|
-
const toggleId =
|
|
61
|
-
const contentId =
|
|
60
|
+
const tooltipID = getUniqueId();
|
|
61
|
+
const toggleId = getUniqueId();
|
|
62
|
+
const contentId = getUniqueId();
|
|
62
63
|
const codeBlockRef = useRef<HTMLDivElement>(null);
|
|
63
64
|
|
|
64
65
|
const language = /language-(\w+)/.exec(className || '')?.[1];
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { Button, ButtonProps } from '@patternfly/react-core';
|
|
6
6
|
import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
|
|
7
|
+
import { ExtraProps } from 'react-markdown';
|
|
7
8
|
|
|
8
|
-
const LinkMessage = ({ children, target, href, ...props }: ButtonProps) => {
|
|
9
|
+
const LinkMessage = ({ children, target, href, id, ...props }: ButtonProps & ExtraProps) => {
|
|
9
10
|
if (target === '_blank') {
|
|
10
11
|
return (
|
|
11
12
|
<Button
|
|
@@ -16,6 +17,8 @@ const LinkMessage = ({ children, target, href, ...props }: ButtonProps) => {
|
|
|
16
17
|
iconPosition="end"
|
|
17
18
|
isInline
|
|
18
19
|
target={target}
|
|
20
|
+
// need to explicitly call this out or id doesn't seem to get passed - required for footnotes
|
|
21
|
+
id={id}
|
|
19
22
|
{...props}
|
|
20
23
|
>
|
|
21
24
|
{children}
|
|
@@ -24,7 +27,8 @@ const LinkMessage = ({ children, target, href, ...props }: ButtonProps) => {
|
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
return (
|
|
27
|
-
|
|
30
|
+
// need to explicitly call this out or id doesn't seem to get passed - required for footnotes
|
|
31
|
+
<Button isInline component="a" href={href} variant="link" id={id} {...props}>
|
|
28
32
|
{children}
|
|
29
33
|
</Button>
|
|
30
34
|
);
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
import { ExtraProps } from 'react-markdown';
|
|
6
6
|
import { ListItem } from '@patternfly/react-core';
|
|
7
7
|
|
|
8
|
-
const ListItemMessage = ({ children }: JSX.IntrinsicElements['li'] & ExtraProps) =>
|
|
8
|
+
const ListItemMessage = ({ children, ...props }: JSX.IntrinsicElements['li'] & ExtraProps) => (
|
|
9
|
+
<ListItem {...props} tabIndex={props?.id?.includes('fn-') ? -1 : props?.tabIndex}>
|
|
10
|
+
{children}
|
|
11
|
+
</ListItem>
|
|
12
|
+
);
|
|
9
13
|
|
|
10
14
|
export default ListItemMessage;
|
|
@@ -21,5 +21,22 @@
|
|
|
21
21
|
background-color: var(--pf-t--global--color--brand--default);
|
|
22
22
|
color: var(--pf-t--global--text--color--on-brand--default);
|
|
23
23
|
padding: var(--pf-t--global--spacer--sm);
|
|
24
|
+
|
|
25
|
+
// prevents issues when highlighting things like footnotes - don't have blue on blue
|
|
26
|
+
.pf-chatbot__message-text {
|
|
27
|
+
background-color: initial;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// targets footnotes specifically and prevents misalignment problems
|
|
32
|
+
.footnotes {
|
|
33
|
+
li > span {
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
li a {
|
|
40
|
+
color: var(--pf-t--global--text--color--on-brand--default);
|
|
24
41
|
}
|
|
25
42
|
}
|
package/src/Message/Message.scss
CHANGED
|
@@ -89,6 +89,49 @@
|
|
|
89
89
|
display: grid;
|
|
90
90
|
gap: var(--pf-t--global--spacer--sm);
|
|
91
91
|
}
|
|
92
|
+
|
|
93
|
+
// targets footnotes specifically
|
|
94
|
+
.footnotes,
|
|
95
|
+
.pf-chatbot__message-text.footnotes {
|
|
96
|
+
padding: var(--pf-t--global--spacer--sm) var(--pf-t--global--spacer--sm) 0 var(--pf-t--global--spacer--sm);
|
|
97
|
+
--pf-chatbot-message-text-font-size: var(--pf-t--global--font--size--xs);
|
|
98
|
+
--pf-chatbot-message-text-inline-code-font-size: var(--pf-t--global--font--size--xs);
|
|
99
|
+
|
|
100
|
+
.pf-chatbot__message-text h1,
|
|
101
|
+
h2,
|
|
102
|
+
h3,
|
|
103
|
+
h4,
|
|
104
|
+
h5,
|
|
105
|
+
h6 {
|
|
106
|
+
--pf-v6-c-content--h1--FontSize: var(--pf-t--global--font--size--md);
|
|
107
|
+
--pf-v6-c-content--h2--FontSize: var(--pf-t--global--font--size--md);
|
|
108
|
+
--pf-v6-c-content--h3--FontSize: var(--pf-t--global--font--size--md);
|
|
109
|
+
--pf-v6-c-content--h4--FontSize: var(--pf-t--global--font--size--md);
|
|
110
|
+
--pf-v6-c-content--h5--FontSize: var(--pf-t--global--font--size--md);
|
|
111
|
+
--pf-v6-c-content--h6--FontSize: var(--pf-t--global--font--size--md);
|
|
112
|
+
}
|
|
113
|
+
.pf-chatbot__message-text .pf-v6-c-content,
|
|
114
|
+
.pf-chatbot__message-text .pf-v6-c-content--small,
|
|
115
|
+
.pf-chatbot__message-text .pf-v6-c-content--blockquote,
|
|
116
|
+
.pf-chatbot__message-text p,
|
|
117
|
+
.pf-chatbot__message-text a {
|
|
118
|
+
--pf-v6-c-content--FontSize: var(--pf-t--global--font--size--xs);
|
|
119
|
+
}
|
|
120
|
+
.pf-chatbot__message-inline-code,
|
|
121
|
+
.pf-chatbot__message-text .pf-v6-c-button.pf-m-link,
|
|
122
|
+
.pf-chatbot__message-ordered-list .pf-v6-c-list,
|
|
123
|
+
.pf-chatbot__message-ordered-list ul,
|
|
124
|
+
.pf-chatbot__message-ordered-list li,
|
|
125
|
+
.pf-chatbot__message-unordered-list .pf-v6-c-list,
|
|
126
|
+
.pf-chatbot__message-unordered-list ul,
|
|
127
|
+
.pf-chatbot__message-unordered-list li {
|
|
128
|
+
font-size: var(--pf-t--global--font--size--xs);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.footnotes {
|
|
133
|
+
background-color: var(--pf-t--global--background--color--tertiary--default);
|
|
134
|
+
}
|
|
92
135
|
}
|
|
93
136
|
|
|
94
137
|
// Attachments
|
|
@@ -106,6 +149,7 @@
|
|
|
106
149
|
@import './MessageLoading';
|
|
107
150
|
@import './CodeBlockMessage/CodeBlockMessage';
|
|
108
151
|
@import './TextMessage/TextMessage';
|
|
152
|
+
@import './SuperscriptMessage/SuperscriptMessage.scss';
|
|
109
153
|
|
|
110
154
|
// ============================================================================
|
|
111
155
|
// Information density styles
|
|
@@ -7,6 +7,7 @@ import { monitorSampleAppQuickStart } from './QuickStarts/monitor-sampleapp-quic
|
|
|
7
7
|
import { monitorSampleAppQuickStartWithImage } from './QuickStarts/monitor-sampleapp-quickstart-with-image';
|
|
8
8
|
import rehypeExternalLinks from '../__mocks__/rehype-external-links';
|
|
9
9
|
import { AlertActionLink } from '@patternfly/react-core';
|
|
10
|
+
import { DeepThinkingProps } from '../DeepThinking';
|
|
10
11
|
|
|
11
12
|
const ALL_ACTIONS = [
|
|
12
13
|
{ label: /Good response/i },
|
|
@@ -141,10 +142,30 @@ const EMPTY_TABLE = `
|
|
|
141
142
|
|
|
142
143
|
`;
|
|
143
144
|
|
|
145
|
+
const FOOTNOTE = `This is some text with a footnote[^1] and here's a longer one.[^bignote]
|
|
146
|
+
|
|
147
|
+
You can also reference the same footnote multiple times[^1].
|
|
148
|
+
|
|
149
|
+
[^1]: This is the full footnote text. You can click the arrow to go back up.
|
|
150
|
+
|
|
151
|
+
[^bignote]: Here's one with multiple paragraphs and **formatting**.
|
|
152
|
+
|
|
153
|
+
Indent paragraphs to include them in the footnote.
|
|
154
|
+
|
|
155
|
+
Add as many paragraphs as you like. You can include *italic text*, **bold text**, and even \`code\`.
|
|
156
|
+
|
|
157
|
+
> You can even include blockquotes in footnotes!`;
|
|
158
|
+
|
|
144
159
|
const IMAGE = ``;
|
|
145
160
|
|
|
146
161
|
const INLINE_IMAGE = `inline text `;
|
|
147
162
|
|
|
163
|
+
const DEEP_THINKING: DeepThinkingProps = {
|
|
164
|
+
toggleContent: 'Show thinking',
|
|
165
|
+
subheading: 'Thought for 3 seconds',
|
|
166
|
+
body: "Here's why I said this."
|
|
167
|
+
};
|
|
168
|
+
|
|
148
169
|
const ERROR = {
|
|
149
170
|
title: 'Could not load chat',
|
|
150
171
|
children: 'Wait a few minutes and check your network settings. If the issue persists: ',
|
|
@@ -675,6 +696,28 @@ describe('Message', () => {
|
|
|
675
696
|
);
|
|
676
697
|
expect(screen.getAllByRole('img')[1]).toHaveAttribute('src', 'test.png');
|
|
677
698
|
});
|
|
699
|
+
it('should handle tool response correctly', async () => {
|
|
700
|
+
render(
|
|
701
|
+
<Message
|
|
702
|
+
avatar="./img"
|
|
703
|
+
role="user"
|
|
704
|
+
name="User"
|
|
705
|
+
content="Hi"
|
|
706
|
+
toolResponse={{
|
|
707
|
+
toggleContent: 'Tool response: Name',
|
|
708
|
+
subheading: 'Thought for 3 seconds',
|
|
709
|
+
body: 'Lorem ipsum dolor sit amet',
|
|
710
|
+
cardTitle: 'Card title',
|
|
711
|
+
cardBody: 'Card body'
|
|
712
|
+
}}
|
|
713
|
+
/>
|
|
714
|
+
);
|
|
715
|
+
expect(screen.getByRole('button', { name: /Tool response: Name/i })).toBeTruthy();
|
|
716
|
+
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
|
|
717
|
+
expect(screen.getByText('Lorem ipsum dolor sit amet')).toBeTruthy();
|
|
718
|
+
expect(screen.getByText('Card title')).toBeTruthy();
|
|
719
|
+
expect(screen.getByText('Card body')).toBeTruthy();
|
|
720
|
+
});
|
|
678
721
|
it('should handle block quote correctly', () => {
|
|
679
722
|
render(<Message avatar="./img" role="user" name="User" content={BLOCK_QUOTES} />);
|
|
680
723
|
expect(screen.getByText(/Blockquotes can also be nested.../)).toBeTruthy();
|
|
@@ -740,6 +783,28 @@ describe('Message', () => {
|
|
|
740
783
|
render(<Message avatar="./img" role="user" name="User" content={TABLE} tableProps={{ 'aria-label': 'Test' }} />);
|
|
741
784
|
expect(screen.getByRole('grid', { name: /Test/i })).toBeTruthy();
|
|
742
785
|
});
|
|
786
|
+
it('should render footnote correctly', () => {
|
|
787
|
+
render(<Message avatar="./img" role="user" name="User" content={FOOTNOTE} />);
|
|
788
|
+
expect(screen.getByText(/This is some text with a footnote/i)).toBeTruthy();
|
|
789
|
+
expect(screen.getByText(/and here's a longer one./i)).toBeTruthy();
|
|
790
|
+
expect(screen.getByText(/You can also reference the same footnote multiple times./i)).toBeTruthy();
|
|
791
|
+
expect(screen.getByRole('heading', { name: /Footnotes/i })).toBeTruthy();
|
|
792
|
+
expect(screen.getByText(/This is the full footnote text. You can click the arrow to go back up./i)).toBeTruthy();
|
|
793
|
+
expect(screen.getByText(/Here's one with multiple paragraphs and/i)).toBeTruthy();
|
|
794
|
+
expect(screen.getByText(/formatting/i)).toBeTruthy();
|
|
795
|
+
expect(screen.getByText(/Indent paragraphs to include them in the footnote./i)).toBeTruthy();
|
|
796
|
+
expect(screen.getByText(/Add as many paragraphs as you like. You can include/i)).toBeTruthy();
|
|
797
|
+
expect(screen.getByText(/italic text/i)).toBeTruthy();
|
|
798
|
+
expect(screen.getByText(/bold text/i)).toBeTruthy();
|
|
799
|
+
expect(screen.getByText(/, and even/i)).toBeTruthy();
|
|
800
|
+
expect(screen.getByText(/code/i)).toBeTruthy();
|
|
801
|
+
expect(screen.getByText(/You can even include blockquotes in footnotes!/i)).toBeTruthy();
|
|
802
|
+
expect(screen.getAllByRole('link', { name: '1' })).toHaveLength(2);
|
|
803
|
+
expect(screen.getAllByRole('link', { name: '2' })).toBeTruthy();
|
|
804
|
+
expect(screen.getByRole('link', { name: 'Back to reference 1' })).toBeTruthy();
|
|
805
|
+
expect(screen.getByRole('link', { name: 'Back to reference 1-2' })).toBeTruthy();
|
|
806
|
+
expect(screen.getByRole('link', { name: /Back to reference 2/i })).toBeTruthy();
|
|
807
|
+
});
|
|
743
808
|
it('should render beforeMainContent with main content', () => {
|
|
744
809
|
const mainContent = 'Main message content';
|
|
745
810
|
const beforeMainContentText = 'Before main content';
|
|
@@ -962,4 +1027,29 @@ describe('Message', () => {
|
|
|
962
1027
|
const form = container.querySelector('form');
|
|
963
1028
|
expect(form).toHaveClass('test');
|
|
964
1029
|
});
|
|
1030
|
+
it('should be able to disable markdown parsing', () => {
|
|
1031
|
+
render(<Message avatar="./img" role="user" name="User" content={CODE_MESSAGE} isMarkdownDisabled />);
|
|
1032
|
+
// this is looking for markdown syntax that is ordinarily stripped
|
|
1033
|
+
expect(screen.getByText(/~~~yaml/i)).toBeTruthy();
|
|
1034
|
+
});
|
|
1035
|
+
it('should be able to pass props to react-markdown, such as disabling tags', () => {
|
|
1036
|
+
render(
|
|
1037
|
+
<Message
|
|
1038
|
+
avatar="./img"
|
|
1039
|
+
role="user"
|
|
1040
|
+
name="User"
|
|
1041
|
+
content={CODE_MESSAGE}
|
|
1042
|
+
reactMarkdownProps={{ disallowedElements: ['code'] }}
|
|
1043
|
+
/>
|
|
1044
|
+
);
|
|
1045
|
+
expect(screen.getByText('Here is some YAML code:')).toBeTruthy();
|
|
1046
|
+
// code block isn't rendering
|
|
1047
|
+
expect(screen.queryByRole('button', { name: 'Copy code' })).toBeFalsy();
|
|
1048
|
+
});
|
|
1049
|
+
it('should render deep thinking section correctly', () => {
|
|
1050
|
+
render(<Message avatar="./img" role="user" name="User" content="" deepThinking={DEEP_THINKING} />);
|
|
1051
|
+
expect(screen.getByRole('button', { name: /Show thinking/i })).toBeTruthy();
|
|
1052
|
+
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
|
|
1053
|
+
expect(screen.getByText("Here's why I said this.")).toBeTruthy();
|
|
1054
|
+
});
|
|
965
1055
|
});
|