@machina.ai/cell-cli 1.11.0-rc1 → 1.13.0-rc2

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 (538) hide show
  1. package/dist/package.json +16 -10
  2. package/dist/src/commands/extensions/disable.d.ts +1 -1
  3. package/dist/src/commands/extensions/disable.js +15 -7
  4. package/dist/src/commands/extensions/disable.js.map +1 -1
  5. package/dist/src/commands/extensions/enable.d.ts +1 -1
  6. package/dist/src/commands/extensions/enable.js +15 -7
  7. package/dist/src/commands/extensions/enable.js.map +1 -1
  8. package/dist/src/commands/extensions/install.js +14 -3
  9. package/dist/src/commands/extensions/install.js.map +1 -1
  10. package/dist/src/commands/extensions/install.test.js +39 -19
  11. package/dist/src/commands/extensions/install.test.js.map +1 -1
  12. package/dist/src/commands/extensions/link.js +14 -3
  13. package/dist/src/commands/extensions/link.js.map +1 -1
  14. package/dist/src/commands/extensions/list.js +13 -4
  15. package/dist/src/commands/extensions/list.js.map +1 -1
  16. package/dist/src/commands/extensions/uninstall.js +13 -2
  17. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  18. package/dist/src/commands/extensions/update.js +18 -13
  19. package/dist/src/commands/extensions/update.js.map +1 -1
  20. package/dist/src/commands/extensions/validate.d.ts +12 -0
  21. package/dist/src/commands/extensions/validate.js +83 -0
  22. package/dist/src/commands/extensions/validate.js.map +1 -0
  23. package/dist/src/commands/extensions/validate.test.js +93 -0
  24. package/dist/src/commands/extensions/validate.test.js.map +1 -0
  25. package/dist/src/commands/extensions.js +3 -0
  26. package/dist/src/commands/extensions.js.map +1 -1
  27. package/dist/src/commands/mcp/add.test.js +3 -0
  28. package/dist/src/commands/mcp/add.test.js.map +1 -1
  29. package/dist/src/commands/mcp/list.js +10 -3
  30. package/dist/src/commands/mcp/list.js.map +1 -1
  31. package/dist/src/commands/mcp/list.test.js +37 -27
  32. package/dist/src/commands/mcp/list.test.js.map +1 -1
  33. package/dist/src/config/auth.js +0 -5
  34. package/dist/src/config/auth.js.map +1 -1
  35. package/dist/src/config/config.d.ts +6 -3
  36. package/dist/src/config/config.js +65 -80
  37. package/dist/src/config/config.js.map +1 -1
  38. package/dist/src/config/config.test.js +235 -212
  39. package/dist/src/config/config.test.js.map +1 -1
  40. package/dist/src/config/extension-manager.d.ts +63 -0
  41. package/dist/src/config/extension-manager.js +450 -0
  42. package/dist/src/config/extension-manager.js.map +1 -0
  43. package/dist/src/config/extension.d.ts +4 -51
  44. package/dist/src/config/extension.js +1 -535
  45. package/dist/src/config/extension.js.map +1 -1
  46. package/dist/src/config/extension.test.js +525 -201
  47. package/dist/src/config/extension.test.js.map +1 -1
  48. package/dist/src/config/extensions/consent.d.ts +38 -0
  49. package/dist/src/config/extensions/consent.js +123 -0
  50. package/dist/src/config/extensions/consent.js.map +1 -0
  51. package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
  52. package/dist/src/config/extensions/extensionEnablement.js +4 -3
  53. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  54. package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
  55. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  56. package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
  57. package/dist/src/config/extensions/extensionSettings.js +113 -0
  58. package/dist/src/config/extensions/extensionSettings.js.map +1 -0
  59. package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
  60. package/dist/src/config/extensions/extensionSettings.test.js +254 -0
  61. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
  62. package/dist/src/config/extensions/github.d.ts +2 -2
  63. package/dist/src/config/extensions/github.js +5 -10
  64. package/dist/src/config/extensions/github.js.map +1 -1
  65. package/dist/src/config/extensions/github.test.js +153 -167
  66. package/dist/src/config/extensions/github.test.js.map +1 -1
  67. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  68. package/dist/src/config/extensions/github_fetch.js +13 -1
  69. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  70. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  71. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  72. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  73. package/dist/src/config/extensions/storage.d.ts +14 -0
  74. package/dist/src/config/extensions/storage.js +32 -0
  75. package/dist/src/config/extensions/storage.js.map +1 -0
  76. package/dist/src/config/extensions/update.d.ts +4 -4
  77. package/dist/src/config/extensions/update.js +39 -39
  78. package/dist/src/config/extensions/update.js.map +1 -1
  79. package/dist/src/config/extensions/update.test.js +72 -74
  80. package/dist/src/config/extensions/update.test.js.map +1 -1
  81. package/dist/src/config/extensions/variableSchema.d.ts +0 -6
  82. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  83. package/dist/src/config/extensions/variables.d.ts +4 -0
  84. package/dist/src/config/extensions/variables.js +6 -0
  85. package/dist/src/config/extensions/variables.js.map +1 -1
  86. package/dist/src/config/keyBindings.d.ts +3 -0
  87. package/dist/src/config/keyBindings.js +30 -8
  88. package/dist/src/config/keyBindings.js.map +1 -1
  89. package/dist/src/config/keyBindings.test.js +17 -0
  90. package/dist/src/config/keyBindings.test.js.map +1 -1
  91. package/dist/src/config/policies/read-only.toml +56 -0
  92. package/dist/src/config/policies/write.toml +63 -0
  93. package/dist/src/config/policies/yolo.toml +31 -0
  94. package/dist/src/config/policy-engine.integration.test.js +41 -38
  95. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  96. package/dist/src/config/policy.d.ts +2 -2
  97. package/dist/src/config/policy.js +10 -148
  98. package/dist/src/config/policy.js.map +1 -1
  99. package/dist/src/config/sandboxConfig.d.ts +1 -1
  100. package/dist/src/config/sandboxConfig.js +6 -3
  101. package/dist/src/config/sandboxConfig.js.map +1 -1
  102. package/dist/src/config/settings.d.ts +2 -1
  103. package/dist/src/config/settings.js +58 -18
  104. package/dist/src/config/settings.js.map +1 -1
  105. package/dist/src/config/settings.test.js +128 -69
  106. package/dist/src/config/settings.test.js.map +1 -1
  107. package/dist/src/config/settingsSchema.d.ts +170 -28
  108. package/dist/src/config/settingsSchema.js +418 -27
  109. package/dist/src/config/settingsSchema.js.map +1 -1
  110. package/dist/src/config/settingsSchema.test.js +42 -1
  111. package/dist/src/config/settingsSchema.test.js.map +1 -1
  112. package/dist/src/config/trustedFolders.d.ts +1 -1
  113. package/dist/src/config/trustedFolders.js +4 -2
  114. package/dist/src/config/trustedFolders.js.map +1 -1
  115. package/dist/src/core/initializer.js +2 -1
  116. package/dist/src/core/initializer.js.map +1 -1
  117. package/dist/src/gemini.d.ts +1 -1
  118. package/dist/src/gemini.js +46 -16
  119. package/dist/src/gemini.js.map +1 -1
  120. package/dist/src/gemini.test.js +88 -30
  121. package/dist/src/gemini.test.js.map +1 -1
  122. package/dist/src/generated/git-commit.d.ts +2 -2
  123. package/dist/src/generated/git-commit.js +2 -2
  124. package/dist/src/nonInteractiveCli.d.ts +9 -1
  125. package/dist/src/nonInteractiveCli.js +114 -7
  126. package/dist/src/nonInteractiveCli.js.map +1 -1
  127. package/dist/src/nonInteractiveCli.test.js +355 -112
  128. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  129. package/dist/src/services/BuiltinCommandLoader.js +4 -0
  130. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  131. package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
  132. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  133. package/dist/src/services/FeedbackService.js +2 -2
  134. package/dist/src/services/FeedbackService.js.map +1 -1
  135. package/dist/src/services/McpPromptLoader.js +2 -2
  136. package/dist/src/services/McpPromptLoader.js.map +1 -1
  137. package/dist/src/services/McpPromptLoader.test.js +4 -2
  138. package/dist/src/services/McpPromptLoader.test.js.map +1 -1
  139. package/dist/src/test-utils/async.d.ts +9 -0
  140. package/dist/src/test-utils/async.js +29 -0
  141. package/dist/src/test-utils/async.js.map +1 -0
  142. package/dist/src/test-utils/createExtension.d.ts +3 -1
  143. package/dist/src/test-utils/createExtension.js +3 -3
  144. package/dist/src/test-utils/createExtension.js.map +1 -1
  145. package/dist/src/test-utils/render.d.ts +16 -2
  146. package/dist/src/test-utils/render.js +66 -4
  147. package/dist/src/test-utils/render.js.map +1 -1
  148. package/dist/src/test-utils/render.test.d.ts +6 -0
  149. package/dist/src/test-utils/render.test.js +79 -0
  150. package/dist/src/test-utils/render.test.js.map +1 -0
  151. package/dist/src/ui/App.test.js +1 -1
  152. package/dist/src/ui/App.test.js.map +1 -1
  153. package/dist/src/ui/AppContainer.js +181 -65
  154. package/dist/src/ui/AppContainer.js.map +1 -1
  155. package/dist/src/ui/AppContainer.test.js +505 -147
  156. package/dist/src/ui/AppContainer.test.js.map +1 -1
  157. package/dist/src/ui/IdeIntegrationNudge.js +1 -1
  158. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
  159. package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
  160. package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
  161. package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
  162. package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
  163. package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
  164. package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
  165. package/dist/src/ui/auth/AuthDialog.js +7 -3
  166. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  167. package/dist/src/ui/auth/useAuth.d.ts +2 -0
  168. package/dist/src/ui/auth/useAuth.js +31 -2
  169. package/dist/src/ui/auth/useAuth.js.map +1 -1
  170. package/dist/src/ui/colors.js +3 -0
  171. package/dist/src/ui/colors.js.map +1 -1
  172. package/dist/src/ui/commands/directoryCommand.js +1 -1
  173. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  174. package/dist/src/ui/commands/extensionsCommand.js +64 -11
  175. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  176. package/dist/src/ui/commands/extensionsCommand.test.js +72 -1
  177. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  178. package/dist/src/ui/commands/mcpCommand.js +14 -14
  179. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  180. package/dist/src/ui/commands/mcpCommand.test.js +4 -0
  181. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
  182. package/dist/src/ui/commands/memoryCommand.js +1 -1
  183. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  184. package/dist/src/ui/commands/memoryCommand.test.js +3 -1
  185. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
  186. package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
  187. package/dist/src/ui/commands/policiesCommand.js +59 -0
  188. package/dist/src/ui/commands/policiesCommand.js.map +1 -0
  189. package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
  190. package/dist/src/ui/commands/policiesCommand.test.js +83 -0
  191. package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
  192. package/dist/src/ui/components/AnsiOutput.test.js +1 -1
  193. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  194. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  195. package/dist/src/ui/components/AsciiArt.js +3 -3
  196. package/dist/src/ui/components/Composer.js +1 -1
  197. package/dist/src/ui/components/Composer.js.map +1 -1
  198. package/dist/src/ui/components/Composer.test.js +5 -2
  199. package/dist/src/ui/components/Composer.test.js.map +1 -1
  200. package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
  201. package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
  202. package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
  203. package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
  204. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  205. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  206. package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
  207. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
  208. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  209. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  210. package/dist/src/ui/components/DialogManager.js +4 -0
  211. package/dist/src/ui/components/DialogManager.js.map +1 -1
  212. package/dist/src/ui/components/FolderTrustDialog.test.js +2 -1
  213. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  214. package/dist/src/ui/components/Footer.js +4 -3
  215. package/dist/src/ui/components/Footer.js.map +1 -1
  216. package/dist/src/ui/components/Footer.test.js +83 -0
  217. package/dist/src/ui/components/Footer.test.js.map +1 -1
  218. package/dist/src/ui/components/Header.test.js +13 -5
  219. package/dist/src/ui/components/Header.test.js.map +1 -1
  220. package/dist/src/ui/components/Help.test.js +5 -4
  221. package/dist/src/ui/components/Help.test.js.map +1 -1
  222. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  223. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  224. package/dist/src/ui/components/InputPrompt.js +27 -8
  225. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  226. package/dist/src/ui/components/InputPrompt.test.js +776 -727
  227. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  228. package/dist/src/ui/components/LoadingIndicator.js +2 -2
  229. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  230. package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
  231. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  232. package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
  233. package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
  234. package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
  235. package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
  236. package/dist/src/ui/components/MainContent.js +15 -4
  237. package/dist/src/ui/components/MainContent.js.map +1 -1
  238. package/dist/src/ui/components/ModelDialog.js +1 -1
  239. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  240. package/dist/src/ui/components/ModelDialog.test.js +23 -13
  241. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  242. package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
  243. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
  244. package/dist/src/ui/components/Notifications.js +38 -5
  245. package/dist/src/ui/components/Notifications.js.map +1 -1
  246. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
  247. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  248. package/dist/src/ui/components/PrepareLabel.test.js +14 -8
  249. package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
  250. package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
  251. package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
  252. package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
  253. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  254. package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
  255. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
  256. package/dist/src/ui/components/SettingsDialog.js +32 -25
  257. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  258. package/dist/src/ui/components/SettingsDialog.test.js +428 -532
  259. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  260. package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
  261. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  262. package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
  263. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
  264. package/dist/src/ui/components/StatsDisplay.test.js +1 -1
  265. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
  266. package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
  267. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  268. package/dist/src/ui/components/ThemeDialog.test.js +2 -2
  269. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  270. package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
  271. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
  272. package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
  273. package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
  274. package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
  275. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  276. package/dist/src/ui/components/messages/InfoMessage.js +1 -1
  277. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  278. package/dist/src/ui/components/messages/Todo.js +27 -5
  279. package/dist/src/ui/components/messages/Todo.js.map +1 -1
  280. package/dist/src/ui/components/messages/Todo.test.js +20 -8
  281. package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
  282. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  283. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  284. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
  285. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  286. package/dist/src/ui/components/messages/WarningMessage.js +2 -2
  287. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
  288. package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -1
  289. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  290. package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
  291. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
  292. package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
  293. package/dist/src/ui/components/shared/TextInput.js +38 -0
  294. package/dist/src/ui/components/shared/TextInput.js.map +1 -0
  295. package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
  296. package/dist/src/ui/components/shared/TextInput.test.js +242 -0
  297. package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
  298. package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
  299. package/dist/src/ui/components/shared/text-buffer.js +51 -13
  300. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  301. package/dist/src/ui/components/shared/text-buffer.test.js +385 -202
  302. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  303. package/dist/src/ui/components/views/ChatList.test.js +7 -4
  304. package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
  305. package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
  306. package/dist/src/ui/components/views/ExtensionsList.js +9 -11
  307. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  308. package/dist/src/ui/components/views/ExtensionsList.test.js +43 -22
  309. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  310. package/dist/src/ui/components/views/McpStatus.test.js +23 -12
  311. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  312. package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
  313. package/dist/src/ui/contexts/KeypressContext.js +610 -540
  314. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  315. package/dist/src/ui/contexts/KeypressContext.test.js +438 -718
  316. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  317. package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
  318. package/dist/src/ui/contexts/MouseContext.js +89 -0
  319. package/dist/src/ui/contexts/MouseContext.js.map +1 -0
  320. package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
  321. package/dist/src/ui/contexts/MouseContext.test.js +164 -0
  322. package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
  323. package/dist/src/ui/contexts/SessionContext.test.js +35 -17
  324. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
  325. package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
  326. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  327. package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
  328. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  329. package/dist/src/ui/hooks/atCommandProcessor.js +31 -9
  330. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  331. package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
  332. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  333. package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
  334. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  335. package/dist/src/ui/hooks/slashCommandProcessor.test.js +193 -165
  336. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  337. package/dist/src/ui/hooks/useAtCompletion.test.js +16 -5
  338. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
  339. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
  340. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  341. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -1
  342. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  343. package/dist/src/ui/hooks/useCommandCompletion.test.js +66 -64
  344. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
  345. package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
  346. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
  347. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  348. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  349. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -5
  350. package/dist/src/ui/hooks/useExtensionUpdates.js +18 -13
  351. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  352. package/dist/src/ui/hooks/useExtensionUpdates.test.js +49 -44
  353. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  354. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  355. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  356. package/dist/src/ui/hooks/useFocus.test.js +25 -9
  357. package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
  358. package/dist/src/ui/hooks/useFolderTrust.test.js +46 -22
  359. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  360. package/dist/src/ui/hooks/useGeminiStream.js +56 -19
  361. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  362. package/dist/src/ui/hooks/useGeminiStream.test.js +260 -411
  363. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  364. package/dist/src/ui/hooks/useGitBranchName.js +4 -0
  365. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  366. package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
  367. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  368. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  369. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  370. package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
  371. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  372. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  373. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  374. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  375. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  376. package/dist/src/ui/hooks/useKeypress.test.js +103 -114
  377. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
  378. package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
  379. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  380. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  381. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  382. package/dist/src/ui/hooks/useMessageQueue.test.js +62 -45
  383. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  384. package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
  385. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  386. package/dist/src/ui/hooks/useMouse.d.ts +17 -0
  387. package/dist/src/ui/hooks/useMouse.js +27 -0
  388. package/dist/src/ui/hooks/useMouse.js.map +1 -0
  389. package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
  390. package/dist/src/ui/hooks/useMouse.test.js +57 -0
  391. package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
  392. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  393. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  394. package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
  395. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  396. package/dist/src/ui/hooks/usePhraseCycler.test.js +109 -106
  397. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
  398. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
  399. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  400. package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
  401. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
  402. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  403. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  404. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
  405. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  406. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  407. package/dist/src/ui/hooks/useReactToolScheduler.js +59 -34
  408. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  409. package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
  410. package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
  411. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
  412. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  413. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  414. package/dist/src/ui/hooks/useSelectionList.js +5 -4
  415. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  416. package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
  417. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  418. package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
  419. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  420. package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
  421. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  422. package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
  423. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  424. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  425. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  426. package/dist/src/ui/hooks/useToolScheduler.test.js +226 -242
  427. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  428. package/dist/src/ui/hooks/vim.test.js +235 -355
  429. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  430. package/dist/src/ui/keyMatchers.test.js +30 -3
  431. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  432. package/dist/src/ui/state/extensions.d.ts +1 -0
  433. package/dist/src/ui/state/extensions.js +1 -0
  434. package/dist/src/ui/state/extensions.js.map +1 -1
  435. package/dist/src/ui/themes/ansi-light.js +1 -0
  436. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  437. package/dist/src/ui/themes/ansi.js +1 -0
  438. package/dist/src/ui/themes/ansi.js.map +1 -1
  439. package/dist/src/ui/themes/atom-one-dark.js +2 -0
  440. package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
  441. package/dist/src/ui/themes/ayu-light.js +2 -0
  442. package/dist/src/ui/themes/ayu-light.js.map +1 -1
  443. package/dist/src/ui/themes/ayu.js +2 -0
  444. package/dist/src/ui/themes/ayu.js.map +1 -1
  445. package/dist/src/ui/themes/color-utils.d.ts +1 -0
  446. package/dist/src/ui/themes/color-utils.js +6 -0
  447. package/dist/src/ui/themes/color-utils.js.map +1 -1
  448. package/dist/src/ui/themes/color-utils.test.js +13 -1
  449. package/dist/src/ui/themes/color-utils.test.js.map +1 -1
  450. package/dist/src/ui/themes/dracula.js +2 -0
  451. package/dist/src/ui/themes/dracula.js.map +1 -1
  452. package/dist/src/ui/themes/github-dark.js +2 -0
  453. package/dist/src/ui/themes/github-dark.js.map +1 -1
  454. package/dist/src/ui/themes/github-light.js +2 -0
  455. package/dist/src/ui/themes/github-light.js.map +1 -1
  456. package/dist/src/ui/themes/googlecode.js +2 -0
  457. package/dist/src/ui/themes/googlecode.js.map +1 -1
  458. package/dist/src/ui/themes/no-color.js +3 -0
  459. package/dist/src/ui/themes/no-color.js.map +1 -1
  460. package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
  461. package/dist/src/ui/themes/semantic-tokens.js +6 -0
  462. package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
  463. package/dist/src/ui/themes/shades-of-purple.js +2 -0
  464. package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
  465. package/dist/src/ui/themes/theme.d.ts +3 -0
  466. package/dist/src/ui/themes/theme.js +14 -3
  467. package/dist/src/ui/themes/theme.js.map +1 -1
  468. package/dist/src/ui/themes/theme.test.js +67 -1
  469. package/dist/src/ui/themes/theme.test.js.map +1 -1
  470. package/dist/src/ui/themes/xcode.js +2 -0
  471. package/dist/src/ui/themes/xcode.js.map +1 -1
  472. package/dist/src/ui/types.d.ts +3 -1
  473. package/dist/src/ui/types.js +2 -0
  474. package/dist/src/ui/types.js.map +1 -1
  475. package/dist/src/ui/utils/CodeColorizer.js +2 -1
  476. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  477. package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
  478. package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
  479. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  480. package/dist/src/ui/utils/MarkdownDisplay.js +11 -9
  481. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  482. package/dist/src/ui/utils/clipboardUtils.js +2 -2
  483. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  484. package/dist/src/ui/utils/input.d.ts +17 -0
  485. package/dist/src/ui/utils/input.js +51 -0
  486. package/dist/src/ui/utils/input.js.map +1 -0
  487. package/dist/src/ui/utils/input.test.d.ts +6 -0
  488. package/dist/src/ui/utils/input.test.js +44 -0
  489. package/dist/src/ui/utils/input.test.js.map +1 -0
  490. package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
  491. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
  492. package/dist/src/ui/utils/mouse.d.ts +31 -0
  493. package/dist/src/ui/utils/mouse.js +164 -0
  494. package/dist/src/ui/utils/mouse.js.map +1 -0
  495. package/dist/src/ui/utils/mouse.test.d.ts +6 -0
  496. package/dist/src/ui/utils/mouse.test.js +131 -0
  497. package/dist/src/ui/utils/mouse.test.js.map +1 -0
  498. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  499. package/dist/src/ui/utils/textOutput.js +49 -0
  500. package/dist/src/ui/utils/textOutput.js.map +1 -0
  501. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  502. package/dist/src/ui/utils/textOutput.test.js +79 -0
  503. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  504. package/dist/src/ui/utils/updateCheck.d.ts +7 -1
  505. package/dist/src/ui/utils/updateCheck.js +33 -29
  506. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  507. package/dist/src/ui/utils/updateCheck.test.js +24 -50
  508. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  509. package/dist/src/utils/commentJson.js +2 -2
  510. package/dist/src/utils/commentJson.js.map +1 -1
  511. package/dist/src/utils/commentJson.test.js +7 -6
  512. package/dist/src/utils/commentJson.test.js.map +1 -1
  513. package/dist/src/utils/envVarResolver.d.ts +2 -2
  514. package/dist/src/utils/envVarResolver.js +10 -7
  515. package/dist/src/utils/envVarResolver.js.map +1 -1
  516. package/dist/src/utils/events.d.ts +11 -2
  517. package/dist/src/utils/events.js +1 -0
  518. package/dist/src/utils/events.js.map +1 -1
  519. package/dist/src/utils/handleAutoUpdate.js +9 -3
  520. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  521. package/dist/src/utils/sandbox.js +16 -18
  522. package/dist/src/utils/sandbox.js.map +1 -1
  523. package/dist/src/utils/version.js +6 -2
  524. package/dist/src/utils/version.js.map +1 -1
  525. package/dist/src/zed-integration/acp.js +2 -1
  526. package/dist/src/zed-integration/acp.js.map +1 -1
  527. package/dist/src/zed-integration/schema.d.ts +4 -4
  528. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  529. package/dist/src/zed-integration/zedIntegration.js +12 -19
  530. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  531. package/dist/tsconfig.tsbuildinfo +1 -1
  532. package/package.json +18 -14
  533. package/dist/src/config/policy.test.js +0 -360
  534. package/dist/src/config/policy.test.js.map +0 -1
  535. package/dist/src/utils/package.d.ts +0 -12
  536. package/dist/src/utils/package.js +0 -24
  537. package/dist/src/utils/package.js.map +0 -1
  538. /package/dist/src/{config/policy.test.d.ts → commands/extensions/validate.test.d.ts} +0 -0
@@ -1,10 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  /**
2
3
  * @license
3
4
  * Copyright 2025 Google LLC
4
5
  * SPDX-License-Identifier: Apache-2.0
5
6
  */
6
7
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { renderHook, act } from '@testing-library/react';
8
+ import { act } from 'react';
9
+ import { render } from '../../test-utils/render.js';
10
+ import { waitFor } from '../../test-utils/async.js';
8
11
  import { useSelectionList, } from './useSelectionList.js';
9
12
  import { useKeypress } from './useKeypress.js';
10
13
  vi.mock('./useKeypress.js');
@@ -31,15 +34,15 @@ describe('useSelectionList', () => {
31
34
  mockOnSelect.mockClear();
32
35
  mockOnHighlight.mockClear();
33
36
  });
34
- const pressKey = (name, sequence = name) => {
37
+ const pressKey = (name, sequence = name, options = {}) => {
35
38
  act(() => {
36
39
  if (activeKeypressHandler) {
37
40
  const key = {
38
41
  name,
39
42
  sequence,
40
- ctrl: false,
43
+ ctrl: options.ctrl ?? false,
41
44
  meta: false,
42
- shift: false,
45
+ shift: options.shift ?? false,
43
46
  paste: false,
44
47
  };
45
48
  activeKeypressHandler(key);
@@ -49,131 +52,186 @@ describe('useSelectionList', () => {
49
52
  }
50
53
  });
51
54
  };
55
+ const renderSelectionListHook = async (initialProps) => {
56
+ let hookResult;
57
+ function TestComponent(props) {
58
+ hookResult = useSelectionList(props);
59
+ return null;
60
+ }
61
+ const { rerender, unmount } = render(_jsx(TestComponent, { ...initialProps }));
62
+ return {
63
+ result: {
64
+ get current() {
65
+ return hookResult;
66
+ },
67
+ },
68
+ rerender: async (newProps) => {
69
+ rerender(_jsx(TestComponent, { ...initialProps, ...newProps }));
70
+ },
71
+ unmount: async () => {
72
+ unmount();
73
+ },
74
+ };
75
+ };
52
76
  describe('Initialization', () => {
53
- it('should initialize with the default index (0) if enabled', () => {
54
- const { result } = renderHook(() => useSelectionList({ items, onSelect: mockOnSelect }));
77
+ it('should initialize with the default index (0) if enabled', async () => {
78
+ const { result } = await renderSelectionListHook({
79
+ items,
80
+ onSelect: mockOnSelect,
81
+ });
55
82
  expect(result.current.activeIndex).toBe(0);
56
83
  });
57
- it('should initialize with the provided initialIndex if enabled', () => {
58
- const { result } = renderHook(() => useSelectionList({
84
+ it('should initialize with the provided initialIndex if enabled', async () => {
85
+ const { result } = await renderSelectionListHook({
59
86
  items,
60
87
  initialIndex: 2,
61
88
  onSelect: mockOnSelect,
62
- }));
89
+ });
63
90
  expect(result.current.activeIndex).toBe(2);
64
91
  });
65
- it('should handle an empty list gracefully', () => {
66
- const { result } = renderHook(() => useSelectionList({ items: [], onSelect: mockOnSelect }));
92
+ it('should handle an empty list gracefully', async () => {
93
+ const { result } = await renderSelectionListHook({
94
+ items: [],
95
+ onSelect: mockOnSelect,
96
+ });
67
97
  expect(result.current.activeIndex).toBe(0);
68
98
  });
69
- it('should find the next enabled item (downwards) if initialIndex is disabled', () => {
70
- const { result } = renderHook(() => useSelectionList({
99
+ it('should find the next enabled item (downwards) if initialIndex is disabled', async () => {
100
+ const { result } = await renderSelectionListHook({
71
101
  items,
72
102
  initialIndex: 1,
73
103
  onSelect: mockOnSelect,
74
- }));
104
+ });
75
105
  expect(result.current.activeIndex).toBe(2);
76
106
  });
77
- 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 () => {
78
108
  const wrappingItems = [
79
109
  { value: 'A', key: 'A' },
80
110
  { value: 'B', disabled: true, key: 'B' },
81
111
  { value: 'C', disabled: true, key: 'C' },
82
112
  ];
83
- const { result } = renderHook(() => useSelectionList({
113
+ const { result } = await renderSelectionListHook({
84
114
  items: wrappingItems,
85
115
  initialIndex: 2,
86
116
  onSelect: mockOnSelect,
87
- }));
117
+ });
88
118
  expect(result.current.activeIndex).toBe(0);
89
119
  });
90
- it('should default to 0 if initialIndex is out of bounds', () => {
91
- const { result } = renderHook(() => useSelectionList({
120
+ it('should default to 0 if initialIndex is out of bounds', async () => {
121
+ const { result } = await renderSelectionListHook({
92
122
  items,
93
123
  initialIndex: 10,
94
124
  onSelect: mockOnSelect,
95
- }));
125
+ });
96
126
  expect(result.current.activeIndex).toBe(0);
97
- const { result: resultNeg } = renderHook(() => useSelectionList({
127
+ const { result: resultNeg } = await renderSelectionListHook({
98
128
  items,
99
129
  initialIndex: -1,
100
130
  onSelect: mockOnSelect,
101
- }));
131
+ });
102
132
  expect(resultNeg.current.activeIndex).toBe(0);
103
133
  });
104
- 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 () => {
105
135
  const allDisabled = [
106
136
  { value: 'A', disabled: true, key: 'A' },
107
137
  { value: 'B', disabled: true, key: 'B' },
108
138
  ];
109
- const { result } = renderHook(() => useSelectionList({
139
+ const { result } = await renderSelectionListHook({
110
140
  items: allDisabled,
111
141
  initialIndex: 1,
112
142
  onSelect: mockOnSelect,
113
- }));
143
+ });
114
144
  expect(result.current.activeIndex).toBe(1);
115
145
  });
116
146
  });
117
147
  describe('Keyboard Navigation (Up/Down/J/K)', () => {
118
- it('should move down with "j" and "down" keys, skipping disabled items', () => {
119
- const { result } = renderHook(() => useSelectionList({ items, onSelect: mockOnSelect }));
148
+ it('should move down with "j" and "down" keys, skipping disabled items', async () => {
149
+ const { result } = await renderSelectionListHook({
150
+ items,
151
+ onSelect: mockOnSelect,
152
+ });
120
153
  expect(result.current.activeIndex).toBe(0);
121
154
  pressKey('j');
122
155
  expect(result.current.activeIndex).toBe(2);
123
156
  pressKey('down');
124
157
  expect(result.current.activeIndex).toBe(3);
125
158
  });
126
- it('should move up with "k" and "up" keys, skipping disabled items', () => {
127
- const { result } = renderHook(() => useSelectionList({ items, initialIndex: 3, onSelect: mockOnSelect }));
159
+ it('should move up with "k" and "up" keys, skipping disabled items', async () => {
160
+ const { result } = await renderSelectionListHook({
161
+ items,
162
+ initialIndex: 3,
163
+ onSelect: mockOnSelect,
164
+ });
128
165
  expect(result.current.activeIndex).toBe(3);
129
166
  pressKey('k');
130
167
  expect(result.current.activeIndex).toBe(2);
131
168
  pressKey('up');
132
169
  expect(result.current.activeIndex).toBe(0);
133
170
  });
134
- it('should wrap navigation correctly', () => {
135
- const { result } = renderHook(() => useSelectionList({
171
+ it('should ignore navigation keys when shift is pressed', async () => {
172
+ const { result } = await renderSelectionListHook({
173
+ items,
174
+ initialIndex: 2, // Start at middle item 'C'
175
+ onSelect: mockOnSelect,
176
+ });
177
+ expect(result.current.activeIndex).toBe(2);
178
+ // Shift+Down / Shift+J should not move down
179
+ pressKey('down', undefined, { shift: true });
180
+ expect(result.current.activeIndex).toBe(2);
181
+ pressKey('j', undefined, { shift: true });
182
+ expect(result.current.activeIndex).toBe(2);
183
+ // Shift+Up / Shift+K should not move up
184
+ pressKey('up', undefined, { shift: true });
185
+ expect(result.current.activeIndex).toBe(2);
186
+ pressKey('k', undefined, { shift: true });
187
+ expect(result.current.activeIndex).toBe(2);
188
+ // Verify normal navigation still works
189
+ pressKey('down');
190
+ expect(result.current.activeIndex).toBe(3);
191
+ });
192
+ it('should wrap navigation correctly', async () => {
193
+ const { result } = await renderSelectionListHook({
136
194
  items,
137
195
  initialIndex: items.length - 1,
138
196
  onSelect: mockOnSelect,
139
- }));
197
+ });
140
198
  expect(result.current.activeIndex).toBe(3);
141
199
  pressKey('down');
142
200
  expect(result.current.activeIndex).toBe(0);
143
201
  pressKey('up');
144
202
  expect(result.current.activeIndex).toBe(3);
145
203
  });
146
- it('should call onHighlight when index changes', () => {
147
- renderHook(() => useSelectionList({
204
+ it('should call onHighlight when index changes', async () => {
205
+ await renderSelectionListHook({
148
206
  items,
149
207
  onSelect: mockOnSelect,
150
208
  onHighlight: mockOnHighlight,
151
- }));
209
+ });
152
210
  pressKey('down');
153
211
  expect(mockOnHighlight).toHaveBeenCalledTimes(1);
154
212
  expect(mockOnHighlight).toHaveBeenCalledWith('C');
155
213
  });
156
- it('should not move or call onHighlight if navigation results in the same index (e.g., single item)', () => {
214
+ it('should not move or call onHighlight if navigation results in the same index (e.g., single item)', async () => {
157
215
  const singleItem = [{ value: 'A', key: 'A' }];
158
- const { result } = renderHook(() => useSelectionList({
216
+ const { result } = await renderSelectionListHook({
159
217
  items: singleItem,
160
218
  onSelect: mockOnSelect,
161
219
  onHighlight: mockOnHighlight,
162
- }));
220
+ });
163
221
  pressKey('down');
164
222
  expect(result.current.activeIndex).toBe(0);
165
223
  expect(mockOnHighlight).not.toHaveBeenCalled();
166
224
  });
167
- it('should not move or call onHighlight if all items are disabled', () => {
225
+ it('should not move or call onHighlight if all items are disabled', async () => {
168
226
  const allDisabled = [
169
227
  { value: 'A', disabled: true, key: 'A' },
170
228
  { value: 'B', disabled: true, key: 'B' },
171
229
  ];
172
- const { result } = renderHook(() => useSelectionList({
230
+ const { result } = await renderSelectionListHook({
173
231
  items: allDisabled,
174
232
  onSelect: mockOnSelect,
175
233
  onHighlight: mockOnHighlight,
176
- }));
234
+ });
177
235
  const initialIndex = result.current.activeIndex;
178
236
  pressKey('down');
179
237
  expect(result.current.activeIndex).toBe(initialIndex);
@@ -181,33 +239,33 @@ describe('useSelectionList', () => {
181
239
  });
182
240
  });
183
241
  describe('Selection (Enter)', () => {
184
- it('should call onSelect when "return" is pressed on enabled item', () => {
185
- renderHook(() => useSelectionList({
242
+ it('should call onSelect when "return" is pressed on enabled item', async () => {
243
+ await renderSelectionListHook({
186
244
  items,
187
245
  initialIndex: 2,
188
246
  onSelect: mockOnSelect,
189
- }));
247
+ });
190
248
  pressKey('return');
191
249
  expect(mockOnSelect).toHaveBeenCalledTimes(1);
192
250
  expect(mockOnSelect).toHaveBeenCalledWith('C');
193
251
  });
194
- it('should not call onSelect if the active item is disabled', () => {
195
- const { result } = renderHook(() => useSelectionList({
252
+ it('should not call onSelect if the active item is disabled', async () => {
253
+ const { result } = await renderSelectionListHook({
196
254
  items,
197
255
  onSelect: mockOnSelect,
198
- }));
256
+ });
199
257
  act(() => result.current.setActiveIndex(1));
200
258
  pressKey('return');
201
259
  expect(mockOnSelect).not.toHaveBeenCalled();
202
260
  });
203
261
  });
204
262
  describe('Keyboard Navigation Robustness (Rapid Input)', () => {
205
- it('should handle rapid navigation and selection robustly (avoiding stale state)', () => {
206
- const { result } = renderHook(() => useSelectionList({
263
+ it('should handle rapid navigation and selection robustly (avoiding stale state)', async () => {
264
+ const { result } = await renderSelectionListHook({
207
265
  items, // A, B(disabled), C, D. Initial index 0 (A).
208
266
  onSelect: mockOnSelect,
209
267
  onHighlight: mockOnHighlight,
210
- }));
268
+ });
211
269
  // Simulate rapid inputs with separate act blocks to allow effects to run
212
270
  if (!activeKeypressHandler)
213
271
  throw new Error('Handler not active');
@@ -243,12 +301,12 @@ describe('useSelectionList', () => {
243
301
  expect(mockOnSelect).toHaveBeenCalledWith('D');
244
302
  expect(mockOnSelect).not.toHaveBeenCalledWith('A');
245
303
  });
246
- it('should handle ultra-rapid input (multiple presses in single act) without stale state', () => {
247
- const { result } = renderHook(() => useSelectionList({
304
+ it('should handle ultra-rapid input (multiple presses in single act) without stale state', async () => {
305
+ const { result } = await renderSelectionListHook({
248
306
  items, // A, B(disabled), C, D. Initial index 0 (A).
249
307
  onSelect: mockOnSelect,
250
308
  onHighlight: mockOnHighlight,
251
- }));
309
+ });
252
310
  // Simulate ultra-rapid inputs where all keypresses happen faster than React can re-render
253
311
  act(() => {
254
312
  if (!activeKeypressHandler)
@@ -277,34 +335,45 @@ describe('useSelectionList', () => {
277
335
  });
278
336
  });
279
337
  describe('Focus Management (isFocused)', () => {
280
- it('should activate the keypress handler when focused (default) and items exist', () => {
281
- const { result } = renderHook(() => useSelectionList({ items, onSelect: mockOnSelect }));
338
+ it('should activate the keypress handler when focused (default) and items exist', async () => {
339
+ const { result } = await renderSelectionListHook({
340
+ items,
341
+ onSelect: mockOnSelect,
342
+ });
282
343
  expect(activeKeypressHandler).not.toBeNull();
283
344
  pressKey('down');
284
345
  expect(result.current.activeIndex).toBe(2);
285
346
  });
286
- it('should not activate the keypress handler when isFocused is false', () => {
287
- renderHook(() => useSelectionList({ items, onSelect: mockOnSelect, isFocused: false }));
347
+ it('should not activate the keypress handler when isFocused is false', async () => {
348
+ await renderSelectionListHook({
349
+ items,
350
+ onSelect: mockOnSelect,
351
+ isFocused: false,
352
+ });
288
353
  expect(activeKeypressHandler).toBeNull();
289
354
  expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
290
355
  });
291
- it('should not activate the keypress handler when items list is empty', () => {
292
- renderHook(() => useSelectionList({
356
+ it('should not activate the keypress handler when items list is empty', async () => {
357
+ await renderSelectionListHook({
293
358
  items: [],
294
359
  onSelect: mockOnSelect,
295
360
  isFocused: true,
296
- }));
361
+ });
297
362
  expect(activeKeypressHandler).toBeNull();
298
363
  expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
299
364
  });
300
- it('should activate/deactivate when isFocused prop changes', () => {
301
- const { result, rerender } = renderHook((props) => useSelectionList({ items, onSelect: mockOnSelect, ...props }), { initialProps: { isFocused: false } });
365
+ it('should activate/deactivate when isFocused prop changes', async () => {
366
+ const { result, rerender } = await renderSelectionListHook({
367
+ items,
368
+ onSelect: mockOnSelect,
369
+ isFocused: false,
370
+ });
302
371
  expect(activeKeypressHandler).toBeNull();
303
- rerender({ isFocused: true });
372
+ await rerender({ isFocused: true });
304
373
  expect(activeKeypressHandler).not.toBeNull();
305
374
  pressKey('down');
306
375
  expect(result.current.activeIndex).toBe(2);
307
- rerender({ isFocused: false });
376
+ await rerender({ isFocused: false });
308
377
  expect(activeKeypressHandler).toBeNull();
309
378
  expect(() => pressKey('down')).toThrow(/keypress handler is not active/);
310
379
  });
@@ -319,19 +388,22 @@ describe('useSelectionList', () => {
319
388
  const shortList = items;
320
389
  const longList = Array.from({ length: 15 }, (_, i) => ({ value: `Item ${i + 1}`, key: `Item ${i + 1}` }));
321
390
  const pressNumber = (num) => pressKey(num, num);
322
- it('should not respond to numbers if showNumbers is false (default)', () => {
323
- const { result } = renderHook(() => useSelectionList({ items: shortList, onSelect: mockOnSelect }));
391
+ it('should not respond to numbers if showNumbers is false (default)', async () => {
392
+ const { result } = await renderSelectionListHook({
393
+ items: shortList,
394
+ onSelect: mockOnSelect,
395
+ });
324
396
  pressNumber('1');
325
397
  expect(result.current.activeIndex).toBe(0);
326
398
  expect(mockOnSelect).not.toHaveBeenCalled();
327
399
  });
328
- it('should select item immediately if the number cannot be extended (unambiguous)', () => {
329
- const { result } = renderHook(() => useSelectionList({
400
+ it('should select item immediately if the number cannot be extended (unambiguous)', async () => {
401
+ const { result } = await renderSelectionListHook({
330
402
  items: shortList,
331
403
  onSelect: mockOnSelect,
332
404
  onHighlight: mockOnHighlight,
333
405
  showNumbers: true,
334
- }));
406
+ });
335
407
  pressNumber('3');
336
408
  expect(result.current.activeIndex).toBe(2);
337
409
  expect(mockOnHighlight).toHaveBeenCalledWith('C');
@@ -339,14 +411,14 @@ describe('useSelectionList', () => {
339
411
  expect(mockOnSelect).toHaveBeenCalledWith('C');
340
412
  expect(vi.getTimerCount()).toBe(0);
341
413
  });
342
- it('should highlight and wait for timeout if the number can be extended (ambiguous)', () => {
343
- const { result } = renderHook(() => useSelectionList({
414
+ it('should highlight and wait for timeout if the number can be extended (ambiguous)', async () => {
415
+ const { result } = await renderSelectionListHook({
344
416
  items: longList,
345
417
  initialIndex: 1, // Start at index 1 so pressing "1" (index 0) causes a change
346
418
  onSelect: mockOnSelect,
347
419
  onHighlight: mockOnHighlight,
348
420
  showNumbers: true,
349
- }));
421
+ });
350
422
  pressNumber('1');
351
423
  expect(result.current.activeIndex).toBe(0);
352
424
  expect(mockOnHighlight).toHaveBeenCalledWith('Item 1');
@@ -358,12 +430,12 @@ describe('useSelectionList', () => {
358
430
  expect(mockOnSelect).toHaveBeenCalledTimes(1);
359
431
  expect(mockOnSelect).toHaveBeenCalledWith('Item 1');
360
432
  });
361
- it('should handle multi-digit input correctly', () => {
362
- const { result } = renderHook(() => useSelectionList({
433
+ it('should handle multi-digit input correctly', async () => {
434
+ const { result } = await renderSelectionListHook({
363
435
  items: longList,
364
436
  onSelect: mockOnSelect,
365
437
  showNumbers: true,
366
- }));
438
+ });
367
439
  pressNumber('1');
368
440
  expect(mockOnSelect).not.toHaveBeenCalled();
369
441
  pressNumber('2');
@@ -371,12 +443,12 @@ describe('useSelectionList', () => {
371
443
  expect(mockOnSelect).toHaveBeenCalledTimes(1);
372
444
  expect(mockOnSelect).toHaveBeenCalledWith('Item 12');
373
445
  });
374
- it('should reset buffer if input becomes invalid (out of bounds)', () => {
375
- const { result } = renderHook(() => useSelectionList({
446
+ it('should reset buffer if input becomes invalid (out of bounds)', async () => {
447
+ const { result } = await renderSelectionListHook({
376
448
  items: shortList,
377
449
  onSelect: mockOnSelect,
378
450
  showNumbers: true,
379
- }));
451
+ });
380
452
  pressNumber('5');
381
453
  expect(result.current.activeIndex).toBe(0);
382
454
  expect(mockOnSelect).not.toHaveBeenCalled();
@@ -384,12 +456,12 @@ describe('useSelectionList', () => {
384
456
  expect(result.current.activeIndex).toBe(2);
385
457
  expect(mockOnSelect).toHaveBeenCalledWith('C');
386
458
  });
387
- it('should allow "0" as subsequent digit, but ignore as first digit', () => {
388
- const { result } = renderHook(() => useSelectionList({
459
+ it('should allow "0" as subsequent digit, but ignore as first digit', async () => {
460
+ const { result } = await renderSelectionListHook({
389
461
  items: longList,
390
462
  onSelect: mockOnSelect,
391
463
  showNumbers: true,
392
- }));
464
+ });
393
465
  pressNumber('0');
394
466
  expect(result.current.activeIndex).toBe(0);
395
467
  expect(mockOnSelect).not.toHaveBeenCalled();
@@ -401,12 +473,12 @@ describe('useSelectionList', () => {
401
473
  expect(result.current.activeIndex).toBe(9);
402
474
  expect(mockOnSelect).toHaveBeenCalledWith('Item 10');
403
475
  });
404
- it('should clear the initial "0" input after timeout', () => {
405
- renderHook(() => useSelectionList({
476
+ it('should clear the initial "0" input after timeout', async () => {
477
+ await renderSelectionListHook({
406
478
  items: longList,
407
479
  onSelect: mockOnSelect,
408
480
  showNumbers: true,
409
- }));
481
+ });
410
482
  pressNumber('0');
411
483
  act(() => vi.advanceTimersByTime(1000)); // Timeout the '0' input
412
484
  pressNumber('1');
@@ -414,30 +486,30 @@ describe('useSelectionList', () => {
414
486
  act(() => vi.advanceTimersByTime(1000)); // Timeout '1'
415
487
  expect(mockOnSelect).toHaveBeenCalledWith('Item 1');
416
488
  });
417
- it('should highlight but not select a disabled item (immediate selection case)', () => {
418
- const { result } = renderHook(() => useSelectionList({
489
+ it('should highlight but not select a disabled item (immediate selection case)', async () => {
490
+ const { result } = await renderSelectionListHook({
419
491
  items: shortList, // B (index 1, number 2) is disabled
420
492
  onSelect: mockOnSelect,
421
493
  onHighlight: mockOnHighlight,
422
494
  showNumbers: true,
423
- }));
495
+ });
424
496
  pressNumber('2');
425
497
  expect(result.current.activeIndex).toBe(1);
426
498
  expect(mockOnHighlight).toHaveBeenCalledWith('B');
427
499
  // Should not select immediately, even though 20 > 4
428
500
  expect(mockOnSelect).not.toHaveBeenCalled();
429
501
  });
430
- it('should highlight but not select a disabled item (timeout case)', () => {
502
+ it('should highlight but not select a disabled item (timeout case)', async () => {
431
503
  // Create a list where the ambiguous prefix points to a disabled item
432
504
  const disabledAmbiguousList = [
433
505
  { value: 'Item 1 Disabled', disabled: true, key: 'Item 1 Disabled' },
434
506
  ...longList.slice(1),
435
507
  ];
436
- const { result } = renderHook(() => useSelectionList({
508
+ const { result } = await renderSelectionListHook({
437
509
  items: disabledAmbiguousList,
438
510
  onSelect: mockOnSelect,
439
511
  showNumbers: true,
440
- }));
512
+ });
441
513
  pressNumber('1');
442
514
  expect(result.current.activeIndex).toBe(0);
443
515
  expect(vi.getTimerCount()).toBe(1);
@@ -447,12 +519,12 @@ describe('useSelectionList', () => {
447
519
  // Should not select after timeout
448
520
  expect(mockOnSelect).not.toHaveBeenCalled();
449
521
  });
450
- it('should clear the number buffer if a non-numeric key (e.g., navigation) is pressed', () => {
451
- const { result } = renderHook(() => useSelectionList({
522
+ it('should clear the number buffer if a non-numeric key (e.g., navigation) is pressed', async () => {
523
+ const { result } = await renderSelectionListHook({
452
524
  items: longList,
453
525
  onSelect: mockOnSelect,
454
526
  showNumbers: true,
455
- }));
527
+ });
456
528
  pressNumber('1');
457
529
  expect(vi.getTimerCount()).toBe(1);
458
530
  pressKey('down');
@@ -462,12 +534,12 @@ describe('useSelectionList', () => {
462
534
  // Should select '3', not '13'
463
535
  expect(result.current.activeIndex).toBe(2);
464
536
  });
465
- it('should clear the number buffer if "return" is pressed', () => {
466
- renderHook(() => useSelectionList({
537
+ it('should clear the number buffer if "return" is pressed', async () => {
538
+ await renderSelectionListHook({
467
539
  items: longList,
468
540
  onSelect: mockOnSelect,
469
541
  showNumbers: true,
470
- }));
542
+ });
471
543
  pressNumber('1');
472
544
  pressKey('return');
473
545
  expect(mockOnSelect).toHaveBeenCalledTimes(1);
@@ -479,95 +551,107 @@ describe('useSelectionList', () => {
479
551
  });
480
552
  });
481
553
  describe('Reactivity (Dynamic Updates)', () => {
482
- it('should update activeIndex when initialIndex prop changes', () => {
483
- const { result, rerender } = renderHook(({ initialIndex }) => useSelectionList({
554
+ it('should update activeIndex when initialIndex prop changes', async () => {
555
+ const { result, rerender } = await renderSelectionListHook({
484
556
  items,
485
557
  onSelect: mockOnSelect,
486
- initialIndex,
487
- }), { initialProps: { initialIndex: 0 } });
488
- rerender({ initialIndex: 2 });
489
- expect(result.current.activeIndex).toBe(2);
558
+ initialIndex: 0,
559
+ });
560
+ await rerender({ initialIndex: 2 });
561
+ await waitFor(() => {
562
+ expect(result.current.activeIndex).toBe(2);
563
+ });
490
564
  });
491
- it('should respect a new initialIndex even after user interaction', () => {
492
- const { result, rerender } = renderHook(({ initialIndex }) => useSelectionList({
565
+ it('should respect a new initialIndex even after user interaction', async () => {
566
+ const { result, rerender } = await renderSelectionListHook({
493
567
  items,
494
568
  onSelect: mockOnSelect,
495
- initialIndex,
496
- }), { initialProps: { initialIndex: 0 } });
569
+ initialIndex: 0,
570
+ });
497
571
  // User navigates, changing the active index
498
572
  pressKey('down');
499
573
  expect(result.current.activeIndex).toBe(2);
500
574
  // The component re-renders with a new initial index
501
- rerender({ initialIndex: 3 });
575
+ await rerender({ initialIndex: 3 });
502
576
  // The hook should now respect the new initial index
503
- expect(result.current.activeIndex).toBe(3);
577
+ await waitFor(() => {
578
+ expect(result.current.activeIndex).toBe(3);
579
+ });
504
580
  });
505
- it('should validate index when initialIndex prop changes to a disabled item', () => {
506
- const { result, rerender } = renderHook(({ initialIndex }) => useSelectionList({
581
+ it('should validate index when initialIndex prop changes to a disabled item', async () => {
582
+ const { result, rerender } = await renderSelectionListHook({
507
583
  items,
508
584
  onSelect: mockOnSelect,
509
- initialIndex,
510
- }), { initialProps: { initialIndex: 0 } });
511
- rerender({ initialIndex: 1 });
512
- expect(result.current.activeIndex).toBe(2);
585
+ initialIndex: 0,
586
+ });
587
+ await rerender({ initialIndex: 1 });
588
+ await waitFor(() => {
589
+ expect(result.current.activeIndex).toBe(2);
590
+ });
513
591
  });
514
- it('should adjust activeIndex if items change and the initialIndex is now out of bounds', () => {
515
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
592
+ it('should adjust activeIndex if items change and the initialIndex is now out of bounds', async () => {
593
+ const { result, rerender } = await renderSelectionListHook({
516
594
  onSelect: mockOnSelect,
517
595
  initialIndex: 3,
518
- items: testItems,
519
- }), { initialProps: { items } });
596
+ items,
597
+ });
520
598
  expect(result.current.activeIndex).toBe(3);
521
599
  const shorterItems = [
522
600
  { value: 'X', key: 'X' },
523
601
  { value: 'Y', key: 'Y' },
524
602
  ];
525
- rerender({ items: shorterItems }); // Length 2
603
+ await rerender({ items: shorterItems }); // Length 2
526
604
  // The useEffect syncs based on the initialIndex (3) which is now out of bounds. It defaults to 0.
527
- expect(result.current.activeIndex).toBe(0);
605
+ await waitFor(() => {
606
+ expect(result.current.activeIndex).toBe(0);
607
+ });
528
608
  });
529
- it('should adjust activeIndex if items change and the initialIndex becomes disabled', () => {
609
+ it('should adjust activeIndex if items change and the initialIndex becomes disabled', async () => {
530
610
  const initialItems = [
531
611
  { value: 'A', key: 'A' },
532
612
  { value: 'B', key: 'B' },
533
613
  { value: 'C', key: 'C' },
534
614
  ];
535
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
615
+ const { result, rerender } = await renderSelectionListHook({
536
616
  onSelect: mockOnSelect,
537
617
  initialIndex: 1,
538
- items: testItems,
539
- }), { initialProps: { items: initialItems } });
618
+ items: initialItems,
619
+ });
540
620
  expect(result.current.activeIndex).toBe(1);
541
621
  const newItems = [
542
622
  { value: 'A', key: 'A' },
543
623
  { value: 'B', disabled: true, key: 'B' },
544
624
  { value: 'C', key: 'C' },
545
625
  ];
546
- rerender({ items: newItems });
547
- expect(result.current.activeIndex).toBe(2);
626
+ await rerender({ items: newItems });
627
+ await waitFor(() => {
628
+ expect(result.current.activeIndex).toBe(2);
629
+ });
548
630
  });
549
- it('should reset to 0 if items change to an empty list', () => {
550
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
631
+ it('should reset to 0 if items change to an empty list', async () => {
632
+ const { result, rerender } = await renderSelectionListHook({
551
633
  onSelect: mockOnSelect,
552
634
  initialIndex: 2,
553
- items: testItems,
554
- }), { initialProps: { items } });
555
- rerender({ items: [] });
556
- expect(result.current.activeIndex).toBe(0);
635
+ items,
636
+ });
637
+ await rerender({ items: [] });
638
+ await waitFor(() => {
639
+ expect(result.current.activeIndex).toBe(0);
640
+ });
557
641
  });
558
- it('should not reset activeIndex when items are deeply equal', () => {
642
+ it('should not reset activeIndex when items are deeply equal', async () => {
559
643
  const initialItems = [
560
644
  { value: 'A', key: 'A' },
561
645
  { value: 'B', disabled: true, key: 'B' },
562
646
  { value: 'C', key: 'C' },
563
647
  { value: 'D', key: 'D' },
564
648
  ];
565
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
649
+ const { result, rerender } = await renderSelectionListHook({
566
650
  onSelect: mockOnSelect,
567
651
  onHighlight: mockOnHighlight,
568
652
  initialIndex: 2,
569
- items: testItems,
570
- }), { initialProps: { items: initialItems } });
653
+ items: initialItems,
654
+ });
571
655
  expect(result.current.activeIndex).toBe(2);
572
656
  act(() => {
573
657
  result.current.setActiveIndex(3);
@@ -581,25 +665,27 @@ describe('useSelectionList', () => {
581
665
  { value: 'C', key: 'C' },
582
666
  { value: 'D', key: 'D' },
583
667
  ];
584
- rerender({ items: newItems });
668
+ await rerender({ items: newItems });
585
669
  // Active index should remain the same since items are deeply equal
586
- expect(result.current.activeIndex).toBe(3);
670
+ await waitFor(() => {
671
+ expect(result.current.activeIndex).toBe(3);
672
+ });
587
673
  // onHighlight should NOT be called since the index didn't change
588
674
  expect(mockOnHighlight).not.toHaveBeenCalled();
589
675
  });
590
- it('should update activeIndex when items change structurally', () => {
676
+ it('should update activeIndex when items change structurally', async () => {
591
677
  const initialItems = [
592
678
  { value: 'A', key: 'A' },
593
679
  { value: 'B', disabled: true, key: 'B' },
594
680
  { value: 'C', key: 'C' },
595
681
  { value: 'D', key: 'D' },
596
682
  ];
597
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
683
+ const { result, rerender } = await renderSelectionListHook({
598
684
  onSelect: mockOnSelect,
599
685
  onHighlight: mockOnHighlight,
600
686
  initialIndex: 3,
601
- items: testItems,
602
- }), { initialProps: { items: initialItems } });
687
+ items: initialItems,
688
+ });
603
689
  expect(result.current.activeIndex).toBe(3);
604
690
  mockOnHighlight.mockClear();
605
691
  // Change item values (not deeply equal)
@@ -608,21 +694,23 @@ describe('useSelectionList', () => {
608
694
  { value: 'Y', key: 'Y' },
609
695
  { value: 'Z', key: 'Z' },
610
696
  ];
611
- rerender({ items: newItems });
697
+ await rerender({ items: newItems });
612
698
  // Active index should update based on initialIndex and new items
613
- expect(result.current.activeIndex).toBe(0);
699
+ await waitFor(() => {
700
+ expect(result.current.activeIndex).toBe(0);
701
+ });
614
702
  });
615
- it('should handle partial changes in items array', () => {
703
+ it('should handle partial changes in items array', async () => {
616
704
  const initialItems = [
617
705
  { value: 'A', key: 'A' },
618
706
  { value: 'B', key: 'B' },
619
707
  { value: 'C', key: 'C' },
620
708
  ];
621
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
709
+ const { result, rerender } = await renderSelectionListHook({
622
710
  onSelect: mockOnSelect,
623
711
  initialIndex: 1,
624
- items: testItems,
625
- }), { initialProps: { items: initialItems } });
712
+ items: initialItems,
713
+ });
626
714
  expect(result.current.activeIndex).toBe(1);
627
715
  // Change only one item's disabled status
628
716
  const newItems = [
@@ -630,20 +718,22 @@ describe('useSelectionList', () => {
630
718
  { value: 'B', disabled: true, key: 'B' },
631
719
  { value: 'C', key: 'C' },
632
720
  ];
633
- rerender({ items: newItems });
721
+ await rerender({ items: newItems });
634
722
  // Should find next valid index since current became disabled
635
- expect(result.current.activeIndex).toBe(2);
723
+ await waitFor(() => {
724
+ expect(result.current.activeIndex).toBe(2);
725
+ });
636
726
  });
637
- it('should update selection when a new item is added to the start of the list', () => {
727
+ it('should update selection when a new item is added to the start of the list', async () => {
638
728
  const initialItems = [
639
729
  { value: 'A', key: 'A' },
640
730
  { value: 'B', key: 'B' },
641
731
  { value: 'C', key: 'C' },
642
732
  ];
643
- const { result, rerender } = renderHook(({ items: testItems }) => useSelectionList({
733
+ const { result, rerender } = await renderSelectionListHook({
644
734
  onSelect: mockOnSelect,
645
- items: testItems,
646
- }), { initialProps: { items: initialItems } });
735
+ items: initialItems,
736
+ });
647
737
  pressKey('down');
648
738
  expect(result.current.activeIndex).toBe(1);
649
739
  const newItems = [
@@ -652,23 +742,35 @@ describe('useSelectionList', () => {
652
742
  { value: 'B', key: 'B' },
653
743
  { value: 'C', key: 'C' },
654
744
  ];
655
- rerender({ items: newItems });
656
- expect(result.current.activeIndex).toBe(2);
745
+ await rerender({ items: newItems });
746
+ await waitFor(() => {
747
+ expect(result.current.activeIndex).toBe(2);
748
+ });
657
749
  });
658
- it('should not re-initialize when items have identical keys but are different objects', () => {
750
+ it('should not re-initialize when items have identical keys but are different objects', async () => {
659
751
  const initialItems = [
660
752
  { value: 'A', key: 'A' },
661
753
  { value: 'B', key: 'B' },
662
754
  ];
663
755
  let renderCount = 0;
664
- const { rerender } = renderHook(({ items: testItems }) => {
665
- renderCount++;
666
- return useSelectionList({
667
- onSelect: mockOnSelect,
668
- onHighlight: mockOnHighlight,
669
- items: testItems,
670
- });
671
- }, { initialProps: { items: initialItems } });
756
+ const renderHookWithCount = async (initialProps) => {
757
+ function TestComponent(props) {
758
+ renderCount++;
759
+ useSelectionList({
760
+ onSelect: mockOnSelect,
761
+ onHighlight: mockOnHighlight,
762
+ items: props.items,
763
+ });
764
+ return null;
765
+ }
766
+ const { rerender } = render(_jsx(TestComponent, { ...initialProps }));
767
+ return {
768
+ rerender: async (newProps) => {
769
+ rerender(_jsx(TestComponent, { ...initialProps, ...newProps }));
770
+ },
771
+ };
772
+ };
773
+ const { rerender } = await renderHookWithCount({ items: initialItems });
672
774
  // Initial render
673
775
  expect(renderCount).toBe(1);
674
776
  // Create new items with the same keys but different object references
@@ -676,23 +778,10 @@ describe('useSelectionList', () => {
676
778
  { value: 'A', key: 'A' },
677
779
  { value: 'B', key: 'B' },
678
780
  ];
679
- rerender({ items: newItems });
781
+ await rerender({ items: newItems });
680
782
  expect(renderCount).toBe(2);
681
783
  });
682
784
  });
683
- describe('Manual Control', () => {
684
- it('should allow manual setting of active index via setActiveIndex', () => {
685
- const { result } = renderHook(() => useSelectionList({ items, onSelect: mockOnSelect }));
686
- act(() => {
687
- result.current.setActiveIndex(3);
688
- });
689
- expect(result.current.activeIndex).toBe(3);
690
- act(() => {
691
- result.current.setActiveIndex(1);
692
- });
693
- expect(result.current.activeIndex).toBe(1);
694
- });
695
- });
696
785
  describe('Cleanup', () => {
697
786
  beforeEach(() => {
698
787
  vi.useFakeTimers();
@@ -700,20 +789,20 @@ describe('useSelectionList', () => {
700
789
  afterEach(() => {
701
790
  vi.useRealTimers();
702
791
  });
703
- it('should clear timeout on unmount when timer is active', () => {
792
+ it('should clear timeout on unmount when timer is active', async () => {
704
793
  const longList = Array.from({ length: 15 }, (_, i) => ({ value: `Item ${i + 1}`, key: `Item ${i + 1}` }));
705
- const { unmount } = renderHook(() => useSelectionList({
794
+ const { unmount } = await renderSelectionListHook({
706
795
  items: longList,
707
796
  onSelect: mockOnSelect,
708
797
  showNumbers: true,
709
- }));
798
+ });
710
799
  pressKey('1', '1');
711
800
  expect(vi.getTimerCount()).toBe(1);
712
801
  act(() => {
713
802
  vi.advanceTimersByTime(500);
714
803
  });
715
804
  expect(mockOnSelect).not.toHaveBeenCalled();
716
- unmount();
805
+ await unmount();
717
806
  expect(vi.getTimerCount()).toBe(0);
718
807
  act(() => {
719
808
  vi.advanceTimersByTime(1000);