From 75c7bf47f3c445f3b95ffcbeaf6e25852bb679d4 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 4 May 2026 01:47:11 +0500 Subject: [PATCH] fix(test): repair GlobalTaskList memo re-render test React.memo blocks root.render() re-renders when props are unchanged, so storeState task updates were invisible to the memoized component. Switch useStore mock to a subscription model (useState + useEffect) so notifyStoreUpdate() forces a proper re-render in the expansion test. --- .../components/sidebar/GlobalTaskList.test.ts | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/test/renderer/components/sidebar/GlobalTaskList.test.ts b/test/renderer/components/sidebar/GlobalTaskList.test.ts index 3dcacade..8bfd3436 100644 --- a/test/renderer/components/sidebar/GlobalTaskList.test.ts +++ b/test/renderer/components/sidebar/GlobalTaskList.test.ts @@ -32,12 +32,29 @@ const taskLocalState = { renameTask: vi.fn(), }; +const storeListeners = new Set<() => void>(); +function notifyStoreUpdate(): void { + storeListeners.forEach((l) => l()); +} + vi.mock('../../../../src/renderer/store', () => ({ - useStore: (selector: (state: StoreState) => unknown) => selector(storeState), + useStore: (selector: (state: StoreState) => unknown) => { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { useState, useEffect } = require('react') as typeof import('react'); + const [, setVersion] = useState(0); + useEffect(() => { + const listener = () => setVersion((v) => v + 1); + storeListeners.add(listener); + return () => { + storeListeners.delete(listener); + }; + }, []); + return selector(storeState); + }, })); vi.mock('zustand/react/shallow', () => ({ - useShallow: (selector: T) => selector, + useShallow: (selector: T) => selector, })); vi.mock('../../../../src/renderer/components/common/ConfirmDialog', () => ({ @@ -75,7 +92,8 @@ vi.mock('../../../../src/renderer/components/sidebar/TaskFiltersPopover', () => })); vi.mock('../../../../src/renderer/components/ui/popover', () => ({ - Popover: ({ children }: React.PropsWithChildren) => React.createElement(React.Fragment, null, children), + Popover: ({ children }: React.PropsWithChildren) => + React.createElement(React.Fragment, null, children), PopoverTrigger: ({ children }: React.PropsWithChildren) => React.createElement(React.Fragment, null, children), PopoverContent: ({ children }: React.PropsWithChildren) => @@ -83,7 +101,8 @@ vi.mock('../../../../src/renderer/components/ui/popover', () => ({ })); vi.mock('../../../../src/renderer/components/ui/tooltip', () => ({ - Tooltip: ({ children }: React.PropsWithChildren) => React.createElement(React.Fragment, null, children), + Tooltip: ({ children }: React.PropsWithChildren) => + React.createElement(React.Fragment, null, children), TooltipTrigger: ({ children }: React.PropsWithChildren) => React.createElement(React.Fragment, null, children), TooltipContent: ({ children }: React.PropsWithChildren) => @@ -113,9 +132,11 @@ function flushMicrotasks(): Promise { } function findButton(host: HTMLElement, label: string): HTMLButtonElement | null { - return Array.from(host.querySelectorAll('button')).find( - (button) => button.textContent?.trim() === label - ) ?? null; + return ( + Array.from(host.querySelectorAll('button')).find( + (button) => button.textContent?.trim() === label + ) ?? null + ); } function visibleSubjects(host: HTMLElement): string[] { @@ -175,6 +196,7 @@ describe('GlobalTaskList project grouping', () => { afterEach(() => { document.body.innerHTML = ''; vi.unstubAllGlobals(); + storeListeners.clear(); }); it('shows five tasks first, then expands and collapses with Show more and Show less', async () => { @@ -199,7 +221,14 @@ describe('GlobalTaskList project grouping', () => { await flushMicrotasks(); }); - expect(visibleSubjects(host)).toEqual(['Task 1', 'Task 2', 'Task 3', 'Task 4', 'Task 5', 'Task 6']); + expect(visibleSubjects(host)).toEqual([ + 'Task 1', + 'Task 2', + 'Task 3', + 'Task 4', + 'Task 5', + 'Task 6', + ]); expect(findButton(host, 'Show less')).not.toBeNull(); await act(async () => { @@ -249,7 +278,7 @@ describe('GlobalTaskList project grouping', () => { ]; await act(async () => { - root.render(React.createElement(GlobalTaskList)); + notifyStoreUpdate(); await flushMicrotasks(); });