@google/gemini-cli 0.12.0-nightly.20251023.c4c0c0d1 → 0.12.0-preview.0

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.
Files changed (248) hide show
  1. package/README.md +7 -5
  2. package/dist/package.json +3 -3
  3. package/dist/src/commands/extensions/disable.d.ts +1 -1
  4. package/dist/src/commands/extensions/disable.js +5 -4
  5. package/dist/src/commands/extensions/disable.js.map +1 -1
  6. package/dist/src/commands/extensions/enable.d.ts +1 -1
  7. package/dist/src/commands/extensions/enable.js +3 -2
  8. package/dist/src/commands/extensions/enable.js.map +1 -1
  9. package/dist/src/commands/extensions/install.js +2 -1
  10. package/dist/src/commands/extensions/install.js.map +1 -1
  11. package/dist/src/commands/extensions/install.test.js +1 -0
  12. package/dist/src/commands/extensions/install.test.js.map +1 -1
  13. package/dist/src/commands/extensions/link.js +2 -1
  14. package/dist/src/commands/extensions/link.js.map +1 -1
  15. package/dist/src/commands/extensions/list.js +2 -2
  16. package/dist/src/commands/extensions/list.js.map +1 -1
  17. package/dist/src/commands/extensions/uninstall.js +2 -1
  18. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  19. package/dist/src/commands/extensions/update.js +2 -2
  20. package/dist/src/commands/extensions/update.js.map +1 -1
  21. package/dist/src/commands/mcp/list.js +2 -2
  22. package/dist/src/commands/mcp/list.js.map +1 -1
  23. package/dist/src/config/config.d.ts +6 -3
  24. package/dist/src/config/config.js +56 -11
  25. package/dist/src/config/config.js.map +1 -1
  26. package/dist/src/config/config.test.js +208 -175
  27. package/dist/src/config/config.test.js.map +1 -1
  28. package/dist/src/config/extension-manager.d.ts +23 -10
  29. package/dist/src/config/extension-manager.js +90 -64
  30. package/dist/src/config/extension-manager.js.map +1 -1
  31. package/dist/src/config/extension.test.js +183 -76
  32. package/dist/src/config/extension.test.js.map +1 -1
  33. package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
  34. package/dist/src/config/extensions/extensionEnablement.js +3 -2
  35. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  36. package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
  37. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  38. package/dist/src/config/extensions/extensionSettings.d.ts +3 -3
  39. package/dist/src/config/extensions/extensionSettings.js +74 -24
  40. package/dist/src/config/extensions/extensionSettings.js.map +1 -1
  41. package/dist/src/config/extensions/extensionSettings.test.js +145 -24
  42. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -1
  43. package/dist/src/config/extensions/github.js +3 -3
  44. package/dist/src/config/extensions/github.js.map +1 -1
  45. package/dist/src/config/extensions/github.test.js +1 -1
  46. package/dist/src/config/extensions/github.test.js.map +1 -1
  47. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  48. package/dist/src/config/extensions/github_fetch.js +13 -1
  49. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  50. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  51. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  52. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  53. package/dist/src/config/extensions/update.js +7 -6
  54. package/dist/src/config/extensions/update.js.map +1 -1
  55. package/dist/src/config/extensions/update.test.js +54 -30
  56. package/dist/src/config/extensions/update.test.js.map +1 -1
  57. package/dist/src/config/keyBindings.js +1 -1
  58. package/dist/src/config/keyBindings.js.map +1 -1
  59. package/dist/src/config/policies/read-only.toml +56 -0
  60. package/dist/src/config/policies/write.toml +63 -0
  61. package/dist/src/config/policies/yolo.toml +31 -0
  62. package/dist/src/config/policy-engine.integration.test.js +41 -38
  63. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  64. package/dist/src/config/policy-toml-loader.d.ts +46 -0
  65. package/dist/src/config/policy-toml-loader.js +314 -0
  66. package/dist/src/config/policy-toml-loader.js.map +1 -0
  67. package/dist/src/config/policy-toml-loader.test.d.ts +6 -0
  68. package/dist/src/config/policy-toml-loader.test.js +626 -0
  69. package/dist/src/config/policy-toml-loader.test.js.map +1 -0
  70. package/dist/src/config/policy.d.ts +9 -2
  71. package/dist/src/config/policy.js +139 -110
  72. package/dist/src/config/policy.js.map +1 -1
  73. package/dist/src/config/policy.test.js +780 -82
  74. package/dist/src/config/policy.test.js.map +1 -1
  75. package/dist/src/config/settings.test.js +6 -6
  76. package/dist/src/config/settings.test.js.map +1 -1
  77. package/dist/src/core/initializer.js +2 -1
  78. package/dist/src/core/initializer.js.map +1 -1
  79. package/dist/src/gemini.js +6 -17
  80. package/dist/src/gemini.js.map +1 -1
  81. package/dist/src/gemini.test.js +27 -2
  82. package/dist/src/gemini.test.js.map +1 -1
  83. package/dist/src/generated/git-commit.d.ts +2 -2
  84. package/dist/src/generated/git-commit.js +2 -2
  85. package/dist/src/generated/git-commit.js.map +1 -1
  86. package/dist/src/nonInteractiveCli.js +16 -4
  87. package/dist/src/nonInteractiveCli.js.map +1 -1
  88. package/dist/src/nonInteractiveCli.test.js +67 -12
  89. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  90. package/dist/src/test-utils/render.d.ts +12 -0
  91. package/dist/src/test-utils/render.js +28 -1
  92. package/dist/src/test-utils/render.js.map +1 -1
  93. package/dist/src/test-utils/render.test.d.ts +6 -0
  94. package/dist/src/test-utils/render.test.js +54 -0
  95. package/dist/src/test-utils/render.test.js.map +1 -0
  96. package/dist/src/ui/AppContainer.js +29 -23
  97. package/dist/src/ui/AppContainer.js.map +1 -1
  98. package/dist/src/ui/AppContainer.test.js +8 -0
  99. package/dist/src/ui/AppContainer.test.js.map +1 -1
  100. package/dist/src/ui/commands/directoryCommand.js +1 -1
  101. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  102. package/dist/src/ui/commands/extensionsCommand.js +45 -1
  103. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  104. package/dist/src/ui/commands/extensionsCommand.test.js +64 -1
  105. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  106. package/dist/src/ui/commands/memoryCommand.js +1 -1
  107. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  108. package/dist/src/ui/commands/memoryCommand.test.js +3 -1
  109. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
  110. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  111. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  112. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  113. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  114. package/dist/src/ui/components/FolderTrustDialog.test.js +4 -4
  115. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  116. package/dist/src/ui/components/Footer.js +1 -1
  117. package/dist/src/ui/components/Footer.js.map +1 -1
  118. package/dist/src/ui/components/Footer.test.js +24 -0
  119. package/dist/src/ui/components/Footer.test.js.map +1 -1
  120. package/dist/src/ui/components/Help.test.js +0 -1
  121. package/dist/src/ui/components/Help.test.js.map +1 -1
  122. package/dist/src/ui/components/InputPrompt.test.js +442 -342
  123. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  124. package/dist/src/ui/components/ModelDialog.test.js +5 -5
  125. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  126. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +11 -12
  127. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  128. package/dist/src/ui/components/SettingsDialog.test.js +13 -14
  129. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  130. package/dist/src/ui/components/ThemeDialog.test.js +1 -2
  131. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  132. package/dist/src/ui/components/shared/BaseSelectionList.test.js +11 -12
  133. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  134. package/dist/src/ui/components/shared/text-buffer.test.js +2 -1
  135. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  136. package/dist/src/ui/components/views/ExtensionsList.d.ts +1 -1
  137. package/dist/src/ui/components/views/ExtensionsList.js +4 -1
  138. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  139. package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
  140. package/dist/src/ui/contexts/KeypressContext.js +114 -64
  141. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  142. package/dist/src/ui/contexts/KeypressContext.test.js +166 -482
  143. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  144. package/dist/src/ui/contexts/SessionContext.test.js +27 -13
  145. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
  146. package/dist/src/ui/hooks/atCommandProcessor.js +2 -2
  147. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  148. package/dist/src/ui/hooks/shellCommandProcessor.test.js +18 -2
  149. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  150. package/dist/src/ui/hooks/slashCommandProcessor.test.js +74 -80
  151. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  152. package/dist/src/ui/hooks/useAtCompletion.test.js +32 -23
  153. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
  154. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +2 -1
  155. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  156. package/dist/src/ui/hooks/useCommandCompletion.test.js +79 -78
  157. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
  158. package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
  159. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
  160. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  161. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  162. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +1 -2
  163. package/dist/src/ui/hooks/useExtensionUpdates.js +4 -2
  164. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  165. package/dist/src/ui/hooks/useExtensionUpdates.test.js +37 -26
  166. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  167. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  168. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  169. package/dist/src/ui/hooks/useFocus.test.js +25 -9
  170. package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
  171. package/dist/src/ui/hooks/useFolderTrust.test.js +45 -22
  172. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  173. package/dist/src/ui/hooks/useGeminiStream.js +56 -19
  174. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  175. package/dist/src/ui/hooks/useGeminiStream.test.js +155 -74
  176. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  177. package/dist/src/ui/hooks/useGitBranchName.test.js +29 -16
  178. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  179. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  180. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  181. package/dist/src/ui/hooks/useIdeTrustListener.test.js +24 -7
  182. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  183. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  184. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  185. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  186. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  187. package/dist/src/ui/hooks/useKeypress.test.js +94 -113
  188. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
  189. package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
  190. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  191. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  192. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  193. package/dist/src/ui/hooks/useMessageQueue.test.js +61 -45
  194. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  195. package/dist/src/ui/hooks/useModelCommand.test.js +18 -11
  196. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  197. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  198. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  199. package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
  200. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  201. package/dist/src/ui/hooks/usePhraseCycler.test.js +83 -110
  202. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
  203. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -10
  204. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  205. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  206. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  207. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +33 -40
  208. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  209. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  210. package/dist/src/ui/hooks/useReactToolScheduler.js +37 -26
  211. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  212. package/dist/src/ui/hooks/useReactToolScheduler.test.js +1 -1
  213. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -1
  214. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  215. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  216. package/dist/src/ui/hooks/useSelectionList.test.js +193 -132
  217. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  218. package/dist/src/ui/hooks/useShellHistory.test.js +40 -16
  219. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  220. package/dist/src/ui/hooks/useSlashCompletion.test.js +54 -49
  221. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  222. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  223. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  224. package/dist/src/ui/hooks/useToolScheduler.test.js +163 -74
  225. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  226. package/dist/src/ui/hooks/vim.test.js +251 -356
  227. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  228. package/dist/src/ui/keyMatchers.test.js +3 -3
  229. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  230. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  231. package/dist/src/ui/utils/textOutput.js +49 -0
  232. package/dist/src/ui/utils/textOutput.js.map +1 -0
  233. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  234. package/dist/src/ui/utils/textOutput.test.js +79 -0
  235. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  236. package/dist/src/ui/utils/updateCheck.d.ts +7 -1
  237. package/dist/src/ui/utils/updateCheck.js +27 -26
  238. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  239. package/dist/src/ui/utils/updateCheck.test.js +19 -49
  240. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  241. package/dist/src/utils/handleAutoUpdate.js +9 -3
  242. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  243. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  244. package/dist/src/zed-integration/zedIntegration.js +9 -16
  245. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  246. package/dist/tsconfig.tsbuildinfo +1 -1
  247. package/package.json +4 -4
  248. package/dist/google-gemini-cli-0.12.0-nightly.20251022.0542de95.tgz +0 -0
@@ -5,7 +5,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
5
5
  * SPDX-License-Identifier: Apache-2.0
6
6
  */
7
7
  import { renderWithProviders } from '../../test-utils/render.js';
8
- import { waitFor, act } from '@testing-library/react';
8
+ import { act } from 'react';
9
9
  import { InputPrompt } from './InputPrompt.js';
10
10
  import { ApprovalMode } from '@google/gemini-cli-core';
11
11
  import * as path from 'node:path';
@@ -207,63 +207,68 @@ describe('InputPrompt', () => {
207
207
  streamingState: StreamingState.Idle,
208
208
  };
209
209
  });
210
- const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms));
211
210
  it('should call shellHistory.getPreviousCommand on up arrow in shell mode', async () => {
212
211
  props.shellModeActive = true;
213
212
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
214
- await wait();
215
- stdin.write('\u001B[A');
216
- await wait();
217
- expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled();
213
+ await act(async () => {
214
+ stdin.write('\u001B[A');
215
+ });
216
+ await vi.waitFor(() => expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled());
218
217
  unmount();
219
218
  });
220
219
  it('should call shellHistory.getNextCommand on down arrow in shell mode', async () => {
221
220
  props.shellModeActive = true;
222
221
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
223
- await wait();
224
- stdin.write('\u001B[B');
225
- await wait();
226
- expect(mockShellHistory.getNextCommand).toHaveBeenCalled();
222
+ await act(async () => {
223
+ stdin.write('\u001B[B');
224
+ });
225
+ await vi.waitFor(() => expect(mockShellHistory.getNextCommand).toHaveBeenCalled());
227
226
  unmount();
228
227
  });
229
228
  it('should set the buffer text when a shell history command is retrieved', async () => {
230
229
  props.shellModeActive = true;
231
230
  vi.mocked(mockShellHistory.getPreviousCommand).mockReturnValue('previous command');
232
231
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
233
- await wait();
234
- stdin.write('\u001B[A');
235
- await wait();
236
- expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled();
237
- expect(props.buffer.setText).toHaveBeenCalledWith('previous command');
232
+ await act(async () => {
233
+ stdin.write('\u001B[A');
234
+ });
235
+ await vi.waitFor(() => {
236
+ expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled();
237
+ expect(props.buffer.setText).toHaveBeenCalledWith('previous command');
238
+ });
238
239
  unmount();
239
240
  });
240
241
  it('should call shellHistory.addCommandToHistory on submit in shell mode', async () => {
241
242
  props.shellModeActive = true;
242
243
  props.buffer.setText('ls -l');
243
244
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
244
- await wait();
245
- stdin.write('\r');
246
- await wait();
247
- expect(mockShellHistory.addCommandToHistory).toHaveBeenCalledWith('ls -l');
248
- expect(props.onSubmit).toHaveBeenCalledWith('ls -l');
245
+ await act(async () => {
246
+ stdin.write('\r');
247
+ });
248
+ await vi.waitFor(() => {
249
+ expect(mockShellHistory.addCommandToHistory).toHaveBeenCalledWith('ls -l');
250
+ expect(props.onSubmit).toHaveBeenCalledWith('ls -l');
251
+ });
249
252
  unmount();
250
253
  });
251
254
  it('should NOT call shell history methods when not in shell mode', async () => {
252
255
  props.buffer.setText('some text');
253
256
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
254
- await wait();
255
- stdin.write('\u001B[A'); // Up arrow
256
- await wait();
257
- stdin.write('\u001B[B'); // Down arrow
258
- await wait();
259
- stdin.write('\r'); // Enter
260
- await wait();
257
+ await act(async () => {
258
+ stdin.write('\u001B[A'); // Up arrow
259
+ });
260
+ await vi.waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
261
+ await act(async () => {
262
+ stdin.write('\u001B[B'); // Down arrow
263
+ });
264
+ await vi.waitFor(() => expect(mockInputHistory.navigateDown).toHaveBeenCalled());
265
+ await act(async () => {
266
+ stdin.write('\r'); // Enter
267
+ });
268
+ await vi.waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('some text'));
261
269
  expect(mockShellHistory.getPreviousCommand).not.toHaveBeenCalled();
262
270
  expect(mockShellHistory.getNextCommand).not.toHaveBeenCalled();
263
271
  expect(mockShellHistory.addCommandToHistory).not.toHaveBeenCalled();
264
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
265
- expect(mockInputHistory.navigateDown).toHaveBeenCalled();
266
- expect(props.onSubmit).toHaveBeenCalledWith('some text');
267
272
  unmount();
268
273
  });
269
274
  it('should call completion.navigateUp for both up arrow and Ctrl+P when suggestions are showing', async () => {
@@ -277,13 +282,15 @@ describe('InputPrompt', () => {
277
282
  });
278
283
  props.buffer.setText('/mem');
279
284
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
280
- await wait();
281
285
  // Test up arrow
282
- stdin.write('\u001B[A'); // Up arrow
283
- await wait();
284
- stdin.write('\u0010'); // Ctrl+P
285
- await wait();
286
- expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(2);
286
+ await act(async () => {
287
+ stdin.write('\u001B[A'); // Up arrow
288
+ });
289
+ await vi.waitFor(() => expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(1));
290
+ await act(async () => {
291
+ stdin.write('\u0010'); // Ctrl+P
292
+ });
293
+ await vi.waitFor(() => expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(2));
287
294
  expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
288
295
  unmount();
289
296
  });
@@ -298,13 +305,15 @@ describe('InputPrompt', () => {
298
305
  });
299
306
  props.buffer.setText('/mem');
300
307
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
301
- await wait();
302
308
  // Test down arrow
303
- stdin.write('\u001B[B'); // Down arrow
304
- await wait();
305
- stdin.write('\u000E'); // Ctrl+N
306
- await wait();
307
- expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(2);
309
+ await act(async () => {
310
+ stdin.write('\u001B[B'); // Down arrow
311
+ });
312
+ await vi.waitFor(() => expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(1));
313
+ await act(async () => {
314
+ stdin.write('\u000E'); // Ctrl+N
315
+ });
316
+ await vi.waitFor(() => expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(2));
308
317
  expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
309
318
  unmount();
310
319
  });
@@ -315,15 +324,22 @@ describe('InputPrompt', () => {
315
324
  });
316
325
  props.buffer.setText('some text');
317
326
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
318
- await wait();
319
- stdin.write('\u001B[A'); // Up arrow
320
- await wait();
321
- stdin.write('\u001B[B'); // Down arrow
322
- await wait();
323
- stdin.write('\u0010'); // Ctrl+P
324
- await wait();
325
- stdin.write('\u000E'); // Ctrl+N
326
- await wait();
327
+ await act(async () => {
328
+ stdin.write('\u001B[A'); // Up arrow
329
+ });
330
+ await vi.waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
331
+ await act(async () => {
332
+ stdin.write('\u001B[B'); // Down arrow
333
+ });
334
+ await vi.waitFor(() => expect(mockInputHistory.navigateDown).toHaveBeenCalled());
335
+ await act(async () => {
336
+ stdin.write('\u0010'); // Ctrl+P
337
+ });
338
+ await vi.waitFor(() => { });
339
+ await act(async () => {
340
+ stdin.write('\u000E'); // Ctrl+N
341
+ });
342
+ await vi.waitFor(() => { });
327
343
  expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
328
344
  expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
329
345
  unmount();
@@ -338,23 +354,27 @@ describe('InputPrompt', () => {
338
354
  vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
339
355
  vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue('/test/.gemini-clipboard/clipboard-123.png');
340
356
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
341
- await wait();
342
357
  // Send Ctrl+V
343
- stdin.write('\x16'); // Ctrl+V
344
- await wait();
345
- expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
346
- expect(clipboardUtils.saveClipboardImage).toHaveBeenCalledWith(props.config.getTargetDir());
347
- expect(clipboardUtils.cleanupOldClipboardImages).toHaveBeenCalledWith(props.config.getTargetDir());
348
- expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
358
+ await act(async () => {
359
+ stdin.write('\x16'); // Ctrl+V
360
+ });
361
+ await vi.waitFor(() => {
362
+ expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
363
+ expect(clipboardUtils.saveClipboardImage).toHaveBeenCalledWith(props.config.getTargetDir());
364
+ expect(clipboardUtils.cleanupOldClipboardImages).toHaveBeenCalledWith(props.config.getTargetDir());
365
+ expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
366
+ });
349
367
  unmount();
350
368
  });
351
369
  it('should not insert anything when clipboard has no image', async () => {
352
370
  vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
353
371
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
354
- await wait();
355
- stdin.write('\x16'); // Ctrl+V
356
- await wait();
357
- expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
372
+ await act(async () => {
373
+ stdin.write('\x16'); // Ctrl+V
374
+ });
375
+ await vi.waitFor(() => {
376
+ expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
377
+ });
358
378
  expect(clipboardUtils.saveClipboardImage).not.toHaveBeenCalled();
359
379
  expect(mockBuffer.setText).not.toHaveBeenCalled();
360
380
  unmount();
@@ -363,10 +383,12 @@ describe('InputPrompt', () => {
363
383
  vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
364
384
  vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(null);
365
385
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
366
- await wait();
367
- stdin.write('\x16'); // Ctrl+V
368
- await wait();
369
- expect(clipboardUtils.saveClipboardImage).toHaveBeenCalled();
386
+ await act(async () => {
387
+ stdin.write('\x16'); // Ctrl+V
388
+ });
389
+ await vi.waitFor(() => {
390
+ expect(clipboardUtils.saveClipboardImage).toHaveBeenCalled();
391
+ });
370
392
  expect(mockBuffer.setText).not.toHaveBeenCalled();
371
393
  unmount();
372
394
  });
@@ -380,11 +402,13 @@ describe('InputPrompt', () => {
380
402
  mockBuffer.lines = ['Hello world'];
381
403
  mockBuffer.replaceRangeByOffset = vi.fn();
382
404
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
383
- await wait();
384
- stdin.write('\x16'); // Ctrl+V
385
- await wait();
386
- // Should insert at cursor position with spaces
387
- expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
405
+ await act(async () => {
406
+ stdin.write('\x16'); // Ctrl+V
407
+ });
408
+ await vi.waitFor(() => {
409
+ // Should insert at cursor position with spaces
410
+ expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
411
+ });
388
412
  // Get the actual call to see what path was used
389
413
  const actualCall = vi.mocked(mockBuffer.replaceRangeByOffset).mock
390
414
  .calls[0];
@@ -399,10 +423,12 @@ describe('InputPrompt', () => {
399
423
  .mockImplementation(() => { });
400
424
  vi.mocked(clipboardUtils.clipboardHasImage).mockRejectedValue(new Error('Clipboard error'));
401
425
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
402
- await wait();
403
- stdin.write('\x16'); // Ctrl+V
404
- await wait();
405
- expect(consoleErrorSpy).toHaveBeenCalledWith('Error handling clipboard image:', expect.any(Error));
426
+ await act(async () => {
427
+ stdin.write('\x16'); // Ctrl+V
428
+ });
429
+ await vi.waitFor(() => {
430
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error handling clipboard image:', expect.any(Error));
431
+ });
406
432
  expect(mockBuffer.setText).not.toHaveBeenCalled();
407
433
  consoleErrorSpy.mockRestore();
408
434
  unmount();
@@ -418,10 +444,10 @@ describe('InputPrompt', () => {
418
444
  });
419
445
  props.buffer.setText('/mem');
420
446
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
421
- await wait();
422
- stdin.write('\t'); // Press Tab
423
- await wait();
424
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
447
+ await act(async () => {
448
+ stdin.write('\t'); // Press Tab
449
+ });
450
+ await vi.waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
425
451
  unmount();
426
452
  });
427
453
  it('should append a sub-command when the parent command is already complete', async () => {
@@ -437,10 +463,10 @@ describe('InputPrompt', () => {
437
463
  });
438
464
  props.buffer.setText('/memory ');
439
465
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
440
- await wait();
441
- stdin.write('\t'); // Press Tab
442
- await wait();
443
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(1);
466
+ await act(async () => {
467
+ stdin.write('\t'); // Press Tab
468
+ });
469
+ await vi.waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(1));
444
470
  unmount();
445
471
  });
446
472
  it('should handle the "backspace" edge case correctly', async () => {
@@ -457,11 +483,12 @@ describe('InputPrompt', () => {
457
483
  // The user has backspaced, so the query is now just '/memory'
458
484
  props.buffer.setText('/memory');
459
485
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
460
- await wait();
461
- stdin.write('\t'); // Press Tab
462
- await wait();
486
+ await act(async () => {
487
+ stdin.write('\t'); // Press Tab
488
+ });
489
+ await vi.waitFor(() =>
463
490
  // It should NOT become '/show'. It should correctly become '/memory show'.
464
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
491
+ expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
465
492
  unmount();
466
493
  });
467
494
  it('should complete a partial argument for a command', async () => {
@@ -474,10 +501,10 @@ describe('InputPrompt', () => {
474
501
  });
475
502
  props.buffer.setText('/chat resume fi-');
476
503
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
477
- await wait();
478
- stdin.write('\t'); // Press Tab
479
- await wait();
480
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
504
+ await act(async () => {
505
+ stdin.write('\t'); // Press Tab
506
+ });
507
+ await vi.waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
481
508
  unmount();
482
509
  });
483
510
  it('should autocomplete on Enter when suggestions are active, without submitting', async () => {
@@ -489,11 +516,13 @@ describe('InputPrompt', () => {
489
516
  });
490
517
  props.buffer.setText('/mem');
491
518
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
492
- await wait();
493
- stdin.write('\r');
494
- await wait();
495
- // The app should autocomplete the text, NOT submit.
496
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
519
+ await act(async () => {
520
+ stdin.write('\r');
521
+ });
522
+ await vi.waitFor(() => {
523
+ // The app should autocomplete the text, NOT submit.
524
+ expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
525
+ });
497
526
  expect(props.onSubmit).not.toHaveBeenCalled();
498
527
  unmount();
499
528
  });
@@ -514,18 +543,19 @@ describe('InputPrompt', () => {
514
543
  });
515
544
  props.buffer.setText('/?');
516
545
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
517
- await wait();
518
- stdin.write('\t'); // Press Tab for autocomplete
519
- await wait();
520
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
546
+ await act(async () => {
547
+ stdin.write('\t'); // Press Tab for autocomplete
548
+ });
549
+ await vi.waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
521
550
  unmount();
522
551
  });
523
552
  it('should not submit on Enter when the buffer is empty or only contains whitespace', async () => {
524
553
  props.buffer.setText(' '); // Set buffer to whitespace
525
554
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
526
- await wait();
527
- stdin.write('\r'); // Press Enter
528
- await wait();
555
+ await act(async () => {
556
+ stdin.write('\r'); // Press Enter
557
+ });
558
+ await vi.waitFor(() => { });
529
559
  expect(props.onSubmit).not.toHaveBeenCalled();
530
560
  unmount();
531
561
  });
@@ -537,10 +567,10 @@ describe('InputPrompt', () => {
537
567
  });
538
568
  props.buffer.setText('/clear');
539
569
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
540
- await wait();
541
- stdin.write('\r');
542
- await wait();
543
- expect(props.onSubmit).toHaveBeenCalledWith('/clear');
570
+ await act(async () => {
571
+ stdin.write('\r');
572
+ });
573
+ await vi.waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('/clear'));
544
574
  unmount();
545
575
  });
546
576
  it('should submit directly on Enter when a complete leaf command is typed', async () => {
@@ -551,10 +581,10 @@ describe('InputPrompt', () => {
551
581
  });
552
582
  props.buffer.setText('/clear');
553
583
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
554
- await wait();
555
- stdin.write('\r');
556
- await wait();
557
- expect(props.onSubmit).toHaveBeenCalledWith('/clear');
584
+ await act(async () => {
585
+ stdin.write('\r');
586
+ });
587
+ await vi.waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('/clear'));
558
588
  unmount();
559
589
  });
560
590
  it('should autocomplete an @-path on Enter without submitting', async () => {
@@ -566,10 +596,10 @@ describe('InputPrompt', () => {
566
596
  });
567
597
  props.buffer.setText('@src/components/');
568
598
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
569
- await wait();
570
- stdin.write('\r');
571
- await wait();
572
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
599
+ await act(async () => {
600
+ stdin.write('\r');
601
+ });
602
+ await vi.waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
573
603
  expect(props.onSubmit).not.toHaveBeenCalled();
574
604
  unmount();
575
605
  });
@@ -579,31 +609,36 @@ describe('InputPrompt', () => {
579
609
  mockBuffer.cursor = [0, 11];
580
610
  mockBuffer.lines = ['first line\\'];
581
611
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
582
- await wait();
583
- stdin.write('\r');
584
- await wait();
612
+ await act(async () => {
613
+ stdin.write('\r');
614
+ });
615
+ await vi.waitFor(() => {
616
+ expect(props.buffer.backspace).toHaveBeenCalled();
617
+ expect(props.buffer.newline).toHaveBeenCalled();
618
+ });
585
619
  expect(props.onSubmit).not.toHaveBeenCalled();
586
- expect(props.buffer.backspace).toHaveBeenCalled();
587
- expect(props.buffer.newline).toHaveBeenCalled();
588
620
  unmount();
589
621
  });
590
622
  it('should clear the buffer on Ctrl+C if it has text', async () => {
591
623
  props.buffer.setText('some text to clear');
592
624
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
593
- await wait();
594
- stdin.write('\x03'); // Ctrl+C character
595
- await wait();
596
- expect(props.buffer.setText).toHaveBeenCalledWith('');
597
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
625
+ await act(async () => {
626
+ stdin.write('\x03'); // Ctrl+C character
627
+ });
628
+ await vi.waitFor(() => {
629
+ expect(props.buffer.setText).toHaveBeenCalledWith('');
630
+ expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
631
+ });
598
632
  expect(props.onSubmit).not.toHaveBeenCalled();
599
633
  unmount();
600
634
  });
601
635
  it('should NOT clear the buffer on Ctrl+C if it is empty', async () => {
602
636
  props.buffer.text = '';
603
637
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
604
- await wait();
605
- stdin.write('\x03'); // Ctrl+C character
606
- await wait();
638
+ await act(async () => {
639
+ stdin.write('\x03'); // Ctrl+C character
640
+ });
641
+ await vi.waitFor(() => { });
607
642
  expect(props.buffer.setText).not.toHaveBeenCalled();
608
643
  unmount();
609
644
  });
@@ -699,8 +734,9 @@ describe('InputPrompt', () => {
699
734
  : [],
700
735
  });
701
736
  const { unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
702
- await wait();
703
- expect(mockedUseCommandCompletion).toHaveBeenCalledWith(mockBuffer, ['/test/project/src'], path.join('test', 'project', 'src'), mockSlashCommands, mockCommandContext, false, false, expect.any(Object));
737
+ await vi.waitFor(() => {
738
+ expect(mockedUseCommandCompletion).toHaveBeenCalledWith(mockBuffer, ['/test/project/src'], path.join('test', 'project', 'src'), mockSlashCommands, mockCommandContext, false, false, expect.any(Object));
739
+ });
704
740
  unmount();
705
741
  });
706
742
  });
@@ -708,32 +744,38 @@ describe('InputPrompt', () => {
708
744
  it('should not call buffer.handleInput when vim mode is enabled and vim handles the input', async () => {
709
745
  props.vimHandleInput = vi.fn().mockReturnValue(true); // Mock that vim handled it.
710
746
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
711
- await wait();
712
- stdin.write('i');
713
- await wait();
714
- expect(props.vimHandleInput).toHaveBeenCalled();
747
+ await act(async () => {
748
+ stdin.write('i');
749
+ });
750
+ await vi.waitFor(() => {
751
+ expect(props.vimHandleInput).toHaveBeenCalled();
752
+ });
715
753
  expect(mockBuffer.handleInput).not.toHaveBeenCalled();
716
754
  unmount();
717
755
  });
718
756
  it('should call buffer.handleInput when vim mode is enabled but vim does not handle the input', async () => {
719
757
  props.vimHandleInput = vi.fn().mockReturnValue(false); // Mock that vim did NOT handle it.
720
758
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
721
- await wait();
722
- stdin.write('i');
723
- await wait();
724
- expect(props.vimHandleInput).toHaveBeenCalled();
725
- expect(mockBuffer.handleInput).toHaveBeenCalled();
759
+ await act(async () => {
760
+ stdin.write('i');
761
+ });
762
+ await vi.waitFor(() => {
763
+ expect(props.vimHandleInput).toHaveBeenCalled();
764
+ expect(mockBuffer.handleInput).toHaveBeenCalled();
765
+ });
726
766
  unmount();
727
767
  });
728
768
  it('should call handleInput when vim mode is disabled', async () => {
729
769
  // Mock vimHandleInput to return false (vim didn't handle the input)
730
770
  props.vimHandleInput = vi.fn().mockReturnValue(false);
731
771
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
732
- await wait();
733
- stdin.write('i');
734
- await wait();
735
- expect(props.vimHandleInput).toHaveBeenCalled();
736
- expect(mockBuffer.handleInput).toHaveBeenCalled();
772
+ await act(async () => {
773
+ stdin.write('i');
774
+ });
775
+ await vi.waitFor(() => {
776
+ expect(props.vimHandleInput).toHaveBeenCalled();
777
+ expect(mockBuffer.handleInput).toHaveBeenCalled();
778
+ });
737
779
  unmount();
738
780
  });
739
781
  });
@@ -741,21 +783,24 @@ describe('InputPrompt', () => {
741
783
  it('should handle bracketed paste when not focused', async () => {
742
784
  props.focus = false;
743
785
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
744
- await wait();
745
- stdin.write('\x1B[200~pasted text\x1B[201~');
746
- await wait();
747
- expect(mockBuffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
748
- paste: true,
749
- sequence: 'pasted text',
750
- }));
786
+ await act(async () => {
787
+ stdin.write('\x1B[200~pasted text\x1B[201~');
788
+ });
789
+ await vi.waitFor(() => {
790
+ expect(mockBuffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
791
+ paste: true,
792
+ sequence: 'pasted text',
793
+ }));
794
+ });
751
795
  unmount();
752
796
  });
753
797
  it('should ignore regular keypresses when not focused', async () => {
754
798
  props.focus = false;
755
799
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
756
- await wait();
757
- stdin.write('a');
758
- await wait();
800
+ await act(async () => {
801
+ stdin.write('a');
802
+ });
803
+ await vi.waitFor(() => { });
759
804
  expect(mockBuffer.handleInput).not.toHaveBeenCalled();
760
805
  unmount();
761
806
  });
@@ -817,9 +862,10 @@ describe('InputPrompt', () => {
817
862
  mockBuffer.viewportVisualLines = [text];
818
863
  mockBuffer.visualCursor = visualCursor;
819
864
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
820
- await wait();
821
- const frame = stdout.lastFrame();
822
- expect(frame).toContain(expected);
865
+ await vi.waitFor(() => {
866
+ const frame = stdout.lastFrame();
867
+ expect(frame).toContain(expected);
868
+ });
823
869
  unmount();
824
870
  });
825
871
  });
@@ -863,9 +909,10 @@ describe('InputPrompt', () => {
863
909
  mockBuffer.visualCursor = visualCursor;
864
910
  mockBuffer.visualToLogicalMap = visualToLogicalMap;
865
911
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
866
- await wait();
867
- const frame = stdout.lastFrame();
868
- expect(frame).toContain(expected);
912
+ await vi.waitFor(() => {
913
+ const frame = stdout.lastFrame();
914
+ expect(frame).toContain(expected);
915
+ });
869
916
  unmount();
870
917
  });
871
918
  it('should display cursor on a blank line in a multiline block', async () => {
@@ -880,11 +927,12 @@ describe('InputPrompt', () => {
880
927
  [2, 0],
881
928
  ];
882
929
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
883
- await wait();
884
- const frame = stdout.lastFrame();
885
- const lines = frame.split('\n');
886
- // The line with the cursor should just be an inverted space inside the box border
887
- expect(lines.find((l) => l.includes(chalk.inverse(' ')))).not.toBeUndefined();
930
+ await vi.waitFor(() => {
931
+ const frame = stdout.lastFrame();
932
+ const lines = frame.split('\n');
933
+ // The line with the cursor should just be an inverted space inside the box border
934
+ expect(lines.find((l) => l.includes(chalk.inverse(' ')))).not.toBeUndefined();
935
+ });
888
936
  unmount();
889
937
  });
890
938
  });
@@ -904,15 +952,16 @@ describe('InputPrompt', () => {
904
952
  [2, 0], // 'world' is logical line 2, col 0
905
953
  ];
906
954
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
907
- await wait();
908
- const frame = stdout.lastFrame();
909
- // Check that all lines, including the empty one, are rendered.
910
- // This implicitly tests that the Box wrapper provides height for the empty line.
911
- expect(frame).toContain('hello');
912
- expect(frame).toContain(`world${chalk.inverse(' ')}`);
913
- const outputLines = frame.split('\n');
914
- // The number of lines should be 2 for the border plus 3 for the content.
915
- expect(outputLines.length).toBe(5);
955
+ await vi.waitFor(() => {
956
+ const frame = stdout.lastFrame();
957
+ // Check that all lines, including the empty one, are rendered.
958
+ // This implicitly tests that the Box wrapper provides height for the empty line.
959
+ expect(frame).toContain('hello');
960
+ expect(frame).toContain(`world${chalk.inverse(' ')}`);
961
+ const outputLines = frame.split('\n');
962
+ // The number of lines should be 2 for the border plus 3 for the content.
963
+ expect(outputLines.length).toBe(5);
964
+ });
916
965
  unmount();
917
966
  });
918
967
  });
@@ -932,16 +981,18 @@ describe('InputPrompt', () => {
932
981
  },
933
982
  ])('should handle multiline paste $description', async ({ pastedText }) => {
934
983
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
935
- await wait();
936
984
  // Simulate a bracketed paste event from the terminal
937
- stdin.write(`\x1b[200~${pastedText}\x1b[201~`);
938
- await wait();
939
- // Verify that the buffer's handleInput was called once with the full text
940
- expect(props.buffer.handleInput).toHaveBeenCalledTimes(1);
941
- expect(props.buffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
942
- paste: true,
943
- sequence: pastedText,
944
- }));
985
+ await act(async () => {
986
+ stdin.write(`\x1b[200~${pastedText}\x1b[201~`);
987
+ });
988
+ await vi.waitFor(() => {
989
+ // Verify that the buffer's handleInput was called once with the full text
990
+ expect(props.buffer.handleInput).toHaveBeenCalledTimes(1);
991
+ expect(props.buffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
992
+ paste: true,
993
+ sequence: pastedText,
994
+ }));
995
+ });
945
996
  unmount();
946
997
  });
947
998
  });
@@ -963,11 +1014,13 @@ describe('InputPrompt', () => {
963
1014
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
964
1015
  await vi.runAllTimersAsync();
965
1016
  // Simulate a paste operation (this should set the paste protection)
966
- act(() => {
1017
+ await act(async () => {
967
1018
  stdin.write(`\x1b[200~pasted content\x1b[201~`);
968
1019
  });
969
1020
  // Simulate an Enter key press immediately after paste
970
- stdin.write('\r');
1021
+ await act(async () => {
1022
+ stdin.write('\r');
1023
+ });
971
1024
  await vi.runAllTimersAsync();
972
1025
  // Verify that onSubmit was NOT called due to recent paste protection
973
1026
  expect(props.onSubmit).not.toHaveBeenCalled();
@@ -981,7 +1034,7 @@ describe('InputPrompt', () => {
981
1034
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
982
1035
  await vi.runAllTimersAsync();
983
1036
  // Simulate a paste operation (this sets the protection)
984
- act(() => {
1037
+ await act(async () => {
985
1038
  stdin.write('\x1b[200~pasted text\x1b[201~');
986
1039
  });
987
1040
  await vi.runAllTimersAsync();
@@ -990,7 +1043,9 @@ describe('InputPrompt', () => {
990
1043
  await vi.advanceTimersByTimeAsync(50);
991
1044
  });
992
1045
  // Now Enter should work normally
993
- stdin.write('\r');
1046
+ await act(async () => {
1047
+ stdin.write('\r');
1048
+ });
994
1049
  await vi.runAllTimersAsync();
995
1050
  expect(props.onSubmit).toHaveBeenCalledWith('pasted text');
996
1051
  expect(props.buffer.newline).not.toHaveBeenCalled();
@@ -1011,10 +1066,14 @@ describe('InputPrompt', () => {
1011
1066
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: true });
1012
1067
  await vi.runAllTimersAsync();
1013
1068
  // Simulate a paste operation
1014
- stdin.write('\x1b[200~some pasted stuff\x1b[201~');
1069
+ await act(async () => {
1070
+ stdin.write('\x1b[200~some pasted stuff\x1b[201~');
1071
+ });
1015
1072
  await vi.runAllTimersAsync();
1016
1073
  // Simulate an Enter key press immediately after paste
1017
- stdin.write('\r');
1074
+ await act(async () => {
1075
+ stdin.write('\r');
1076
+ });
1018
1077
  await vi.runAllTimersAsync();
1019
1078
  // Verify that onSubmit was called
1020
1079
  expect(props.onSubmit).toHaveBeenCalledWith('pasted command');
@@ -1026,7 +1085,9 @@ describe('InputPrompt', () => {
1026
1085
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1027
1086
  await vi.runAllTimersAsync();
1028
1087
  // Press Enter without any recent paste
1029
- stdin.write('\r');
1088
+ await act(async () => {
1089
+ stdin.write('\r');
1090
+ });
1030
1091
  await vi.runAllTimersAsync();
1031
1092
  // Verify that onSubmit was called normally
1032
1093
  expect(props.onSubmit).toHaveBeenCalledWith('normal command');
@@ -1039,13 +1100,19 @@ describe('InputPrompt', () => {
1039
1100
  props.onEscapePromptChange = onEscapePromptChange;
1040
1101
  props.buffer.setText('text to clear');
1041
1102
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1042
- await wait();
1043
- stdin.write('\x1B');
1044
- await wait();
1045
- stdin.write('\x1B');
1046
- await wait();
1047
- expect(props.buffer.setText).toHaveBeenCalledWith('');
1048
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
1103
+ await act(async () => {
1104
+ stdin.write('\x1B');
1105
+ });
1106
+ await vi.waitFor(() => {
1107
+ expect(onEscapePromptChange).toHaveBeenCalledWith(true);
1108
+ });
1109
+ await act(async () => {
1110
+ stdin.write('\x1B');
1111
+ });
1112
+ await vi.waitFor(() => {
1113
+ expect(props.buffer.setText).toHaveBeenCalledWith('');
1114
+ expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
1115
+ });
1049
1116
  unmount();
1050
1117
  });
1051
1118
  it('should reset escape state on any non-ESC key', async () => {
@@ -1053,12 +1120,16 @@ describe('InputPrompt', () => {
1053
1120
  props.onEscapePromptChange = onEscapePromptChange;
1054
1121
  props.buffer.setText('some text');
1055
1122
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1056
- stdin.write('\x1B');
1057
- await waitFor(() => {
1123
+ await act(async () => {
1124
+ stdin.write('\x1B');
1125
+ });
1126
+ await vi.waitFor(() => {
1058
1127
  expect(onEscapePromptChange).toHaveBeenCalledWith(true);
1059
1128
  });
1060
- stdin.write('a');
1061
- await waitFor(() => {
1129
+ await act(async () => {
1130
+ stdin.write('a');
1131
+ });
1132
+ await vi.waitFor(() => {
1062
1133
  expect(onEscapePromptChange).toHaveBeenCalledWith(false);
1063
1134
  });
1064
1135
  unmount();
@@ -1066,10 +1137,10 @@ describe('InputPrompt', () => {
1066
1137
  it('should handle ESC in shell mode by disabling shell mode', async () => {
1067
1138
  props.shellModeActive = true;
1068
1139
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1069
- await wait();
1070
- stdin.write('\x1B');
1071
- await wait();
1072
- expect(props.setShellModeActive).toHaveBeenCalledWith(false);
1140
+ await act(async () => {
1141
+ stdin.write('\x1B');
1142
+ });
1143
+ await vi.waitFor(() => expect(props.setShellModeActive).toHaveBeenCalledWith(false));
1073
1144
  unmount();
1074
1145
  });
1075
1146
  it('should handle ESC when completion suggestions are showing', async () => {
@@ -1079,10 +1150,10 @@ describe('InputPrompt', () => {
1079
1150
  suggestions: [{ label: 'suggestion', value: 'suggestion' }],
1080
1151
  });
1081
1152
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1082
- await wait();
1083
- stdin.write('\x1B');
1084
- await wait();
1085
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
1153
+ await act(async () => {
1154
+ stdin.write('\x1B');
1155
+ });
1156
+ await vi.waitFor(() => expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled());
1086
1157
  unmount();
1087
1158
  });
1088
1159
  it('should not call onEscapePromptChange when not provided', async () => {
@@ -1091,20 +1162,23 @@ describe('InputPrompt', () => {
1091
1162
  props.buffer.setText('some text');
1092
1163
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1093
1164
  await vi.runAllTimersAsync();
1094
- stdin.write('\x1B');
1165
+ await act(async () => {
1166
+ stdin.write('\x1B');
1167
+ });
1095
1168
  await vi.runAllTimersAsync();
1096
1169
  vi.useRealTimers();
1097
1170
  unmount();
1098
1171
  });
1099
1172
  it('should not interfere with existing keyboard shortcuts', async () => {
1100
1173
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), { kittyProtocolEnabled: false });
1101
- await wait();
1102
- stdin.write('\x0C');
1103
- await wait();
1104
- expect(props.onClearScreen).toHaveBeenCalled();
1105
- stdin.write('\x01');
1106
- await wait();
1107
- expect(props.buffer.move).toHaveBeenCalledWith('home');
1174
+ await act(async () => {
1175
+ stdin.write('\x0C');
1176
+ });
1177
+ await vi.waitFor(() => expect(props.onClearScreen).toHaveBeenCalled());
1178
+ await act(async () => {
1179
+ stdin.write('\x01');
1180
+ });
1181
+ await vi.waitFor(() => expect(props.buffer.move).toHaveBeenCalledWith('home'));
1108
1182
  unmount();
1109
1183
  });
1110
1184
  });
@@ -1132,12 +1206,11 @@ describe('InputPrompt', () => {
1132
1206
  activeSuggestionIndex: 0,
1133
1207
  });
1134
1208
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1135
- await wait();
1136
1209
  // Trigger reverse search with Ctrl+R
1137
- act(() => {
1210
+ await act(async () => {
1138
1211
  stdin.write('\x12');
1139
1212
  });
1140
- await waitFor(() => {
1213
+ await vi.waitFor(() => {
1141
1214
  const frame = stdout.lastFrame();
1142
1215
  expect(frame).toContain('(r:)');
1143
1216
  expect(frame).toContain('echo hello');
@@ -1148,12 +1221,17 @@ describe('InputPrompt', () => {
1148
1221
  });
1149
1222
  it('resets reverse search state on Escape', async () => {
1150
1223
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1151
- await wait();
1152
- stdin.write('\x12');
1153
- await wait();
1154
- stdin.write('\x1B');
1155
- stdin.write('\u001b[27u'); // Press kitty escape key
1156
- await waitFor(() => {
1224
+ await act(async () => {
1225
+ stdin.write('\x12');
1226
+ });
1227
+ await vi.waitFor(() => { });
1228
+ await act(async () => {
1229
+ stdin.write('\x1B');
1230
+ });
1231
+ await act(async () => {
1232
+ stdin.write('\u001b[27u'); // Press kitty escape key
1233
+ });
1234
+ await vi.waitFor(() => {
1157
1235
  expect(stdout.lastFrame()).not.toContain('(r:)');
1158
1236
  });
1159
1237
  expect(stdout.lastFrame()).not.toContain('echo hello');
@@ -1179,20 +1257,21 @@ describe('InputPrompt', () => {
1179
1257
  }));
1180
1258
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1181
1259
  // Enter reverse search mode with Ctrl+R
1182
- act(() => {
1260
+ await act(async () => {
1183
1261
  stdin.write('\x12');
1184
1262
  });
1185
1263
  // Verify reverse search is active
1186
- await waitFor(() => {
1264
+ await vi.waitFor(() => {
1187
1265
  expect(stdout.lastFrame()).toContain('(r:)');
1188
1266
  });
1189
1267
  // Press Tab to complete the highlighted entry
1190
- act(() => {
1268
+ await act(async () => {
1191
1269
  stdin.write('\t');
1192
1270
  });
1193
- await wait();
1194
- expect(mockHandleAutocomplete).toHaveBeenCalledWith(0);
1195
- expect(props.buffer.setText).toHaveBeenCalledWith('echo hello');
1271
+ await vi.waitFor(() => {
1272
+ expect(mockHandleAutocomplete).toHaveBeenCalledWith(0);
1273
+ expect(props.buffer.setText).toHaveBeenCalledWith('echo hello');
1274
+ });
1196
1275
  unmount();
1197
1276
  }, 15000);
1198
1277
  it('submits the highlighted entry on Enter and exits reverse-search', async () => {
@@ -1208,16 +1287,16 @@ describe('InputPrompt', () => {
1208
1287
  activeSuggestionIndex: 0,
1209
1288
  });
1210
1289
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1211
- act(() => {
1290
+ await act(async () => {
1212
1291
  stdin.write('\x12');
1213
1292
  });
1214
- await waitFor(() => {
1293
+ await vi.waitFor(() => {
1215
1294
  expect(stdout.lastFrame()).toContain('(r:)');
1216
1295
  });
1217
- act(() => {
1296
+ await act(async () => {
1218
1297
  stdin.write('\r');
1219
1298
  });
1220
- await waitFor(() => {
1299
+ await vi.waitFor(() => {
1221
1300
  expect(stdout.lastFrame()).not.toContain('(r:)');
1222
1301
  });
1223
1302
  expect(props.onSubmit).toHaveBeenCalledWith('echo hello');
@@ -1237,19 +1316,18 @@ describe('InputPrompt', () => {
1237
1316
  showSuggestions: reverseSearchActiveFromInputPrompt,
1238
1317
  }));
1239
1318
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1240
- await wait();
1241
1319
  // reverse search with Ctrl+R
1242
- act(() => {
1320
+ await act(async () => {
1243
1321
  stdin.write('\x12');
1244
1322
  });
1245
- await waitFor(() => {
1323
+ await vi.waitFor(() => {
1246
1324
  expect(stdout.lastFrame()).toContain('(r:)');
1247
1325
  });
1248
1326
  // Press kitty escape key
1249
- act(() => {
1327
+ await act(async () => {
1250
1328
  stdin.write('\u001b[27u');
1251
1329
  });
1252
- await waitFor(() => {
1330
+ await vi.waitFor(() => {
1253
1331
  expect(stdout.lastFrame()).not.toContain('(r:)');
1254
1332
  expect(props.buffer.text).toBe(initialText);
1255
1333
  expect(props.buffer.cursor).toEqual(initialCursor);
@@ -1263,10 +1341,12 @@ describe('InputPrompt', () => {
1263
1341
  props.buffer.cursor = [1, 2];
1264
1342
  props.buffer.lines = ['line 1', 'line 2', 'line 3'];
1265
1343
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1266
- await wait();
1267
- stdin.write('\x05'); // Ctrl+E
1268
- await wait();
1269
- expect(props.buffer.move).toHaveBeenCalledWith('end');
1344
+ await act(async () => {
1345
+ stdin.write('\x05'); // Ctrl+E
1346
+ });
1347
+ await vi.waitFor(() => {
1348
+ expect(props.buffer.move).toHaveBeenCalledWith('end');
1349
+ });
1270
1350
  expect(props.buffer.moveToOffset).not.toHaveBeenCalled();
1271
1351
  unmount();
1272
1352
  });
@@ -1275,10 +1355,12 @@ describe('InputPrompt', () => {
1275
1355
  props.buffer.cursor = [0, 5];
1276
1356
  props.buffer.lines = ['single line text'];
1277
1357
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1278
- await wait();
1279
- stdin.write('\x05'); // Ctrl+E
1280
- await wait();
1281
- expect(props.buffer.move).toHaveBeenCalledWith('end');
1358
+ await act(async () => {
1359
+ stdin.write('\x05'); // Ctrl+E
1360
+ });
1361
+ await vi.waitFor(() => {
1362
+ expect(props.buffer.move).toHaveBeenCalledWith('end');
1363
+ });
1282
1364
  expect(props.buffer.moveToOffset).not.toHaveBeenCalled();
1283
1365
  unmount();
1284
1366
  });
@@ -1298,15 +1380,15 @@ describe('InputPrompt', () => {
1298
1380
  activeSuggestionIndex: isActive ? 0 : -1,
1299
1381
  }));
1300
1382
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1301
- await wait();
1302
- act(() => {
1383
+ await act(async () => {
1303
1384
  stdin.write('\x12'); // Ctrl+R
1304
1385
  });
1305
- await wait();
1306
- const frame = stdout.lastFrame() ?? '';
1307
- expect(frame).toContain('(r:)');
1308
- expect(frame).toContain('git commit');
1309
- expect(frame).toContain('git push');
1386
+ await vi.waitFor(() => {
1387
+ const frame = stdout.lastFrame() ?? '';
1388
+ expect(frame).toContain('(r:)');
1389
+ expect(frame).toContain('git commit');
1390
+ expect(frame).toContain('git push');
1391
+ });
1310
1392
  unmount();
1311
1393
  });
1312
1394
  it('expands and collapses long suggestion via Right/Left arrows', async () => {
@@ -1321,18 +1403,26 @@ describe('InputPrompt', () => {
1321
1403
  isLoadingSuggestions: false,
1322
1404
  });
1323
1405
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1324
- await wait();
1325
- stdin.write('\x12');
1326
- await wait();
1327
- expect(clean(stdout.lastFrame())).toContain('→');
1328
- stdin.write('\u001B[C');
1329
- await wait(200);
1330
- expect(clean(stdout.lastFrame())).toContain('←');
1331
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-expanded-match');
1332
- stdin.write('\u001B[D');
1333
- await wait();
1334
- expect(clean(stdout.lastFrame())).toContain('');
1335
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-collapsed-match');
1406
+ await act(async () => {
1407
+ stdin.write('\x12');
1408
+ });
1409
+ await vi.waitFor(() => {
1410
+ expect(clean(stdout.lastFrame())).toContain('');
1411
+ });
1412
+ await act(async () => {
1413
+ stdin.write('\u001B[C');
1414
+ });
1415
+ await vi.waitFor(() => {
1416
+ expect(clean(stdout.lastFrame())).toContain('');
1417
+ });
1418
+ expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-expanded-match');
1419
+ await act(async () => {
1420
+ stdin.write('\u001B[D');
1421
+ });
1422
+ await vi.waitFor(() => {
1423
+ expect(clean(stdout.lastFrame())).toContain('→');
1424
+ });
1425
+ expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-collapsed-match');
1336
1426
  unmount();
1337
1427
  });
1338
1428
  it('renders match window and expanded view (snapshots)', async () => {
@@ -1349,13 +1439,18 @@ describe('InputPrompt', () => {
1349
1439
  isLoadingSuggestions: false,
1350
1440
  });
1351
1441
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1352
- await wait();
1353
- stdin.write('\x12');
1354
- await wait();
1355
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-collapsed-match');
1356
- stdin.write('\u001B[C');
1357
- await wait();
1358
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-expanded-match');
1442
+ await act(async () => {
1443
+ stdin.write('\x12');
1444
+ });
1445
+ await vi.waitFor(() => {
1446
+ expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-collapsed-match');
1447
+ });
1448
+ await act(async () => {
1449
+ stdin.write('\u001B[C');
1450
+ });
1451
+ await vi.waitFor(() => {
1452
+ expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-expanded-match');
1453
+ });
1359
1454
  unmount();
1360
1455
  });
1361
1456
  it('does not show expand/collapse indicator for short suggestions', async () => {
@@ -1370,12 +1465,16 @@ describe('InputPrompt', () => {
1370
1465
  isLoadingSuggestions: false,
1371
1466
  });
1372
1467
  const { stdin, stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1373
- await wait();
1374
- stdin.write('\x12');
1375
- await wait();
1376
- const frame = clean(stdout.lastFrame());
1377
- expect(frame).not.toContain('→');
1378
- expect(frame).not.toContain('←');
1468
+ await act(async () => {
1469
+ stdin.write('\x12');
1470
+ });
1471
+ await vi.waitFor(() => {
1472
+ const frame = clean(stdout.lastFrame());
1473
+ // Ensure it rendered the search mode
1474
+ expect(frame).toContain('(r:)');
1475
+ expect(frame).not.toContain('→');
1476
+ expect(frame).not.toContain('←');
1477
+ });
1379
1478
  unmount();
1380
1479
  });
1381
1480
  });
@@ -1385,12 +1484,12 @@ describe('InputPrompt', () => {
1385
1484
  props.popAllMessages = mockPopAllMessages;
1386
1485
  props.buffer.text = '';
1387
1486
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1388
- await wait();
1389
- stdin.write('\u001B[A');
1390
- await wait();
1391
- expect(mockPopAllMessages).toHaveBeenCalled();
1487
+ await act(async () => {
1488
+ stdin.write('\u001B[A');
1489
+ });
1490
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1392
1491
  const callback = mockPopAllMessages.mock.calls[0][0];
1393
- act(() => {
1492
+ await act(async () => {
1394
1493
  callback('Message 1\n\nMessage 2\n\nMessage 3');
1395
1494
  });
1396
1495
  expect(props.buffer.setText).toHaveBeenCalledWith('Message 1\n\nMessage 2\n\nMessage 3');
@@ -1401,11 +1500,11 @@ describe('InputPrompt', () => {
1401
1500
  props.popAllMessages = mockPopAllMessages;
1402
1501
  props.buffer.text = 'some text';
1403
1502
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1404
- await wait();
1405
- stdin.write('\u001B[A');
1406
- await wait();
1503
+ await act(async () => {
1504
+ stdin.write('\u001B[A');
1505
+ });
1506
+ await vi.waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
1407
1507
  expect(mockPopAllMessages).not.toHaveBeenCalled();
1408
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
1409
1508
  unmount();
1410
1509
  });
1411
1510
  it('should handle undefined messages from popAllMessages', async () => {
@@ -1413,12 +1512,12 @@ describe('InputPrompt', () => {
1413
1512
  props.popAllMessages = mockPopAllMessages;
1414
1513
  props.buffer.text = '';
1415
1514
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1416
- await wait();
1417
- stdin.write('\u001B[A');
1418
- await wait();
1419
- expect(mockPopAllMessages).toHaveBeenCalled();
1515
+ await act(async () => {
1516
+ stdin.write('\u001B[A');
1517
+ });
1518
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1420
1519
  const callback = mockPopAllMessages.mock.calls[0][0];
1421
- act(() => {
1520
+ await act(async () => {
1422
1521
  callback(undefined);
1423
1522
  });
1424
1523
  expect(props.buffer.setText).not.toHaveBeenCalled();
@@ -1433,10 +1532,10 @@ describe('InputPrompt', () => {
1433
1532
  props.buffer.visualCursor = [0, 0];
1434
1533
  props.buffer.visualScrollRow = 0;
1435
1534
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1436
- await wait();
1437
- stdin.write('\u001B[A');
1438
- await wait();
1439
- expect(mockPopAllMessages).toHaveBeenCalled();
1535
+ await act(async () => {
1536
+ stdin.write('\u001B[A');
1537
+ });
1538
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1440
1539
  unmount();
1441
1540
  });
1442
1541
  it('should handle single queued message', async () => {
@@ -1444,11 +1543,12 @@ describe('InputPrompt', () => {
1444
1543
  props.popAllMessages = mockPopAllMessages;
1445
1544
  props.buffer.text = '';
1446
1545
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1447
- await wait();
1448
- stdin.write('\u001B[A');
1449
- await wait();
1546
+ await act(async () => {
1547
+ stdin.write('\u001B[A');
1548
+ });
1549
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1450
1550
  const callback = mockPopAllMessages.mock.calls[0][0];
1451
- act(() => {
1551
+ await act(async () => {
1452
1552
  callback('Single message');
1453
1553
  });
1454
1554
  expect(props.buffer.setText).toHaveBeenCalledWith('Single message');
@@ -1459,20 +1559,20 @@ describe('InputPrompt', () => {
1459
1559
  props.popAllMessages = mockPopAllMessages;
1460
1560
  props.buffer.text = ' '; // Whitespace only
1461
1561
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1462
- await wait();
1463
- stdin.write('\u001B[A');
1464
- await wait();
1465
- expect(mockPopAllMessages).toHaveBeenCalled();
1562
+ await act(async () => {
1563
+ stdin.write('\u001B[A');
1564
+ });
1565
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1466
1566
  unmount();
1467
1567
  });
1468
1568
  it('should not call popAllMessages if it is not provided', async () => {
1469
1569
  props.popAllMessages = undefined;
1470
1570
  props.buffer.text = '';
1471
1571
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1472
- await wait();
1473
- stdin.write('\u001B[A');
1474
- await wait();
1475
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
1572
+ await act(async () => {
1573
+ stdin.write('\u001B[A');
1574
+ });
1575
+ await vi.waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
1476
1576
  unmount();
1477
1577
  });
1478
1578
  it('should navigate input history on fresh start when no queued messages exist', async () => {
@@ -1480,12 +1580,12 @@ describe('InputPrompt', () => {
1480
1580
  props.popAllMessages = mockPopAllMessages;
1481
1581
  props.buffer.text = '';
1482
1582
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1483
- await wait();
1484
- stdin.write('\u001B[A');
1485
- await wait();
1486
- expect(mockPopAllMessages).toHaveBeenCalled();
1583
+ await act(async () => {
1584
+ stdin.write('\u001B[A');
1585
+ });
1586
+ await vi.waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
1487
1587
  const callback = mockPopAllMessages.mock.calls[0][0];
1488
- act(() => {
1588
+ await act(async () => {
1489
1589
  callback(undefined);
1490
1590
  });
1491
1591
  expect(mockInputHistory.navigateUp).toHaveBeenCalled();
@@ -1497,33 +1597,31 @@ describe('InputPrompt', () => {
1497
1597
  it('should render correctly in shell mode', async () => {
1498
1598
  props.shellModeActive = true;
1499
1599
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1500
- await wait();
1501
- expect(stdout.lastFrame()).toMatchSnapshot();
1600
+ await vi.waitFor(() => expect(stdout.lastFrame()).toMatchSnapshot());
1502
1601
  unmount();
1503
1602
  });
1504
1603
  it('should render correctly when accepting edits', async () => {
1505
1604
  props.approvalMode = ApprovalMode.AUTO_EDIT;
1506
1605
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1507
- await wait();
1508
- expect(stdout.lastFrame()).toMatchSnapshot();
1606
+ await vi.waitFor(() => expect(stdout.lastFrame()).toMatchSnapshot());
1509
1607
  unmount();
1510
1608
  });
1511
1609
  it('should render correctly in yolo mode', async () => {
1512
1610
  props.approvalMode = ApprovalMode.YOLO;
1513
1611
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1514
- await wait();
1515
- expect(stdout.lastFrame()).toMatchSnapshot();
1612
+ await vi.waitFor(() => expect(stdout.lastFrame()).toMatchSnapshot());
1516
1613
  unmount();
1517
1614
  });
1518
1615
  it('should not show inverted cursor when shell is focused', async () => {
1519
1616
  props.isEmbeddedShellFocused = true;
1520
1617
  props.focus = false;
1521
1618
  const { stdout, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1522
- await wait();
1523
- expect(stdout.lastFrame()).not.toContain(`{chalk.inverse(' ')}`);
1524
- // This snapshot is good to make sure there was an input prompt but does
1525
- // not show the inverted cursor because snapshots do not show colors.
1526
- expect(stdout.lastFrame()).toMatchSnapshot();
1619
+ await vi.waitFor(() => {
1620
+ expect(stdout.lastFrame()).not.toContain(`{chalk.inverse(' ')}`);
1621
+ // This snapshot is good to make sure there was an input prompt but does
1622
+ // not show the inverted cursor because snapshots do not show colors.
1623
+ expect(stdout.lastFrame()).toMatchSnapshot();
1624
+ });
1527
1625
  unmount();
1528
1626
  });
1529
1627
  });
@@ -1531,10 +1629,10 @@ describe('InputPrompt', () => {
1531
1629
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }), {
1532
1630
  shellFocus: false,
1533
1631
  });
1534
- await wait();
1535
- stdin.write('a');
1536
- await wait();
1537
- expect(mockBuffer.handleInput).toHaveBeenCalled();
1632
+ await act(async () => {
1633
+ stdin.write('a');
1634
+ });
1635
+ await vi.waitFor(() => expect(mockBuffer.handleInput).toHaveBeenCalled());
1538
1636
  unmount();
1539
1637
  });
1540
1638
  describe('command queuing while streaming', () => {
@@ -1569,17 +1667,19 @@ describe('InputPrompt', () => {
1569
1667
  props.buffer.text = bufferText;
1570
1668
  props.shellModeActive = shellMode;
1571
1669
  const { stdin, unmount } = renderWithProviders(_jsx(InputPrompt, { ...props }));
1572
- await wait();
1573
- stdin.write('\r');
1574
- await wait();
1575
- if (shouldSubmit) {
1576
- expect(props.onSubmit).toHaveBeenCalledWith(bufferText);
1577
- expect(props.setQueueErrorMessage).not.toHaveBeenCalled();
1578
- }
1579
- else {
1580
- expect(props.onSubmit).not.toHaveBeenCalled();
1581
- expect(props.setQueueErrorMessage).toHaveBeenCalledWith(errorMessage);
1582
- }
1670
+ await act(async () => {
1671
+ stdin.write('\r');
1672
+ });
1673
+ await vi.waitFor(() => {
1674
+ if (shouldSubmit) {
1675
+ expect(props.onSubmit).toHaveBeenCalledWith(bufferText);
1676
+ expect(props.setQueueErrorMessage).not.toHaveBeenCalled();
1677
+ }
1678
+ else {
1679
+ expect(props.onSubmit).not.toHaveBeenCalled();
1680
+ expect(props.setQueueErrorMessage).toHaveBeenCalledWith(errorMessage);
1681
+ }
1682
+ });
1583
1683
  unmount();
1584
1684
  });
1585
1685
  });