diff --git a/client/src/components/Conversations/Conversations.tsx b/client/src/components/Conversations/Conversations.tsx index 99ca08b799..941dd848d2 100644 --- a/client/src/components/Conversations/Conversations.tsx +++ b/client/src/components/Conversations/Conversations.tsx @@ -41,7 +41,8 @@ const Conversations = ({ paddingLeft: '10px', }} > - {localize(groupName) ?? groupName} + {/* eslint-disable-next-line @typescript-eslint/strict-boolean-expressions */} + {localize(groupName) || groupName} {convos.map((convo, i) => ( { + const actual = jest.requireActual('date-fns'); + return { + ...actual, + startOfToday: jest.fn(() => new Date('2023-07-15T00:00:00Z')), + }; +}); + describe('Conversation Utilities', () => { describe('groupConversationsByDate', () => { it('groups conversations by date correctly', () => { @@ -35,6 +43,66 @@ describe('Conversation Utilities', () => { expect(grouped[4][1]).toHaveLength(1); }); + it('groups conversations correctly across multiple years', () => { + const fixedDate = new Date('2023-07-15T12:00:00Z'); + const conversations = [ + { conversationId: '1', updatedAt: '2023-07-15T10:00:00Z' }, // Today + { conversationId: '2', updatedAt: '2023-07-14T12:00:00Z' }, // Yesterday + { conversationId: '3', updatedAt: '2023-07-08T12:00:00Z' }, // This week + { conversationId: '4', updatedAt: '2023-07-01T12:00:00Z' }, // This month (within last 30 days) + { conversationId: '5', updatedAt: '2023-06-01T12:00:00Z' }, // Last month + { conversationId: '6', updatedAt: '2023-01-01T12:00:00Z' }, // This year, January + { conversationId: '7', updatedAt: '2022-12-01T12:00:00Z' }, // Last year, December + { conversationId: '8', updatedAt: '2022-06-01T12:00:00Z' }, // Last year, June + { conversationId: '9', updatedAt: '2021-12-01T12:00:00Z' }, // Two years ago + { conversationId: '10', updatedAt: '2020-06-01T12:00:00Z' }, // Three years ago + ]; + + // Mock Date.now + const originalDateNow = Date.now; + Date.now = jest.fn(() => fixedDate.getTime()); + + const grouped = groupConversationsByDate(conversations as TConversation[]); + + // Restore Date.now + Date.now = originalDateNow; + + const expectedGroups = [ + dateKeys.today, + dateKeys.yesterday, + dateKeys.previous7Days, + dateKeys.previous30Days, + dateKeys.june, + dateKeys.january, + ' 2022', + ' 2021', + ' 2020', + ]; + + expect(grouped.map(([key]) => key)).toEqual(expectedGroups); + + // Helper function to safely get group length + const getGroupLength = (key: string) => grouped.find(([k]) => k === key)?.[1]?.length ?? 0; + + // Check specific group contents + expect(getGroupLength(dateKeys.today)).toBe(1); + expect(getGroupLength(dateKeys.yesterday)).toBe(1); + expect(getGroupLength(dateKeys.previous7Days)).toBe(1); + expect(getGroupLength(dateKeys.previous30Days)).toBe(1); + expect(getGroupLength(dateKeys.june)).toBe(1); + expect(getGroupLength(dateKeys.january)).toBe(1); + expect(getGroupLength(' 2022')).toBe(2); // December and June 2022 + expect(getGroupLength(' 2021')).toBe(1); + expect(getGroupLength(' 2020')).toBe(1); + + // Check that all conversations are accounted for + const totalGroupedConversations = grouped.reduce( + (total, [, convos]) => total + convos.length, + 0, + ); + expect(totalGroupedConversations).toBe(conversations.length); + }); + it('returns an empty array for no conversations', () => { expect(groupConversationsByDate([])).toEqual([]); }); diff --git a/client/src/utils/convos.ts b/client/src/utils/convos.ts index 5c61b905af..3f11bcbe7c 100644 --- a/client/src/utils/convos.ts +++ b/client/src/utils/convos.ts @@ -6,7 +6,6 @@ import { parseISO, startOfDay, startOfYear, - startOfToday, isWithinInterval, } from 'date-fns'; import { EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider'; @@ -40,7 +39,7 @@ export const dateKeys = { }; const getGroupName = (date: Date) => { - const now = new Date(); + const now = new Date(Date.now()); if (isToday(date)) { return dateKeys.today; } @@ -95,7 +94,7 @@ export const groupConversationsByDate = ( const seenConversationIds = new Set(); const groups = new Map(); - const today = startOfToday(); + const now = new Date(Date.now()); conversations.forEach((conversation) => { if (!conversation || seenConversationIds.has(conversation.conversationId)) { @@ -103,7 +102,13 @@ export const groupConversationsByDate = ( } seenConversationIds.add(conversation.conversationId); - const date = conversation.updatedAt ? parseISO(conversation.updatedAt) : today; + let date: Date; + if (conversation.updatedAt) { + date = parseISO(conversation.updatedAt); + } else { + date = now; + } + const groupName = getGroupName(date); if (!groups.has(groupName)) { groups.set(groupName, []);