From 210fe233dec83b2e1015e6f47905aeb2493cd9c5 Mon Sep 17 00:00:00 2001 From: dimakis Date: Fri, 15 May 2026 10:20:45 +0100 Subject: [PATCH 1/3] fix(ui): add Load More button to desktop session panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The desktop SessionPanel was not wiring up the pagination props (hasMore, loadMore, loadingMore) from useSessionList, so users could only see the first page of sessions. The mobile SessionList already had this — just needed the same treatment on desktop. Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/SessionPanel.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/SessionPanel.tsx b/frontend/src/components/SessionPanel.tsx index 2afd994d..80c491f4 100644 --- a/frontend/src/components/SessionPanel.tsx +++ b/frontend/src/components/SessionPanel.tsx @@ -23,7 +23,7 @@ function readViewMode(): ViewMode { } export function SessionPanel({ activeSessionId, onSelectSession, onNewChat }: SessionPanelProps) { - const { sessions, loading, dismissSession } = useSessionList(); + const { sessions, loading, loadingMore, hasMore, loadMore, dismissSession } = useSessionList(); const { attendCount } = useSessionOverview(); const [viewMode, setViewMode] = useState(readViewMode); @@ -99,6 +99,11 @@ export function SessionPanel({ activeSessionId, onSelectSession, onNewChat }: Se ))} + {hasMore && ( + + )} )} From 5c7028b783aa0aaf058a742a45ce2516e541806d Mon Sep 17 00:00:00 2001 From: dimakis Date: Sat, 16 May 2026 08:35:02 +0100 Subject: [PATCH 2/3] =?UTF-8?q?test(ui):=20address=20PR=20#324=20review=20?= =?UTF-8?q?=E2=80=94=20add=20Load=20More=20button=20test=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../__tests__/SessionPanel.test.tsx | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/frontend/src/components/__tests__/SessionPanel.test.tsx b/frontend/src/components/__tests__/SessionPanel.test.tsx index 877fbb91..004ce24f 100644 --- a/frontend/src/components/__tests__/SessionPanel.test.tsx +++ b/frontend/src/components/__tests__/SessionPanel.test.tsx @@ -7,6 +7,15 @@ vi.mock('../../hooks/useSessionList', () => ({ useSessionList: vi.fn(), })); +// Mock useSessionOverview to avoid EventSource dependency +vi.mock('../../hooks/useSessionOverview', () => ({ + useSessionOverview: vi.fn(() => ({ + activities: [], + attendCount: 0, + connected: false, + })), +})); + import { SessionPanel } from '../SessionPanel'; import { useSessionList } from '../../hooks/useSessionList'; @@ -32,11 +41,15 @@ function makeDefaultReturn(overrides = {}) { beforeEach(() => { mockUseSessionList.mockReturnValue(makeDefaultReturn()); + // Default to "All" view so session list tests work (the "Active" view + // renders ActiveSessionsList which is tested separately). + localStorage.setItem('mitzo-session-view-mode', 'all'); }); afterEach(() => { cleanup(); vi.clearAllMocks(); + localStorage.clear(); }); describe('SessionPanel', () => { @@ -143,4 +156,51 @@ describe('SessionPanel', () => { fireEvent.click(deleteBtn); expect(dismiss).toHaveBeenCalledWith('s1'); }); + + describe('Load More button', () => { + it('renders when hasMore is true', () => { + mockUseSessionList.mockReturnValue( + makeDefaultReturn({ + sessions: [{ id: 's1', summary: 'A session', lastModified: Date.now() }], + hasMore: true, + }), + ); + render( + , + ); + expect(screen.getByText('Load More')).toBeTruthy(); + }); + + it('shows disabled loading state when loadingMore is true', () => { + mockUseSessionList.mockReturnValue( + makeDefaultReturn({ + sessions: [{ id: 's1', summary: 'A session', lastModified: Date.now() }], + hasMore: true, + loadingMore: true, + }), + ); + render( + , + ); + const btn = screen.getByText('Loading...'); + expect(btn).toBeTruthy(); + expect((btn as HTMLButtonElement).disabled).toBe(true); + }); + + it('calls loadMore when clicked', () => { + const loadMore = vi.fn(); + mockUseSessionList.mockReturnValue( + makeDefaultReturn({ + sessions: [{ id: 's1', summary: 'A session', lastModified: Date.now() }], + hasMore: true, + loadMore, + }), + ); + render( + , + ); + fireEvent.click(screen.getByText('Load More')); + expect(loadMore).toHaveBeenCalledOnce(); + }); + }); }); From 2da5d86d04f66a470ba384ef350874b8a0dacdd9 Mon Sep 17 00:00:00 2001 From: dimakis Date: Sat, 16 May 2026 09:22:41 +0100 Subject: [PATCH 3/3] test(ui): add negative Load More test case per review Co-Authored-By: Claude Opus 4.6 --- .../src/components/__tests__/SessionPanel.test.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/src/components/__tests__/SessionPanel.test.tsx b/frontend/src/components/__tests__/SessionPanel.test.tsx index 004ce24f..f4827eb9 100644 --- a/frontend/src/components/__tests__/SessionPanel.test.tsx +++ b/frontend/src/components/__tests__/SessionPanel.test.tsx @@ -158,6 +158,19 @@ describe('SessionPanel', () => { }); describe('Load More button', () => { + it('does not render Load More when hasMore is false', () => { + mockUseSessionList.mockReturnValue( + makeDefaultReturn({ + sessions: [{ id: 's1', summary: 'A session', lastModified: Date.now() }], + hasMore: false, + }), + ); + render( + , + ); + expect(screen.queryByText('Load More')).toBeNull(); + }); + it('renders when hasMore is true', () => { mockUseSessionList.mockReturnValue( makeDefaultReturn({