@patternfly/chatbot 6.8.0-prerelease.6 → 6.8.0-prerelease.8
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/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +46 -5
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +125 -16
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +324 -0
- package/dist/cjs/MessageBox/MessageBox.d.ts +2 -0
- package/dist/cjs/MessageBox/MessageBox.js +3 -2
- package/dist/css/main.css +59 -7
- package/dist/css/main.css.map +1 -1
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +46 -5
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +128 -19
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +325 -1
- package/dist/esm/MessageBox/MessageBox.d.ts +2 -0
- package/dist/esm/MessageBox/MessageBox.js +3 -2
- package/package.json +2 -2
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithExpandableGroups.tsx +104 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +12 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +52 -6
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +551 -3
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +350 -49
- package/src/ChatbotToggle/ChatbotToggle.scss +6 -0
- package/src/Message/Message.scss +5 -0
- package/src/MessageBox/MessageBox.scss +15 -1
- package/src/MessageBox/MessageBox.tsx +10 -1
|
@@ -2,10 +2,10 @@ import '@testing-library/jest-dom';
|
|
|
2
2
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
3
3
|
|
|
4
4
|
import { ChatbotDisplayMode } from '../Chatbot/Chatbot';
|
|
5
|
-
import ChatbotConversationHistoryNav, { Conversation } from './ChatbotConversationHistoryNav';
|
|
6
|
-
import { EmptyStateStatus, Spinner } from '@patternfly/react-core';
|
|
5
|
+
import ChatbotConversationHistoryNav, { Conversation, ConversationGroup } from './ChatbotConversationHistoryNav';
|
|
6
|
+
import { EmptyStateStatus, Spinner, MenuItem } from '@patternfly/react-core';
|
|
7
7
|
import { BellIcon, OutlinedCommentsIcon, SearchIcon } from '@patternfly/react-icons';
|
|
8
|
-
import { ComponentType } from 'react';
|
|
8
|
+
import { ComponentType, useState } from 'react';
|
|
9
9
|
|
|
10
10
|
const ERROR = {
|
|
11
11
|
bodyText: (
|
|
@@ -715,4 +715,552 @@ describe('ChatbotConversationHistoryNav', () => {
|
|
|
715
715
|
);
|
|
716
716
|
expect(screen.getByTestId('bell')).toBeInTheDocument();
|
|
717
717
|
});
|
|
718
|
+
|
|
719
|
+
it('renders static and expandable groups from ConversationGroup[]', () => {
|
|
720
|
+
const groups: ConversationGroup[] = [
|
|
721
|
+
{
|
|
722
|
+
id: 'pinned',
|
|
723
|
+
label: 'Pinned chats',
|
|
724
|
+
items: initialConversations
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
id: 'chats',
|
|
728
|
+
label: 'Chats',
|
|
729
|
+
expandable: {
|
|
730
|
+
isExpanded: true,
|
|
731
|
+
onToggle: jest.fn()
|
|
732
|
+
},
|
|
733
|
+
items: [{ id: '2', text: 'Chatbot extension' }]
|
|
734
|
+
}
|
|
735
|
+
];
|
|
736
|
+
|
|
737
|
+
render(
|
|
738
|
+
<ChatbotConversationHistoryNav
|
|
739
|
+
onDrawerToggle={onDrawerToggle}
|
|
740
|
+
isDrawerOpen={true}
|
|
741
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
742
|
+
setIsDrawerOpen={jest.fn()}
|
|
743
|
+
conversations={groups}
|
|
744
|
+
/>
|
|
745
|
+
);
|
|
746
|
+
|
|
747
|
+
expect(screen.getByRole('heading', { name: 'Pinned chats', level: 3 })).toBeInTheDocument();
|
|
748
|
+
expect(screen.queryByRole('button', { name: 'Pinned chats' })).not.toBeInTheDocument();
|
|
749
|
+
expect(screen.getByRole('button', { name: 'Chats' })).toBeInTheDocument();
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
it('labels each MenuList with aria-labelledby referencing its visible label', () => {
|
|
753
|
+
const groups: ConversationGroup[] = [
|
|
754
|
+
{
|
|
755
|
+
id: 'pinned',
|
|
756
|
+
label: 'Pinned chats',
|
|
757
|
+
items: initialConversations
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
id: 'chats',
|
|
761
|
+
label: 'Chats',
|
|
762
|
+
expandable: {
|
|
763
|
+
isExpanded: true,
|
|
764
|
+
onToggle: jest.fn()
|
|
765
|
+
},
|
|
766
|
+
items: [{ id: '2', text: 'Chatbot extension' }]
|
|
767
|
+
}
|
|
768
|
+
];
|
|
769
|
+
|
|
770
|
+
render(
|
|
771
|
+
<ChatbotConversationHistoryNav
|
|
772
|
+
onDrawerToggle={onDrawerToggle}
|
|
773
|
+
isDrawerOpen={true}
|
|
774
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
775
|
+
setIsDrawerOpen={jest.fn()}
|
|
776
|
+
conversations={groups}
|
|
777
|
+
/>
|
|
778
|
+
);
|
|
779
|
+
|
|
780
|
+
const pinnedHeading = screen.getByRole('heading', { name: 'Pinned chats', level: 3 });
|
|
781
|
+
expect(pinnedHeading).toHaveAttribute('id', 'chatbot-nav-group-pinned-label');
|
|
782
|
+
expect(pinnedHeading.closest('section')).toHaveAttribute('aria-labelledby', 'chatbot-nav-group-pinned-label');
|
|
783
|
+
|
|
784
|
+
expect(screen.getByRole('menu', { name: 'Pinned chats' })).toHaveAttribute(
|
|
785
|
+
'aria-labelledby',
|
|
786
|
+
'chatbot-nav-group-pinned-label'
|
|
787
|
+
);
|
|
788
|
+
expect(
|
|
789
|
+
document.querySelector('ul.pf-v6-c-menu__list[aria-labelledby="chatbot-nav-group-pinned-label"]')
|
|
790
|
+
).toBeTruthy();
|
|
791
|
+
|
|
792
|
+
const chatsToggle = screen.getByRole('button', { name: 'Chats' });
|
|
793
|
+
expect(chatsToggle).toHaveAttribute('id', 'chatbot-nav-group-chats-toggle');
|
|
794
|
+
|
|
795
|
+
expect(screen.getByRole('menu', { name: 'Chats' })).toHaveAttribute(
|
|
796
|
+
'aria-labelledby',
|
|
797
|
+
'chatbot-nav-group-chats-toggle'
|
|
798
|
+
);
|
|
799
|
+
expect(
|
|
800
|
+
document.querySelector('ul.pf-v6-c-menu__list[aria-labelledby="chatbot-nav-group-chats-toggle"]')
|
|
801
|
+
).toBeTruthy();
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
it('labels grouped object conversations on the menu list element', () => {
|
|
805
|
+
render(
|
|
806
|
+
<ChatbotConversationHistoryNav
|
|
807
|
+
onDrawerToggle={onDrawerToggle}
|
|
808
|
+
isDrawerOpen={true}
|
|
809
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
810
|
+
setIsDrawerOpen={jest.fn()}
|
|
811
|
+
conversations={{ Today: initialConversations }}
|
|
812
|
+
/>
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
expect(document.querySelector('ul.pf-v6-c-menu__list')).toHaveAttribute(
|
|
816
|
+
'aria-labelledby',
|
|
817
|
+
'chatbot-nav-group-Today-label'
|
|
818
|
+
);
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
it('labels each menu list in a shared static menu with its group title id', () => {
|
|
822
|
+
const groups: ConversationGroup[] = [
|
|
823
|
+
{
|
|
824
|
+
id: 'pinned',
|
|
825
|
+
label: 'Pinned chats',
|
|
826
|
+
items: initialConversations
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
id: 'recent',
|
|
830
|
+
label: 'Recent chats',
|
|
831
|
+
items: [{ id: '2', text: 'Chatbot extension' }]
|
|
832
|
+
}
|
|
833
|
+
];
|
|
834
|
+
|
|
835
|
+
render(
|
|
836
|
+
<ChatbotConversationHistoryNav
|
|
837
|
+
onDrawerToggle={onDrawerToggle}
|
|
838
|
+
isDrawerOpen={true}
|
|
839
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
840
|
+
setIsDrawerOpen={jest.fn()}
|
|
841
|
+
conversations={groups}
|
|
842
|
+
/>
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
expect(screen.getByRole('menu', { name: 'Pinned chats' })).toHaveAttribute(
|
|
846
|
+
'aria-labelledby',
|
|
847
|
+
'chatbot-nav-group-pinned-label'
|
|
848
|
+
);
|
|
849
|
+
expect(screen.getByRole('menu', { name: 'Recent chats' })).toHaveAttribute(
|
|
850
|
+
'aria-labelledby',
|
|
851
|
+
'chatbot-nav-group-recent-label'
|
|
852
|
+
);
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
it('does not autofocus the first menu item when an expandable group is expanded', async () => {
|
|
856
|
+
const ExpandableGroupDemo = () => {
|
|
857
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
858
|
+
|
|
859
|
+
return (
|
|
860
|
+
<ChatbotConversationHistoryNav
|
|
861
|
+
onDrawerToggle={onDrawerToggle}
|
|
862
|
+
isDrawerOpen={true}
|
|
863
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
864
|
+
setIsDrawerOpen={jest.fn()}
|
|
865
|
+
conversations={[
|
|
866
|
+
{
|
|
867
|
+
id: 'saved-prompts',
|
|
868
|
+
label: 'Saved prompts',
|
|
869
|
+
expandable: {
|
|
870
|
+
isExpanded,
|
|
871
|
+
onToggle: setIsExpanded
|
|
872
|
+
},
|
|
873
|
+
items: [
|
|
874
|
+
{ id: '7', text: 'Summarize this document' },
|
|
875
|
+
{ id: '8', text: 'Draft a release announcement' }
|
|
876
|
+
]
|
|
877
|
+
}
|
|
878
|
+
]}
|
|
879
|
+
/>
|
|
880
|
+
);
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
render(<ExpandableGroupDemo />);
|
|
884
|
+
|
|
885
|
+
fireEvent.click(screen.getByRole('button', { name: 'Saved prompts' }));
|
|
886
|
+
|
|
887
|
+
await waitFor(() => {
|
|
888
|
+
expect(screen.getByRole('menuitem', { name: 'Summarize this document' })).toBeInTheDocument();
|
|
889
|
+
});
|
|
890
|
+
expect(screen.getByRole('menuitem', { name: 'Summarize this document' })).not.toHaveFocus();
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
it('does not render a collapsed expandable group menu', () => {
|
|
894
|
+
const groups: ConversationGroup[] = [
|
|
895
|
+
{
|
|
896
|
+
id: 'chats',
|
|
897
|
+
label: 'Chats',
|
|
898
|
+
items: [
|
|
899
|
+
{ id: '2', text: 'Chat two' },
|
|
900
|
+
{ id: '3', text: 'Chat three' }
|
|
901
|
+
]
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
id: 'saved-prompts',
|
|
905
|
+
label: 'Saved prompts',
|
|
906
|
+
expandable: {
|
|
907
|
+
isExpanded: false,
|
|
908
|
+
onToggle: jest.fn()
|
|
909
|
+
},
|
|
910
|
+
items: [
|
|
911
|
+
{ id: '7', text: 'Summarize this document' },
|
|
912
|
+
{ id: '8', text: 'Draft a release announcement' }
|
|
913
|
+
]
|
|
914
|
+
}
|
|
915
|
+
];
|
|
916
|
+
|
|
917
|
+
render(
|
|
918
|
+
<ChatbotConversationHistoryNav
|
|
919
|
+
onDrawerToggle={onDrawerToggle}
|
|
920
|
+
isDrawerOpen={true}
|
|
921
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
922
|
+
setIsDrawerOpen={jest.fn()}
|
|
923
|
+
conversations={groups}
|
|
924
|
+
/>
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
// Collapsed expandable groups render their toggle outside the menu and omit the menu
|
|
928
|
+
// entirely until expanded, so their items are not part of arrow-key navigation.
|
|
929
|
+
expect(screen.getAllByRole('menu')).toHaveLength(1);
|
|
930
|
+
expect(screen.getByRole('menu', { name: 'Chats' })).toHaveAttribute(
|
|
931
|
+
'aria-labelledby',
|
|
932
|
+
'chatbot-nav-group-chats-label'
|
|
933
|
+
);
|
|
934
|
+
expect(screen.queryByRole('menuitem', { name: 'Summarize this document' })).not.toBeInTheDocument();
|
|
935
|
+
expect(screen.queryByRole('menuitem', { name: 'Draft a release announcement' })).not.toBeInTheDocument();
|
|
936
|
+
|
|
937
|
+
const firstItem = screen.getByRole('menuitem', { name: 'Chat two' });
|
|
938
|
+
const lastItem = screen.getByRole('menuitem', { name: 'Chat three' });
|
|
939
|
+
|
|
940
|
+
lastItem.focus();
|
|
941
|
+
fireEvent.keyDown(lastItem, { key: 'ArrowDown' });
|
|
942
|
+
|
|
943
|
+
expect(firstItem).toHaveFocus();
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
it('collapses and expands a group when expandable.onToggle is called', async () => {
|
|
947
|
+
const onToggle = jest.fn();
|
|
948
|
+
const groups: ConversationGroup[] = [
|
|
949
|
+
{
|
|
950
|
+
id: 'chats',
|
|
951
|
+
label: 'Chats',
|
|
952
|
+
expandable: {
|
|
953
|
+
isExpanded: true,
|
|
954
|
+
onToggle
|
|
955
|
+
},
|
|
956
|
+
items: [{ id: '2', text: 'Chatbot extension' }]
|
|
957
|
+
}
|
|
958
|
+
];
|
|
959
|
+
|
|
960
|
+
const { rerender } = render(
|
|
961
|
+
<ChatbotConversationHistoryNav
|
|
962
|
+
onDrawerToggle={onDrawerToggle}
|
|
963
|
+
isDrawerOpen={true}
|
|
964
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
965
|
+
setIsDrawerOpen={jest.fn()}
|
|
966
|
+
conversations={groups}
|
|
967
|
+
/>
|
|
968
|
+
);
|
|
969
|
+
|
|
970
|
+
expect(screen.getByRole('menuitem', { name: /Chatbot extension/i })).toBeInTheDocument();
|
|
971
|
+
|
|
972
|
+
fireEvent.click(screen.getByRole('button', { name: 'Chats' }));
|
|
973
|
+
expect(onToggle).toHaveBeenCalledWith(false);
|
|
974
|
+
|
|
975
|
+
rerender(
|
|
976
|
+
<ChatbotConversationHistoryNav
|
|
977
|
+
onDrawerToggle={onDrawerToggle}
|
|
978
|
+
isDrawerOpen={true}
|
|
979
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
980
|
+
setIsDrawerOpen={jest.fn()}
|
|
981
|
+
conversations={[
|
|
982
|
+
{
|
|
983
|
+
...groups[0],
|
|
984
|
+
expandable: {
|
|
985
|
+
isExpanded: false,
|
|
986
|
+
onToggle
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
]}
|
|
990
|
+
/>
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
await waitFor(() => {
|
|
994
|
+
expect(screen.queryByRole('menuitem', { name: /Chatbot extension/i })).not.toBeInTheDocument();
|
|
995
|
+
});
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
it('renders custom menu items and footers supplied in ConversationGroup', () => {
|
|
999
|
+
const groups: ConversationGroup[] = [
|
|
1000
|
+
{
|
|
1001
|
+
id: 'chats',
|
|
1002
|
+
label: 'Chats',
|
|
1003
|
+
items: [
|
|
1004
|
+
initialConversations[0],
|
|
1005
|
+
<MenuItem key="show-all" itemId="show-all">
|
|
1006
|
+
Show all
|
|
1007
|
+
</MenuItem>
|
|
1008
|
+
],
|
|
1009
|
+
footer: <div data-testid="group-footer">Footer content</div>
|
|
1010
|
+
}
|
|
1011
|
+
];
|
|
1012
|
+
|
|
1013
|
+
render(
|
|
1014
|
+
<ChatbotConversationHistoryNav
|
|
1015
|
+
onDrawerToggle={onDrawerToggle}
|
|
1016
|
+
isDrawerOpen={true}
|
|
1017
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
1018
|
+
setIsDrawerOpen={jest.fn()}
|
|
1019
|
+
conversations={groups}
|
|
1020
|
+
/>
|
|
1021
|
+
);
|
|
1022
|
+
|
|
1023
|
+
expect(screen.getByRole('menuitem', { name: 'Show all' })).toBeInTheDocument();
|
|
1024
|
+
expect(screen.getByTestId('group-footer')).toBeInTheDocument();
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
it('moves focus to the first overflow item when show all is expanded', async () => {
|
|
1028
|
+
const recentChats: Conversation[] = [
|
|
1029
|
+
{ id: '2', text: 'Chat two' },
|
|
1030
|
+
{ id: '3', text: 'Chat three' },
|
|
1031
|
+
{ id: '4', text: 'Chat four' },
|
|
1032
|
+
{ id: '5', text: 'Chat five' },
|
|
1033
|
+
{ id: '6', text: 'Chat six' }
|
|
1034
|
+
];
|
|
1035
|
+
const VISIBLE_CHAT_COUNT = 3;
|
|
1036
|
+
|
|
1037
|
+
const ShowAllDemo = () => {
|
|
1038
|
+
const [isShowingAllChats, setIsShowingAllChats] = useState(false);
|
|
1039
|
+
|
|
1040
|
+
return (
|
|
1041
|
+
<ChatbotConversationHistoryNav
|
|
1042
|
+
onDrawerToggle={onDrawerToggle}
|
|
1043
|
+
isDrawerOpen={true}
|
|
1044
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
1045
|
+
setIsDrawerOpen={jest.fn()}
|
|
1046
|
+
conversations={[
|
|
1047
|
+
{
|
|
1048
|
+
id: 'chats',
|
|
1049
|
+
label: 'Chats',
|
|
1050
|
+
items: recentChats,
|
|
1051
|
+
showAll: {
|
|
1052
|
+
visibleCount: VISIBLE_CHAT_COUNT,
|
|
1053
|
+
isExpanded: isShowingAllChats,
|
|
1054
|
+
onToggle: setIsShowingAllChats
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
]}
|
|
1058
|
+
/>
|
|
1059
|
+
);
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
render(<ShowAllDemo />);
|
|
1063
|
+
|
|
1064
|
+
fireEvent.click(screen.getByRole('menuitem', { name: /Show all/i }));
|
|
1065
|
+
|
|
1066
|
+
await waitFor(() => {
|
|
1067
|
+
expect(screen.getByRole('menuitem', { name: 'Chat five' })).toHaveFocus();
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
it('keeps focus on the toggle when show all is collapsed', async () => {
|
|
1072
|
+
const recentChats: Conversation[] = [
|
|
1073
|
+
{ id: '2', text: 'Chat two' },
|
|
1074
|
+
{ id: '3', text: 'Chat three' },
|
|
1075
|
+
{ id: '4', text: 'Chat four' },
|
|
1076
|
+
{ id: '5', text: 'Chat five' }
|
|
1077
|
+
];
|
|
1078
|
+
|
|
1079
|
+
const ShowAllDemo = () => {
|
|
1080
|
+
const [isShowingAllChats, setIsShowingAllChats] = useState(true);
|
|
1081
|
+
|
|
1082
|
+
return (
|
|
1083
|
+
<ChatbotConversationHistoryNav
|
|
1084
|
+
onDrawerToggle={onDrawerToggle}
|
|
1085
|
+
isDrawerOpen={true}
|
|
1086
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
1087
|
+
setIsDrawerOpen={jest.fn()}
|
|
1088
|
+
conversations={[
|
|
1089
|
+
{
|
|
1090
|
+
id: 'chats',
|
|
1091
|
+
label: 'Chats',
|
|
1092
|
+
items: recentChats,
|
|
1093
|
+
showAll: {
|
|
1094
|
+
visibleCount: 2,
|
|
1095
|
+
isExpanded: isShowingAllChats,
|
|
1096
|
+
onToggle: setIsShowingAllChats
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
]}
|
|
1100
|
+
/>
|
|
1101
|
+
);
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
render(<ShowAllDemo />);
|
|
1105
|
+
|
|
1106
|
+
fireEvent.click(screen.getByRole('menuitem', { name: 'Show less' }));
|
|
1107
|
+
|
|
1108
|
+
await waitFor(() => {
|
|
1109
|
+
expect(screen.getByRole('menuitem', { name: /Show all/i })).toHaveFocus();
|
|
1110
|
+
});
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
it('renders overflow items above the show all toggle so it stays in a fixed position', () => {
|
|
1114
|
+
const recentChats: Conversation[] = [
|
|
1115
|
+
{ id: '2', text: 'Chat two' },
|
|
1116
|
+
{ id: '3', text: 'Chat three' },
|
|
1117
|
+
{ id: '4', text: 'Chat four' }
|
|
1118
|
+
];
|
|
1119
|
+
|
|
1120
|
+
render(
|
|
1121
|
+
<ChatbotConversationHistoryNav
|
|
1122
|
+
onDrawerToggle={onDrawerToggle}
|
|
1123
|
+
isDrawerOpen={true}
|
|
1124
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
1125
|
+
setIsDrawerOpen={jest.fn()}
|
|
1126
|
+
conversations={[
|
|
1127
|
+
{
|
|
1128
|
+
id: 'chats',
|
|
1129
|
+
label: 'Chats',
|
|
1130
|
+
items: recentChats,
|
|
1131
|
+
showAll: {
|
|
1132
|
+
visibleCount: 1,
|
|
1133
|
+
isExpanded: true,
|
|
1134
|
+
onToggle: jest.fn()
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
]}
|
|
1138
|
+
/>
|
|
1139
|
+
);
|
|
1140
|
+
|
|
1141
|
+
const overflowItem = screen.getByRole('menuitem', { name: 'Chat four' });
|
|
1142
|
+
const toggle = screen.getByRole('menuitem', { name: 'Show less' });
|
|
1143
|
+
const isToggleAfterOverflowItem = Boolean(
|
|
1144
|
+
// eslint-disable-next-line no-bitwise
|
|
1145
|
+
overflowItem.compareDocumentPosition(toggle) & Node.DOCUMENT_POSITION_FOLLOWING
|
|
1146
|
+
);
|
|
1147
|
+
|
|
1148
|
+
expect(isToggleAfterOverflowItem).toBe(true);
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
it('allows arrow key navigation to flow through the show all toggle like any other menu item', async () => {
|
|
1152
|
+
const recentChats: Conversation[] = [
|
|
1153
|
+
{ id: '2', text: 'Chat two' },
|
|
1154
|
+
{ id: '3', text: 'Chat three' },
|
|
1155
|
+
{ id: '4', text: 'Chat four' }
|
|
1156
|
+
];
|
|
1157
|
+
|
|
1158
|
+
render(
|
|
1159
|
+
<ChatbotConversationHistoryNav
|
|
1160
|
+
onDrawerToggle={onDrawerToggle}
|
|
1161
|
+
isDrawerOpen={true}
|
|
1162
|
+
displayMode={ChatbotDisplayMode.embedded}
|
|
1163
|
+
setIsDrawerOpen={jest.fn()}
|
|
1164
|
+
conversations={[
|
|
1165
|
+
{
|
|
1166
|
+
id: 'chats',
|
|
1167
|
+
label: 'Chats',
|
|
1168
|
+
items: recentChats,
|
|
1169
|
+
showAll: {
|
|
1170
|
+
visibleCount: 2,
|
|
1171
|
+
isExpanded: false,
|
|
1172
|
+
onToggle: jest.fn()
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
]}
|
|
1176
|
+
/>
|
|
1177
|
+
);
|
|
1178
|
+
|
|
1179
|
+
const lastVisibleItem = screen.getByRole('menuitem', { name: 'Chat three' });
|
|
1180
|
+
const toggle = screen.getByRole('menuitem', { name: /Show all/i });
|
|
1181
|
+
|
|
1182
|
+
lastVisibleItem.focus();
|
|
1183
|
+
fireEvent.keyDown(lastVisibleItem, { key: 'ArrowDown' });
|
|
1184
|
+
|
|
1185
|
+
await waitFor(() => {
|
|
1186
|
+
expect(toggle).toHaveFocus();
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
fireEvent.keyDown(toggle, { key: 'ArrowUp' });
|
|
1190
|
+
|
|
1191
|
+
await waitFor(() => {
|
|
1192
|
+
expect(lastVisibleItem).toHaveFocus();
|
|
1193
|
+
});
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1196
|
+
it('preserves custom menu item identity when preceding items change', () => {
|
|
1197
|
+
const renderShowAll = () => (
|
|
1198
|
+
<MenuItem key="show-all-chats" itemId="show-all-chats">
|
|
1199
|
+
Show all
|
|
1200
|
+
</MenuItem>
|
|
1201
|
+
);
|
|
1202
|
+
|
|
1203
|
+
const { rerender } = render(
|
|
1204
|
+
<ChatbotConversationHistoryNav
|
|
1205
|
+
onDrawerToggle={onDrawerToggle}
|
|
1206
|
+
isDrawerOpen={true}
|
|
1207
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
1208
|
+
setIsDrawerOpen={jest.fn()}
|
|
1209
|
+
conversations={[
|
|
1210
|
+
{
|
|
1211
|
+
id: 'chats',
|
|
1212
|
+
label: 'Chats',
|
|
1213
|
+
items: [initialConversations[0], renderShowAll()]
|
|
1214
|
+
}
|
|
1215
|
+
]}
|
|
1216
|
+
/>
|
|
1217
|
+
);
|
|
1218
|
+
|
|
1219
|
+
const showAllBefore = screen.getByRole('menuitem', { name: 'Show all' });
|
|
1220
|
+
|
|
1221
|
+
rerender(
|
|
1222
|
+
<ChatbotConversationHistoryNav
|
|
1223
|
+
onDrawerToggle={onDrawerToggle}
|
|
1224
|
+
isDrawerOpen={true}
|
|
1225
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
1226
|
+
setIsDrawerOpen={jest.fn()}
|
|
1227
|
+
conversations={[
|
|
1228
|
+
{
|
|
1229
|
+
id: 'chats',
|
|
1230
|
+
label: 'Chats',
|
|
1231
|
+
items: [initialConversations[0], initialConversations[1], initialConversations[2], renderShowAll()]
|
|
1232
|
+
}
|
|
1233
|
+
]}
|
|
1234
|
+
/>
|
|
1235
|
+
);
|
|
1236
|
+
|
|
1237
|
+
expect(screen.getByRole('menuitem', { name: 'Show all' })).toBe(showAllBefore);
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1240
|
+
it('passes expandableSectionProps from expandable ConversationGroup', () => {
|
|
1241
|
+
const groups: ConversationGroup[] = [
|
|
1242
|
+
{
|
|
1243
|
+
id: 'saved',
|
|
1244
|
+
label: 'Saved prompts',
|
|
1245
|
+
expandable: {
|
|
1246
|
+
isExpanded: true,
|
|
1247
|
+
onToggle: jest.fn(),
|
|
1248
|
+
expandableSectionProps: { className: 'test-expandable-section' }
|
|
1249
|
+
},
|
|
1250
|
+
items: initialConversations
|
|
1251
|
+
}
|
|
1252
|
+
];
|
|
1253
|
+
|
|
1254
|
+
render(
|
|
1255
|
+
<ChatbotConversationHistoryNav
|
|
1256
|
+
onDrawerToggle={onDrawerToggle}
|
|
1257
|
+
isDrawerOpen={true}
|
|
1258
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
1259
|
+
setIsDrawerOpen={jest.fn()}
|
|
1260
|
+
conversations={groups}
|
|
1261
|
+
/>
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
expect(document.querySelector('.test-expandable-section')).toBeInTheDocument();
|
|
1265
|
+
});
|
|
718
1266
|
});
|