@google/gemini-cli 0.12.0-preview.4 → 0.13.0-nightly.20251031.c89bc30d
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/google-gemini-cli-0.13.0-nightly.20251029.cca41edc.tgz +0 -0
- package/dist/package.json +2 -2
- package/dist/src/commands/extensions/install.js +2 -2
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +27 -16
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +2 -2
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/update.js +3 -2
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions/validate.d.ts +12 -0
- package/dist/src/commands/extensions/validate.js +83 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions/validate.test.d.ts +6 -0
- package/dist/src/commands/extensions/validate.test.js +93 -0
- package/dist/src/commands/extensions/validate.test.js.map +1 -0
- package/dist/src/commands/extensions.js +2 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/config/auth.js +0 -5
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/auth.test.js +1 -3
- package/dist/src/config/auth.test.js.map +1 -1
- package/dist/src/config/config.js +2 -1
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +6 -10
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extensions/update.d.ts +2 -2
- package/dist/src/config/extensions/update.js +28 -22
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/sandboxConfig.d.ts +1 -1
- package/dist/src/config/sandboxConfig.js +6 -3
- package/dist/src/config/sandboxConfig.js.map +1 -1
- package/dist/src/config/settings.js +2 -2
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +13 -53
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +25 -7
- package/dist/src/config/settingsSchema.js +24 -6
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +2 -0
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/gemini.js +8 -1
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +1 -0
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/nonInteractiveCli.d.ts +9 -1
- package/dist/src/nonInteractiveCli.js +16 -1
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +209 -103
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/test-utils/async.d.ts +9 -0
- package/dist/src/test-utils/async.js +29 -0
- package/dist/src/test-utils/async.js.map +1 -0
- package/dist/src/test-utils/render.d.ts +2 -1
- package/dist/src/test-utils/render.js +23 -1
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/test-utils/render.test.js +29 -4
- package/dist/src/test-utils/render.test.js.map +1 -1
- package/dist/src/ui/App.test.js +1 -1
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +33 -4
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +205 -99
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
- package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
- package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
- package/dist/src/ui/auth/AuthDialog.js +7 -3
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/auth/useAuth.d.ts +2 -0
- package/dist/src/ui/auth/useAuth.js +31 -2
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +1 -1
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
- package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
- package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +4 -0
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +4 -3
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +3 -2
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +59 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/Header.test.js +9 -5
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +5 -3
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +139 -111
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +27 -14
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +20 -10
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +11 -10
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/PrepareLabel.test.js +13 -7
- package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
- package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +438 -512
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.test.js +3 -2
- package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
- package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.js +27 -5
- package/dist/src/ui/components/messages/Todo.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.test.js +20 -8
- package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +12 -11
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
- package/dist/src/ui/components/shared/TextInput.js +38 -0
- package/dist/src/ui/components/shared/TextInput.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TextInput.test.js +242 -0
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.d.ts +8 -2
- package/dist/src/ui/components/shared/text-buffer.js +28 -13
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.js +137 -0
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
- package/dist/src/ui/components/views/ChatList.test.js +7 -4
- package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.js +1 -0
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +13 -5
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +23 -12
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +132 -252
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/SessionContext.test.js +9 -5
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +29 -7
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +47 -34
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +141 -104
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.test.js +23 -21
- package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +16 -15
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.js +9 -3
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +10 -9
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useFocus.test.js +1 -1
- package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js +7 -6
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +39 -38
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +5 -4
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.test.js +25 -11
- package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.test.js +5 -4
- package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
- package/dist/src/ui/hooks/useModelCommand.test.js +7 -4
- package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.js +46 -16
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +11 -7
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +28 -14
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +116 -109
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellHistory.test.js +25 -17
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +244 -111
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useTimer.test.js +1 -1
- package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +6 -2
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.js +6 -21
- package/dist/src/ui/hooks/vim.test.js.map +1 -1
- package/dist/src/ui/state/extensions.d.ts +1 -0
- package/dist/src/ui/state/extensions.js +1 -0
- package/dist/src/ui/state/extensions.js.map +1 -1
- package/dist/src/ui/types.d.ts +1 -0
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.js +2 -2
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.js +6 -3
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.test.js +5 -1
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
- package/dist/src/utils/commentJson.js +2 -2
- package/dist/src/utils/commentJson.js.map +1 -1
- package/dist/src/utils/commentJson.test.js +7 -6
- package/dist/src/utils/commentJson.test.js.map +1 -1
- package/dist/src/utils/version.js +6 -2
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/zed-integration/acp.js +2 -1
- package/dist/src/zed-integration/acp.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/dist/google-gemini-cli-0.12.0-preview.3.tgz +0 -0
- package/dist/src/utils/package.d.ts +0 -12
- package/dist/src/utils/package.js +0 -24
- package/dist/src/utils/package.js.map +0 -1
|
@@ -6,7 +6,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
*/
|
|
7
7
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
8
|
import { act } from 'react';
|
|
9
|
-
import { render } from '
|
|
9
|
+
import { render } from '../../test-utils/render.js';
|
|
10
|
+
import { waitFor } from '../../test-utils/async.js';
|
|
10
11
|
import { useSelectionList, } from './useSelectionList.js';
|
|
11
12
|
import { useKeypress } from './useKeypress.js';
|
|
12
13
|
vi.mock('./useKeypress.js');
|
|
@@ -51,7 +52,7 @@ describe('useSelectionList', () => {
|
|
|
51
52
|
}
|
|
52
53
|
});
|
|
53
54
|
};
|
|
54
|
-
const renderSelectionListHook = (initialProps) => {
|
|
55
|
+
const renderSelectionListHook = async (initialProps) => {
|
|
55
56
|
let hookResult;
|
|
56
57
|
function TestComponent(props) {
|
|
57
58
|
hookResult = useSelectionList(props);
|
|
@@ -64,74 +65,78 @@ describe('useSelectionList', () => {
|
|
|
64
65
|
return hookResult;
|
|
65
66
|
},
|
|
66
67
|
},
|
|
67
|
-
rerender: (newProps) =>
|
|
68
|
-
|
|
68
|
+
rerender: async (newProps) => {
|
|
69
|
+
rerender(_jsx(TestComponent, { ...initialProps, ...newProps }));
|
|
70
|
+
},
|
|
71
|
+
unmount: async () => {
|
|
72
|
+
unmount();
|
|
73
|
+
},
|
|
69
74
|
};
|
|
70
75
|
};
|
|
71
76
|
describe('Initialization', () => {
|
|
72
|
-
it('should initialize with the default index (0) if enabled', () => {
|
|
73
|
-
const { result } = renderSelectionListHook({
|
|
77
|
+
it('should initialize with the default index (0) if enabled', async () => {
|
|
78
|
+
const { result } = await renderSelectionListHook({
|
|
74
79
|
items,
|
|
75
80
|
onSelect: mockOnSelect,
|
|
76
81
|
});
|
|
77
82
|
expect(result.current.activeIndex).toBe(0);
|
|
78
83
|
});
|
|
79
|
-
it('should initialize with the provided initialIndex if enabled', () => {
|
|
80
|
-
const { result } = renderSelectionListHook({
|
|
84
|
+
it('should initialize with the provided initialIndex if enabled', async () => {
|
|
85
|
+
const { result } = await renderSelectionListHook({
|
|
81
86
|
items,
|
|
82
87
|
initialIndex: 2,
|
|
83
88
|
onSelect: mockOnSelect,
|
|
84
89
|
});
|
|
85
90
|
expect(result.current.activeIndex).toBe(2);
|
|
86
91
|
});
|
|
87
|
-
it('should handle an empty list gracefully', () => {
|
|
88
|
-
const { result } = renderSelectionListHook({
|
|
92
|
+
it('should handle an empty list gracefully', async () => {
|
|
93
|
+
const { result } = await renderSelectionListHook({
|
|
89
94
|
items: [],
|
|
90
95
|
onSelect: mockOnSelect,
|
|
91
96
|
});
|
|
92
97
|
expect(result.current.activeIndex).toBe(0);
|
|
93
98
|
});
|
|
94
|
-
it('should find the next enabled item (downwards) if initialIndex is disabled', () => {
|
|
95
|
-
const { result } = renderSelectionListHook({
|
|
99
|
+
it('should find the next enabled item (downwards) if initialIndex is disabled', async () => {
|
|
100
|
+
const { result } = await renderSelectionListHook({
|
|
96
101
|
items,
|
|
97
102
|
initialIndex: 1,
|
|
98
103
|
onSelect: mockOnSelect,
|
|
99
104
|
});
|
|
100
105
|
expect(result.current.activeIndex).toBe(2);
|
|
101
106
|
});
|
|
102
|
-
it('should wrap around to find the next enabled item if initialIndex is disabled', () => {
|
|
107
|
+
it('should wrap around to find the next enabled item if initialIndex is disabled', async () => {
|
|
103
108
|
const wrappingItems = [
|
|
104
109
|
{ value: 'A', key: 'A' },
|
|
105
110
|
{ value: 'B', disabled: true, key: 'B' },
|
|
106
111
|
{ value: 'C', disabled: true, key: 'C' },
|
|
107
112
|
];
|
|
108
|
-
const { result } = renderSelectionListHook({
|
|
113
|
+
const { result } = await renderSelectionListHook({
|
|
109
114
|
items: wrappingItems,
|
|
110
115
|
initialIndex: 2,
|
|
111
116
|
onSelect: mockOnSelect,
|
|
112
117
|
});
|
|
113
118
|
expect(result.current.activeIndex).toBe(0);
|
|
114
119
|
});
|
|
115
|
-
it('should default to 0 if initialIndex is out of bounds', () => {
|
|
116
|
-
const { result } = renderSelectionListHook({
|
|
120
|
+
it('should default to 0 if initialIndex is out of bounds', async () => {
|
|
121
|
+
const { result } = await renderSelectionListHook({
|
|
117
122
|
items,
|
|
118
123
|
initialIndex: 10,
|
|
119
124
|
onSelect: mockOnSelect,
|
|
120
125
|
});
|
|
121
126
|
expect(result.current.activeIndex).toBe(0);
|
|
122
|
-
const { result: resultNeg } = renderSelectionListHook({
|
|
127
|
+
const { result: resultNeg } = await renderSelectionListHook({
|
|
123
128
|
items,
|
|
124
129
|
initialIndex: -1,
|
|
125
130
|
onSelect: mockOnSelect,
|
|
126
131
|
});
|
|
127
132
|
expect(resultNeg.current.activeIndex).toBe(0);
|
|
128
133
|
});
|
|
129
|
-
it('should stick to the initial index if all items are disabled', () => {
|
|
134
|
+
it('should stick to the initial index if all items are disabled', async () => {
|
|
130
135
|
const allDisabled = [
|
|
131
136
|
{ value: 'A', disabled: true, key: 'A' },
|
|
132
137
|
{ value: 'B', disabled: true, key: 'B' },
|
|
133
138
|
];
|
|
134
|
-
const { result } = renderSelectionListHook({
|
|
139
|
+
const { result } = await renderSelectionListHook({
|
|
135
140
|
items: allDisabled,
|
|
136
141
|
initialIndex: 1,
|
|
137
142
|
onSelect: mockOnSelect,
|
|
@@ -140,8 +145,8 @@ describe('useSelectionList', () => {
|
|
|
140
145
|
});
|
|
141
146
|
});
|
|
142
147
|
describe('Keyboard Navigation (Up/Down/J/K)', () => {
|
|
143
|
-
it('should move down with "j" and "down" keys, skipping disabled items', () => {
|
|
144
|
-
const { result } = renderSelectionListHook({
|
|
148
|
+
it('should move down with "j" and "down" keys, skipping disabled items', async () => {
|
|
149
|
+
const { result } = await renderSelectionListHook({
|
|
145
150
|
items,
|
|
146
151
|
onSelect: mockOnSelect,
|
|
147
152
|
});
|
|
@@ -151,8 +156,8 @@ describe('useSelectionList', () => {
|
|
|
151
156
|
pressKey('down');
|
|
152
157
|
expect(result.current.activeIndex).toBe(3);
|
|
153
158
|
});
|
|
154
|
-
it('should move up with "k" and "up" keys, skipping disabled items', () => {
|
|
155
|
-
const { result } = renderSelectionListHook({
|
|
159
|
+
it('should move up with "k" and "up" keys, skipping disabled items', async () => {
|
|
160
|
+
const { result } = await renderSelectionListHook({
|
|
156
161
|
items,
|
|
157
162
|
initialIndex: 3,
|
|
158
163
|
onSelect: mockOnSelect,
|
|
@@ -163,8 +168,8 @@ describe('useSelectionList', () => {
|
|
|
163
168
|
pressKey('up');
|
|
164
169
|
expect(result.current.activeIndex).toBe(0);
|
|
165
170
|
});
|
|
166
|
-
it('should wrap navigation correctly', () => {
|
|
167
|
-
const { result } = renderSelectionListHook({
|
|
171
|
+
it('should wrap navigation correctly', async () => {
|
|
172
|
+
const { result } = await renderSelectionListHook({
|
|
168
173
|
items,
|
|
169
174
|
initialIndex: items.length - 1,
|
|
170
175
|
onSelect: mockOnSelect,
|
|
@@ -175,8 +180,8 @@ describe('useSelectionList', () => {
|
|
|
175
180
|
pressKey('up');
|
|
176
181
|
expect(result.current.activeIndex).toBe(3);
|
|
177
182
|
});
|
|
178
|
-
it('should call onHighlight when index changes', () => {
|
|
179
|
-
renderSelectionListHook({
|
|
183
|
+
it('should call onHighlight when index changes', async () => {
|
|
184
|
+
await renderSelectionListHook({
|
|
180
185
|
items,
|
|
181
186
|
onSelect: mockOnSelect,
|
|
182
187
|
onHighlight: mockOnHighlight,
|
|
@@ -185,9 +190,9 @@ describe('useSelectionList', () => {
|
|
|
185
190
|
expect(mockOnHighlight).toHaveBeenCalledTimes(1);
|
|
186
191
|
expect(mockOnHighlight).toHaveBeenCalledWith('C');
|
|
187
192
|
});
|
|
188
|
-
it('should not move or call onHighlight if navigation results in the same index (e.g., single item)', () => {
|
|
193
|
+
it('should not move or call onHighlight if navigation results in the same index (e.g., single item)', async () => {
|
|
189
194
|
const singleItem = [{ value: 'A', key: 'A' }];
|
|
190
|
-
const { result } = renderSelectionListHook({
|
|
195
|
+
const { result } = await renderSelectionListHook({
|
|
191
196
|
items: singleItem,
|
|
192
197
|
onSelect: mockOnSelect,
|
|
193
198
|
onHighlight: mockOnHighlight,
|
|
@@ -196,12 +201,12 @@ describe('useSelectionList', () => {
|
|
|
196
201
|
expect(result.current.activeIndex).toBe(0);
|
|
197
202
|
expect(mockOnHighlight).not.toHaveBeenCalled();
|
|
198
203
|
});
|
|
199
|
-
it('should not move or call onHighlight if all items are disabled', () => {
|
|
204
|
+
it('should not move or call onHighlight if all items are disabled', async () => {
|
|
200
205
|
const allDisabled = [
|
|
201
206
|
{ value: 'A', disabled: true, key: 'A' },
|
|
202
207
|
{ value: 'B', disabled: true, key: 'B' },
|
|
203
208
|
];
|
|
204
|
-
const { result } = renderSelectionListHook({
|
|
209
|
+
const { result } = await renderSelectionListHook({
|
|
205
210
|
items: allDisabled,
|
|
206
211
|
onSelect: mockOnSelect,
|
|
207
212
|
onHighlight: mockOnHighlight,
|
|
@@ -213,8 +218,8 @@ describe('useSelectionList', () => {
|
|
|
213
218
|
});
|
|
214
219
|
});
|
|
215
220
|
describe('Selection (Enter)', () => {
|
|
216
|
-
it('should call onSelect when "return" is pressed on enabled item', () => {
|
|
217
|
-
renderSelectionListHook({
|
|
221
|
+
it('should call onSelect when "return" is pressed on enabled item', async () => {
|
|
222
|
+
await renderSelectionListHook({
|
|
218
223
|
items,
|
|
219
224
|
initialIndex: 2,
|
|
220
225
|
onSelect: mockOnSelect,
|
|
@@ -223,8 +228,8 @@ describe('useSelectionList', () => {
|
|
|
223
228
|
expect(mockOnSelect).toHaveBeenCalledTimes(1);
|
|
224
229
|
expect(mockOnSelect).toHaveBeenCalledWith('C');
|
|
225
230
|
});
|
|
226
|
-
it('should not call onSelect if the active item is disabled', () => {
|
|
227
|
-
const { result } = renderSelectionListHook({
|
|
231
|
+
it('should not call onSelect if the active item is disabled', async () => {
|
|
232
|
+
const { result } = await renderSelectionListHook({
|
|
228
233
|
items,
|
|
229
234
|
onSelect: mockOnSelect,
|
|
230
235
|
});
|
|
@@ -234,8 +239,8 @@ describe('useSelectionList', () => {
|
|
|
234
239
|
});
|
|
235
240
|
});
|
|
236
241
|
describe('Keyboard Navigation Robustness (Rapid Input)', () => {
|
|
237
|
-
it('should handle rapid navigation and selection robustly (avoiding stale state)', () => {
|
|
238
|
-
const { result } = renderSelectionListHook({
|
|
242
|
+
it('should handle rapid navigation and selection robustly (avoiding stale state)', async () => {
|
|
243
|
+
const { result } = await renderSelectionListHook({
|
|
239
244
|
items, // A, B(disabled), C, D. Initial index 0 (A).
|
|
240
245
|
onSelect: mockOnSelect,
|
|
241
246
|
onHighlight: mockOnHighlight,
|
|
@@ -275,8 +280,8 @@ describe('useSelectionList', () => {
|
|
|
275
280
|
expect(mockOnSelect).toHaveBeenCalledWith('D');
|
|
276
281
|
expect(mockOnSelect).not.toHaveBeenCalledWith('A');
|
|
277
282
|
});
|
|
278
|
-
it('should handle ultra-rapid input (multiple presses in single act) without stale state', () => {
|
|
279
|
-
const { result } = renderSelectionListHook({
|
|
283
|
+
it('should handle ultra-rapid input (multiple presses in single act) without stale state', async () => {
|
|
284
|
+
const { result } = await renderSelectionListHook({
|
|
280
285
|
items, // A, B(disabled), C, D. Initial index 0 (A).
|
|
281
286
|
onSelect: mockOnSelect,
|
|
282
287
|
onHighlight: mockOnHighlight,
|
|
@@ -309,8 +314,8 @@ describe('useSelectionList', () => {
|
|
|
309
314
|
});
|
|
310
315
|
});
|
|
311
316
|
describe('Focus Management (isFocused)', () => {
|
|
312
|
-
it('should activate the keypress handler when focused (default) and items exist', () => {
|
|
313
|
-
const { result } = renderSelectionListHook({
|
|
317
|
+
it('should activate the keypress handler when focused (default) and items exist', async () => {
|
|
318
|
+
const { result } = await renderSelectionListHook({
|
|
314
319
|
items,
|
|
315
320
|
onSelect: mockOnSelect,
|
|
316
321
|
});
|
|
@@ -318,8 +323,8 @@ describe('useSelectionList', () => {
|
|
|
318
323
|
pressKey('down');
|
|
319
324
|
expect(result.current.activeIndex).toBe(2);
|
|
320
325
|
});
|
|
321
|
-
it('should not activate the keypress handler when isFocused is false', () => {
|
|
322
|
-
renderSelectionListHook({
|
|
326
|
+
it('should not activate the keypress handler when isFocused is false', async () => {
|
|
327
|
+
await renderSelectionListHook({
|
|
323
328
|
items,
|
|
324
329
|
onSelect: mockOnSelect,
|
|
325
330
|
isFocused: false,
|
|
@@ -327,8 +332,8 @@ describe('useSelectionList', () => {
|
|
|
327
332
|
expect(activeKeypressHandler).toBeNull();
|
|
328
333
|
expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
|
|
329
334
|
});
|
|
330
|
-
it('should not activate the keypress handler when items list is empty', () => {
|
|
331
|
-
renderSelectionListHook({
|
|
335
|
+
it('should not activate the keypress handler when items list is empty', async () => {
|
|
336
|
+
await renderSelectionListHook({
|
|
332
337
|
items: [],
|
|
333
338
|
onSelect: mockOnSelect,
|
|
334
339
|
isFocused: true,
|
|
@@ -336,18 +341,18 @@ describe('useSelectionList', () => {
|
|
|
336
341
|
expect(activeKeypressHandler).toBeNull();
|
|
337
342
|
expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
|
|
338
343
|
});
|
|
339
|
-
it('should activate/deactivate when isFocused prop changes', () => {
|
|
340
|
-
const { result, rerender } = renderSelectionListHook({
|
|
344
|
+
it('should activate/deactivate when isFocused prop changes', async () => {
|
|
345
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
341
346
|
items,
|
|
342
347
|
onSelect: mockOnSelect,
|
|
343
348
|
isFocused: false,
|
|
344
349
|
});
|
|
345
350
|
expect(activeKeypressHandler).toBeNull();
|
|
346
|
-
rerender({ isFocused: true });
|
|
351
|
+
await rerender({ isFocused: true });
|
|
347
352
|
expect(activeKeypressHandler).not.toBeNull();
|
|
348
353
|
pressKey('down');
|
|
349
354
|
expect(result.current.activeIndex).toBe(2);
|
|
350
|
-
rerender({ isFocused: false });
|
|
355
|
+
await rerender({ isFocused: false });
|
|
351
356
|
expect(activeKeypressHandler).toBeNull();
|
|
352
357
|
expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
|
|
353
358
|
});
|
|
@@ -362,8 +367,8 @@ describe('useSelectionList', () => {
|
|
|
362
367
|
const shortList = items;
|
|
363
368
|
const longList = Array.from({ length: 15 }, (_, i) => ({ value: `Item ${i + 1}`, key: `Item ${i + 1}` }));
|
|
364
369
|
const pressNumber = (num) => pressKey(num, num);
|
|
365
|
-
it('should not respond to numbers if showNumbers is false (default)', () => {
|
|
366
|
-
const { result } = renderSelectionListHook({
|
|
370
|
+
it('should not respond to numbers if showNumbers is false (default)', async () => {
|
|
371
|
+
const { result } = await renderSelectionListHook({
|
|
367
372
|
items: shortList,
|
|
368
373
|
onSelect: mockOnSelect,
|
|
369
374
|
});
|
|
@@ -371,8 +376,8 @@ describe('useSelectionList', () => {
|
|
|
371
376
|
expect(result.current.activeIndex).toBe(0);
|
|
372
377
|
expect(mockOnSelect).not.toHaveBeenCalled();
|
|
373
378
|
});
|
|
374
|
-
it('should select item immediately if the number cannot be extended (unambiguous)', () => {
|
|
375
|
-
const { result } = renderSelectionListHook({
|
|
379
|
+
it('should select item immediately if the number cannot be extended (unambiguous)', async () => {
|
|
380
|
+
const { result } = await renderSelectionListHook({
|
|
376
381
|
items: shortList,
|
|
377
382
|
onSelect: mockOnSelect,
|
|
378
383
|
onHighlight: mockOnHighlight,
|
|
@@ -385,8 +390,8 @@ describe('useSelectionList', () => {
|
|
|
385
390
|
expect(mockOnSelect).toHaveBeenCalledWith('C');
|
|
386
391
|
expect(vi.getTimerCount()).toBe(0);
|
|
387
392
|
});
|
|
388
|
-
it('should highlight and wait for timeout if the number can be extended (ambiguous)', () => {
|
|
389
|
-
const { result } = renderSelectionListHook({
|
|
393
|
+
it('should highlight and wait for timeout if the number can be extended (ambiguous)', async () => {
|
|
394
|
+
const { result } = await renderSelectionListHook({
|
|
390
395
|
items: longList,
|
|
391
396
|
initialIndex: 1, // Start at index 1 so pressing "1" (index 0) causes a change
|
|
392
397
|
onSelect: mockOnSelect,
|
|
@@ -404,8 +409,8 @@ describe('useSelectionList', () => {
|
|
|
404
409
|
expect(mockOnSelect).toHaveBeenCalledTimes(1);
|
|
405
410
|
expect(mockOnSelect).toHaveBeenCalledWith('Item 1');
|
|
406
411
|
});
|
|
407
|
-
it('should handle multi-digit input correctly', () => {
|
|
408
|
-
const { result } = renderSelectionListHook({
|
|
412
|
+
it('should handle multi-digit input correctly', async () => {
|
|
413
|
+
const { result } = await renderSelectionListHook({
|
|
409
414
|
items: longList,
|
|
410
415
|
onSelect: mockOnSelect,
|
|
411
416
|
showNumbers: true,
|
|
@@ -417,8 +422,8 @@ describe('useSelectionList', () => {
|
|
|
417
422
|
expect(mockOnSelect).toHaveBeenCalledTimes(1);
|
|
418
423
|
expect(mockOnSelect).toHaveBeenCalledWith('Item 12');
|
|
419
424
|
});
|
|
420
|
-
it('should reset buffer if input becomes invalid (out of bounds)', () => {
|
|
421
|
-
const { result } = renderSelectionListHook({
|
|
425
|
+
it('should reset buffer if input becomes invalid (out of bounds)', async () => {
|
|
426
|
+
const { result } = await renderSelectionListHook({
|
|
422
427
|
items: shortList,
|
|
423
428
|
onSelect: mockOnSelect,
|
|
424
429
|
showNumbers: true,
|
|
@@ -430,8 +435,8 @@ describe('useSelectionList', () => {
|
|
|
430
435
|
expect(result.current.activeIndex).toBe(2);
|
|
431
436
|
expect(mockOnSelect).toHaveBeenCalledWith('C');
|
|
432
437
|
});
|
|
433
|
-
it('should allow "0" as subsequent digit, but ignore as first digit', () => {
|
|
434
|
-
const { result } = renderSelectionListHook({
|
|
438
|
+
it('should allow "0" as subsequent digit, but ignore as first digit', async () => {
|
|
439
|
+
const { result } = await renderSelectionListHook({
|
|
435
440
|
items: longList,
|
|
436
441
|
onSelect: mockOnSelect,
|
|
437
442
|
showNumbers: true,
|
|
@@ -447,8 +452,8 @@ describe('useSelectionList', () => {
|
|
|
447
452
|
expect(result.current.activeIndex).toBe(9);
|
|
448
453
|
expect(mockOnSelect).toHaveBeenCalledWith('Item 10');
|
|
449
454
|
});
|
|
450
|
-
it('should clear the initial "0" input after timeout', () => {
|
|
451
|
-
renderSelectionListHook({
|
|
455
|
+
it('should clear the initial "0" input after timeout', async () => {
|
|
456
|
+
await renderSelectionListHook({
|
|
452
457
|
items: longList,
|
|
453
458
|
onSelect: mockOnSelect,
|
|
454
459
|
showNumbers: true,
|
|
@@ -460,8 +465,8 @@ describe('useSelectionList', () => {
|
|
|
460
465
|
act(() => vi.advanceTimersByTime(1000)); // Timeout '1'
|
|
461
466
|
expect(mockOnSelect).toHaveBeenCalledWith('Item 1');
|
|
462
467
|
});
|
|
463
|
-
it('should highlight but not select a disabled item (immediate selection case)', () => {
|
|
464
|
-
const { result } = renderSelectionListHook({
|
|
468
|
+
it('should highlight but not select a disabled item (immediate selection case)', async () => {
|
|
469
|
+
const { result } = await renderSelectionListHook({
|
|
465
470
|
items: shortList, // B (index 1, number 2) is disabled
|
|
466
471
|
onSelect: mockOnSelect,
|
|
467
472
|
onHighlight: mockOnHighlight,
|
|
@@ -473,13 +478,13 @@ describe('useSelectionList', () => {
|
|
|
473
478
|
// Should not select immediately, even though 20 > 4
|
|
474
479
|
expect(mockOnSelect).not.toHaveBeenCalled();
|
|
475
480
|
});
|
|
476
|
-
it('should highlight but not select a disabled item (timeout case)', () => {
|
|
481
|
+
it('should highlight but not select a disabled item (timeout case)', async () => {
|
|
477
482
|
// Create a list where the ambiguous prefix points to a disabled item
|
|
478
483
|
const disabledAmbiguousList = [
|
|
479
484
|
{ value: 'Item 1 Disabled', disabled: true, key: 'Item 1 Disabled' },
|
|
480
485
|
...longList.slice(1),
|
|
481
486
|
];
|
|
482
|
-
const { result } = renderSelectionListHook({
|
|
487
|
+
const { result } = await renderSelectionListHook({
|
|
483
488
|
items: disabledAmbiguousList,
|
|
484
489
|
onSelect: mockOnSelect,
|
|
485
490
|
showNumbers: true,
|
|
@@ -493,8 +498,8 @@ describe('useSelectionList', () => {
|
|
|
493
498
|
// Should not select after timeout
|
|
494
499
|
expect(mockOnSelect).not.toHaveBeenCalled();
|
|
495
500
|
});
|
|
496
|
-
it('should clear the number buffer if a non-numeric key (e.g., navigation) is pressed', () => {
|
|
497
|
-
const { result } = renderSelectionListHook({
|
|
501
|
+
it('should clear the number buffer if a non-numeric key (e.g., navigation) is pressed', async () => {
|
|
502
|
+
const { result } = await renderSelectionListHook({
|
|
498
503
|
items: longList,
|
|
499
504
|
onSelect: mockOnSelect,
|
|
500
505
|
showNumbers: true,
|
|
@@ -508,8 +513,8 @@ describe('useSelectionList', () => {
|
|
|
508
513
|
// Should select '3', not '13'
|
|
509
514
|
expect(result.current.activeIndex).toBe(2);
|
|
510
515
|
});
|
|
511
|
-
it('should clear the number buffer if "return" is pressed', () => {
|
|
512
|
-
renderSelectionListHook({
|
|
516
|
+
it('should clear the number buffer if "return" is pressed', async () => {
|
|
517
|
+
await renderSelectionListHook({
|
|
513
518
|
items: longList,
|
|
514
519
|
onSelect: mockOnSelect,
|
|
515
520
|
showNumbers: true,
|
|
@@ -526,18 +531,18 @@ describe('useSelectionList', () => {
|
|
|
526
531
|
});
|
|
527
532
|
describe('Reactivity (Dynamic Updates)', () => {
|
|
528
533
|
it('should update activeIndex when initialIndex prop changes', async () => {
|
|
529
|
-
const { result, rerender } = renderSelectionListHook({
|
|
534
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
530
535
|
items,
|
|
531
536
|
onSelect: mockOnSelect,
|
|
532
537
|
initialIndex: 0,
|
|
533
538
|
});
|
|
534
|
-
rerender({ initialIndex: 2 });
|
|
535
|
-
await
|
|
539
|
+
await rerender({ initialIndex: 2 });
|
|
540
|
+
await waitFor(() => {
|
|
536
541
|
expect(result.current.activeIndex).toBe(2);
|
|
537
542
|
});
|
|
538
543
|
});
|
|
539
544
|
it('should respect a new initialIndex even after user interaction', async () => {
|
|
540
|
-
const { result, rerender } = renderSelectionListHook({
|
|
545
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
541
546
|
items,
|
|
542
547
|
onSelect: mockOnSelect,
|
|
543
548
|
initialIndex: 0,
|
|
@@ -546,25 +551,25 @@ describe('useSelectionList', () => {
|
|
|
546
551
|
pressKey('down');
|
|
547
552
|
expect(result.current.activeIndex).toBe(2);
|
|
548
553
|
// The component re-renders with a new initial index
|
|
549
|
-
rerender({ initialIndex: 3 });
|
|
554
|
+
await rerender({ initialIndex: 3 });
|
|
550
555
|
// The hook should now respect the new initial index
|
|
551
|
-
await
|
|
556
|
+
await waitFor(() => {
|
|
552
557
|
expect(result.current.activeIndex).toBe(3);
|
|
553
558
|
});
|
|
554
559
|
});
|
|
555
560
|
it('should validate index when initialIndex prop changes to a disabled item', async () => {
|
|
556
|
-
const { result, rerender } = renderSelectionListHook({
|
|
561
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
557
562
|
items,
|
|
558
563
|
onSelect: mockOnSelect,
|
|
559
564
|
initialIndex: 0,
|
|
560
565
|
});
|
|
561
|
-
rerender({ initialIndex: 1 });
|
|
562
|
-
await
|
|
566
|
+
await rerender({ initialIndex: 1 });
|
|
567
|
+
await waitFor(() => {
|
|
563
568
|
expect(result.current.activeIndex).toBe(2);
|
|
564
569
|
});
|
|
565
570
|
});
|
|
566
571
|
it('should adjust activeIndex if items change and the initialIndex is now out of bounds', async () => {
|
|
567
|
-
const { result, rerender } = renderSelectionListHook({
|
|
572
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
568
573
|
onSelect: mockOnSelect,
|
|
569
574
|
initialIndex: 3,
|
|
570
575
|
items,
|
|
@@ -574,9 +579,9 @@ describe('useSelectionList', () => {
|
|
|
574
579
|
{ value: 'X', key: 'X' },
|
|
575
580
|
{ value: 'Y', key: 'Y' },
|
|
576
581
|
];
|
|
577
|
-
rerender({ items: shorterItems }); // Length 2
|
|
582
|
+
await rerender({ items: shorterItems }); // Length 2
|
|
578
583
|
// The useEffect syncs based on the initialIndex (3) which is now out of bounds. It defaults to 0.
|
|
579
|
-
await
|
|
584
|
+
await waitFor(() => {
|
|
580
585
|
expect(result.current.activeIndex).toBe(0);
|
|
581
586
|
});
|
|
582
587
|
});
|
|
@@ -586,7 +591,7 @@ describe('useSelectionList', () => {
|
|
|
586
591
|
{ value: 'B', key: 'B' },
|
|
587
592
|
{ value: 'C', key: 'C' },
|
|
588
593
|
];
|
|
589
|
-
const { result, rerender } = renderSelectionListHook({
|
|
594
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
590
595
|
onSelect: mockOnSelect,
|
|
591
596
|
initialIndex: 1,
|
|
592
597
|
items: initialItems,
|
|
@@ -597,19 +602,19 @@ describe('useSelectionList', () => {
|
|
|
597
602
|
{ value: 'B', disabled: true, key: 'B' },
|
|
598
603
|
{ value: 'C', key: 'C' },
|
|
599
604
|
];
|
|
600
|
-
rerender({ items: newItems });
|
|
601
|
-
await
|
|
605
|
+
await rerender({ items: newItems });
|
|
606
|
+
await waitFor(() => {
|
|
602
607
|
expect(result.current.activeIndex).toBe(2);
|
|
603
608
|
});
|
|
604
609
|
});
|
|
605
610
|
it('should reset to 0 if items change to an empty list', async () => {
|
|
606
|
-
const { result, rerender } = renderSelectionListHook({
|
|
611
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
607
612
|
onSelect: mockOnSelect,
|
|
608
613
|
initialIndex: 2,
|
|
609
614
|
items,
|
|
610
615
|
});
|
|
611
|
-
rerender({ items: [] });
|
|
612
|
-
await
|
|
616
|
+
await rerender({ items: [] });
|
|
617
|
+
await waitFor(() => {
|
|
613
618
|
expect(result.current.activeIndex).toBe(0);
|
|
614
619
|
});
|
|
615
620
|
});
|
|
@@ -620,7 +625,7 @@ describe('useSelectionList', () => {
|
|
|
620
625
|
{ value: 'C', key: 'C' },
|
|
621
626
|
{ value: 'D', key: 'D' },
|
|
622
627
|
];
|
|
623
|
-
const { result, rerender } = renderSelectionListHook({
|
|
628
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
624
629
|
onSelect: mockOnSelect,
|
|
625
630
|
onHighlight: mockOnHighlight,
|
|
626
631
|
initialIndex: 2,
|
|
@@ -639,9 +644,9 @@ describe('useSelectionList', () => {
|
|
|
639
644
|
{ value: 'C', key: 'C' },
|
|
640
645
|
{ value: 'D', key: 'D' },
|
|
641
646
|
];
|
|
642
|
-
rerender({ items: newItems });
|
|
647
|
+
await rerender({ items: newItems });
|
|
643
648
|
// Active index should remain the same since items are deeply equal
|
|
644
|
-
await
|
|
649
|
+
await waitFor(() => {
|
|
645
650
|
expect(result.current.activeIndex).toBe(3);
|
|
646
651
|
});
|
|
647
652
|
// onHighlight should NOT be called since the index didn't change
|
|
@@ -654,7 +659,7 @@ describe('useSelectionList', () => {
|
|
|
654
659
|
{ value: 'C', key: 'C' },
|
|
655
660
|
{ value: 'D', key: 'D' },
|
|
656
661
|
];
|
|
657
|
-
const { result, rerender } = renderSelectionListHook({
|
|
662
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
658
663
|
onSelect: mockOnSelect,
|
|
659
664
|
onHighlight: mockOnHighlight,
|
|
660
665
|
initialIndex: 3,
|
|
@@ -668,9 +673,9 @@ describe('useSelectionList', () => {
|
|
|
668
673
|
{ value: 'Y', key: 'Y' },
|
|
669
674
|
{ value: 'Z', key: 'Z' },
|
|
670
675
|
];
|
|
671
|
-
rerender({ items: newItems });
|
|
676
|
+
await rerender({ items: newItems });
|
|
672
677
|
// Active index should update based on initialIndex and new items
|
|
673
|
-
await
|
|
678
|
+
await waitFor(() => {
|
|
674
679
|
expect(result.current.activeIndex).toBe(0);
|
|
675
680
|
});
|
|
676
681
|
});
|
|
@@ -680,7 +685,7 @@ describe('useSelectionList', () => {
|
|
|
680
685
|
{ value: 'B', key: 'B' },
|
|
681
686
|
{ value: 'C', key: 'C' },
|
|
682
687
|
];
|
|
683
|
-
const { result, rerender } = renderSelectionListHook({
|
|
688
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
684
689
|
onSelect: mockOnSelect,
|
|
685
690
|
initialIndex: 1,
|
|
686
691
|
items: initialItems,
|
|
@@ -692,9 +697,9 @@ describe('useSelectionList', () => {
|
|
|
692
697
|
{ value: 'B', disabled: true, key: 'B' },
|
|
693
698
|
{ value: 'C', key: 'C' },
|
|
694
699
|
];
|
|
695
|
-
rerender({ items: newItems });
|
|
700
|
+
await rerender({ items: newItems });
|
|
696
701
|
// Should find next valid index since current became disabled
|
|
697
|
-
await
|
|
702
|
+
await waitFor(() => {
|
|
698
703
|
expect(result.current.activeIndex).toBe(2);
|
|
699
704
|
});
|
|
700
705
|
});
|
|
@@ -704,7 +709,7 @@ describe('useSelectionList', () => {
|
|
|
704
709
|
{ value: 'B', key: 'B' },
|
|
705
710
|
{ value: 'C', key: 'C' },
|
|
706
711
|
];
|
|
707
|
-
const { result, rerender } = renderSelectionListHook({
|
|
712
|
+
const { result, rerender } = await renderSelectionListHook({
|
|
708
713
|
onSelect: mockOnSelect,
|
|
709
714
|
items: initialItems,
|
|
710
715
|
});
|
|
@@ -716,18 +721,18 @@ describe('useSelectionList', () => {
|
|
|
716
721
|
{ value: 'B', key: 'B' },
|
|
717
722
|
{ value: 'C', key: 'C' },
|
|
718
723
|
];
|
|
719
|
-
rerender({ items: newItems });
|
|
720
|
-
await
|
|
724
|
+
await rerender({ items: newItems });
|
|
725
|
+
await waitFor(() => {
|
|
721
726
|
expect(result.current.activeIndex).toBe(2);
|
|
722
727
|
});
|
|
723
728
|
});
|
|
724
|
-
it('should not re-initialize when items have identical keys but are different objects', () => {
|
|
729
|
+
it('should not re-initialize when items have identical keys but are different objects', async () => {
|
|
725
730
|
const initialItems = [
|
|
726
731
|
{ value: 'A', key: 'A' },
|
|
727
732
|
{ value: 'B', key: 'B' },
|
|
728
733
|
];
|
|
729
734
|
let renderCount = 0;
|
|
730
|
-
const renderHookWithCount = (initialProps) => {
|
|
735
|
+
const renderHookWithCount = async (initialProps) => {
|
|
731
736
|
function TestComponent(props) {
|
|
732
737
|
renderCount++;
|
|
733
738
|
useSelectionList({
|
|
@@ -739,10 +744,12 @@ describe('useSelectionList', () => {
|
|
|
739
744
|
}
|
|
740
745
|
const { rerender } = render(_jsx(TestComponent, { ...initialProps }));
|
|
741
746
|
return {
|
|
742
|
-
rerender: (newProps) =>
|
|
747
|
+
rerender: async (newProps) => {
|
|
748
|
+
rerender(_jsx(TestComponent, { ...initialProps, ...newProps }));
|
|
749
|
+
},
|
|
743
750
|
};
|
|
744
751
|
};
|
|
745
|
-
const { rerender } = renderHookWithCount({ items: initialItems });
|
|
752
|
+
const { rerender } = await renderHookWithCount({ items: initialItems });
|
|
746
753
|
// Initial render
|
|
747
754
|
expect(renderCount).toBe(1);
|
|
748
755
|
// Create new items with the same keys but different object references
|
|
@@ -750,7 +757,7 @@ describe('useSelectionList', () => {
|
|
|
750
757
|
{ value: 'A', key: 'A' },
|
|
751
758
|
{ value: 'B', key: 'B' },
|
|
752
759
|
];
|
|
753
|
-
rerender({ items: newItems });
|
|
760
|
+
await rerender({ items: newItems });
|
|
754
761
|
expect(renderCount).toBe(2);
|
|
755
762
|
});
|
|
756
763
|
});
|
|
@@ -761,9 +768,9 @@ describe('useSelectionList', () => {
|
|
|
761
768
|
afterEach(() => {
|
|
762
769
|
vi.useRealTimers();
|
|
763
770
|
});
|
|
764
|
-
it('should clear timeout on unmount when timer is active', () => {
|
|
771
|
+
it('should clear timeout on unmount when timer is active', async () => {
|
|
765
772
|
const longList = Array.from({ length: 15 }, (_, i) => ({ value: `Item ${i + 1}`, key: `Item ${i + 1}` }));
|
|
766
|
-
const { unmount } = renderSelectionListHook({
|
|
773
|
+
const { unmount } = await renderSelectionListHook({
|
|
767
774
|
items: longList,
|
|
768
775
|
onSelect: mockOnSelect,
|
|
769
776
|
showNumbers: true,
|
|
@@ -774,7 +781,7 @@ describe('useSelectionList', () => {
|
|
|
774
781
|
vi.advanceTimersByTime(500);
|
|
775
782
|
});
|
|
776
783
|
expect(mockOnSelect).not.toHaveBeenCalled();
|
|
777
|
-
unmount();
|
|
784
|
+
await unmount();
|
|
778
785
|
expect(vi.getTimerCount()).toBe(0);
|
|
779
786
|
act(() => {
|
|
780
787
|
vi.advanceTimersByTime(1000);
|